[cueweb] Add optional group-based authorization gate#2431
[cueweb] Add optional group-based authorization gate#2431ramonfigueiredo wants to merge 4 commits into
Conversation
Add an opt-in, environment-driven authorization layer that can restrict who may use CueWeb and who may reach the CueCommander administration pages, enforced server-side in a single middleware chokepoint. - lib/authz.ts: pure, Edge-safe policy helpers (isAuthzEnabled, isUserAllowed, isUserAdmin, isAdminPath) plus group extraction, all driven by env vars. - middleware.ts: requires a signed-in user when the gate is active, then enforces CUEWEB_ALLOWED_GROUPS app-wide and CUEWEB_ADMIN_GROUPS for the CueCommander admin pages and job submission (CueSubmit). Pages redirect to /unauthorized; API routes return 403. Health, metrics, auth, login, unauthorized and static assets are excluded. - lib/auth.ts: jwt/session callbacks resolve the user's groups once at sign-in (from the configurable OIDC claim or a credentials/LDAP groups field) and stamp them on the token; the Edge middleware only reads them. - app/unauthorized/page.tsx: themed access-denied page. - Env knobs (all optional): CUEWEB_AUTHZ_ENABLED (master switch, opt-in, default off), CUEWEB_ALLOWED_GROUPS, CUEWEB_ADMIN_GROUPS, CUEWEB_GROUPS_CLAIM. Documented in .env.example and README.md.
- Reference: Add Authorization Variables (CUEWEB_AUTHZ_ENABLED, CUEWEB_ALLOWED_GROUPS, CUEWEB_ADMIN_GROUPS, CUEWEB_GROUPS_CLAIM) with defaults and gate behavior - Deploying: Add an Authorization (group-based access control) section with opt-in config and IdP groups-claim requirement - Developer guide: Add an Authorization gate section (sign-in resolution vs Edge enforcement, authz helpers, middleware flow, matcher exclusions) - User guide: Add a short Restricted access note about the Access denied page
📝 WalkthroughWalkthroughAdds an optional group-based authorization gate to CueWeb. A new ChangesCueWeb group-based authorization gate
Sequence Diagram(s)sequenceDiagram
participant Browser
participant middleware as middleware.ts (Edge)
participant NextAuth
participant authz as lib/authz.ts
Note over Browser,NextAuth: Sign-in flow — group extraction
Browser->>NextAuth: sign in
NextAuth->>authz: extractGroups(profile, user)
authz-->>NextAuth: string[] groups
NextAuth->>NextAuth: stamp token.groups, session.groups
Note over Browser,middleware: Subsequent request — enforcement
Browser->>middleware: GET /some/page
middleware->>authz: getUserGroups(token)
authz-->>middleware: string[]
middleware->>authz: isUserAllowed(groups)
alt not allowed
middleware-->>Browser: redirect /unauthorized OR JSON 403
else allowed + isAdminPath
middleware->>authz: isUserAdmin(groups)
alt not admin
middleware-->>Browser: redirect /unauthorized OR JSON 403
else admin
middleware-->>Browser: NextResponse.next()
end
else allowed + not admin path
middleware-->>Browser: NextResponse.next()
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
cueweb/.env.example (1)
15-27: ⚡ Quick winReorder the authz env vars.
dotenv-linterflags this block becauseCUEWEB_ADMIN_GROUPS/CUEWEB_ALLOWED_GROUPSshould sort ahead ofCUEWEB_AUTHZ_ENABLED. Reordering keeps the example file lint-clean.🔧 Suggested reorder
- CUEWEB_AUTHZ_ENABLED=false - CUEWEB_ALLOWED_GROUPS= - CUEWEB_ADMIN_GROUPS= + CUEWEB_ADMIN_GROUPS= + CUEWEB_ALLOWED_GROUPS= + CUEWEB_AUTHZ_ENABLED=false CUEWEB_GROUPS_CLAIM=groups🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@cueweb/.env.example` around lines 15 - 27, The authorization environment variables in the .env.example file are not in alphabetical order, which causes dotenv-linter to flag the configuration. Reorder the four authorization-related variables (CUEWEB_ADMIN_GROUPS, CUEWEB_ALLOWED_GROUPS, CUEWEB_AUTHZ_ENABLED, and CUEWEB_GROUPS_CLAIM) so they appear in strict alphabetical order while keeping their associated comments aligned with each variable definition.Source: Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@cueweb/lib/auth.ts`:
- Around line 173-181: The jwt callback in the jwt function only assigns
token.groups when the extractGroups result has length greater than 0, causing
stale group claims to persist if groups become empty after initial sign-in.
Instead of conditionally assigning token.groups only when groups.length > 0,
always assign token.groups = groups after calling extractGroups, even if the
result is an empty array, to ensure that cleared group membership is reflected
on the token and prevent over-authorization from stale group claims.
In `@cueweb/lib/authz.ts`:
- Around line 96-98: The normalization of array-based group values in the block
where Array.isArray(raw) is checked does not trim whitespace from stringified
values, causing entries like "admins " to fail matching against configured
groups. Modify the map function that converts group values using String(g) to
also apply trim() immediately after stringification, ensuring leading and
trailing whitespace is removed before the filter(Boolean) call validates the
results.
---
Nitpick comments:
In `@cueweb/.env.example`:
- Around line 15-27: The authorization environment variables in the .env.example
file are not in alphabetical order, which causes dotenv-linter to flag the
configuration. Reorder the four authorization-related variables
(CUEWEB_ADMIN_GROUPS, CUEWEB_ALLOWED_GROUPS, CUEWEB_AUTHZ_ENABLED, and
CUEWEB_GROUPS_CLAIM) so they appear in strict alphabetical order while keeping
their associated comments aligned with each variable definition.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 394c0912-7d08-4318-8ee9-668b226e0530
📒 Files selected for processing (10)
cueweb/.env.examplecueweb/README.mdcueweb/app/unauthorized/page.tsxcueweb/lib/auth.tscueweb/lib/authz.tscueweb/middleware.tsdocs/_docs/developer-guide/cueweb-development.mddocs/_docs/getting-started/deploying-cueweb.mddocs/_docs/reference/cueweb.mddocs/_docs/user-guides/cueweb-user-guide.md
- auth.ts: always set token.groups at sign-in (even to []), so a user whose group membership was cleared no longer carries stale memberships - authz.ts: trim array-based group claim values during normalization so entries like "admins " still match configured groups
|
@DiegoTavares / @lithorus |
Related Issues
Main issue:
Issues related to this PR:
Summarize your change.
[cueweb] Add optional group-based authorization gate
Add an opt-in, environment-driven authorization layer that can restrict who may use CueWeb and who may reach the CueCommander administration pages, enforced server-side in a single middleware chokepoint.
[cueweb/docs]: Document the group-based authorization gate
LLM usage disclosure
Parts of this solution's implementation were developed with assistance from Claude Opus.