feat(jwt): accept LFX v2 API audience for user JWT verification - #67
feat(jwt): accept LFX v2 API audience for user JWT verification#67mlehotskylf wants to merge 3 commits into
Conversation
User-facing access tokens and impersonation tokens carry the LFX v2 API audience, not the Auth0 Management API audience, so MetadataLookup's JWT path rejected them with 'invalid audience' (verified in dev). Accept the audience from AUTH0_LFX_V2_API_AUDIENCE as an additional valid audience. Tokens verified via a non-management audience are never forwarded to the Auth0 Management API: user.Token stays empty so read lookups fall back to the service's M2M credentials, while write flows (which require the user's own management-scoped token) fail closed. Also validate the audience against all 'aud' values of the token rather than only the first one. Needed for SS 'My CLAs' identity resolution per linuxfoundation/lfx-self-serve#1216 (condition 1). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
There was a problem hiding this comment.
Pull request overview
Adds LFX v2 API audience support for read-only JWT identity lookups while retaining Management API token handling.
Changes:
- Supports multiple allowed and token audiences.
- Uses M2M credentials for non-management-audience reads.
- Adds audience validation and token-retention tests.
A security issue remains: the expanded audience policy also applies to write authorization paths.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
pkg/jwt/parser.go |
Adds multi-audience parsing and validation. |
pkg/jwt/parser_test.go |
Tests audience allow-lists and multi-audience tokens. |
internal/infrastructure/auth0/user.go |
Retains only Management API tokens for lookups. |
internal/infrastructure/auth0/user_test.go |
Tests audience-based token retention. |
internal/infrastructure/auth0/jwt_parser.go |
Configures the LFX v2 audience allow-list. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Scope-gated JWTVerify calls back the write-authorizing paths (ChangePassword, SetPrimaryEmail, add_alias). The expanded audience allow-list accepts the LFX v2 API audience for read-only lookups, but required scopes are Auth0 Management API scopes and only meaningful on Management-audience tokens. Clear ExpectedAudiences when a required scope is present so a broader-audience token carrying an identically named scope can never authorize a write. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Why
Per the approved decision on linuxfoundation/lfx-self-serve#1216 (condition 1), LFX Self Serve must build the "My CLAs" identity list server-side via the
lfx.auth-service.user_identity.listNATS RPC, passing the session user's own access token so the auth service verifies the JWT and extractssubfrom verified claims.That flow doesn't work today — verified empirically in dev:
{"success":false,"error":"invalid audience"}.MetadataLookupstores the verified JWT asuser.Token, whichGetUser/SearchUserthen reuse as the bearer for Auth0 Management API calls — where Auth0 itself would reject a non-management-audience token.Details and evidence: linuxfoundation/lfx-self-serve#1216 (comment)
What
NewJWTVerificationConfigbuilds an audience allow-list: the Management API audience plus, whenAUTH0_LFX_V2_API_AUDIENCEis set (it already is in all deployments, for impersonation), that audience too.MetadataLookup,user.Tokenis populated only when the verified token carries the Management API audience. Otherwise the verifiedsubis used with the service's own M2M credentials (read:users) for read lookups, and write flows fail closed:LinkIdentityToUser/UnlinkIdentityFromUserreject an empty user token and never use M2M credentials (existing behavior).UpdateUserre-verifiesuser.Tokenitself with the update scope (existing behavior).audvalues, not just the first — Auth0 access tokens commonly carry[api-audience, …/userinfo].No behavior change for existing callers: all other services pass usernames/emails/subs (non-JWT path, untouched), and currently-accepted management-audience JWTs (SS Flow C profile tokens) verify and forward exactly as before.
Security note for reviewers
Accepting the LFX v2 API audience widens who can pass JWT verification on read subjects, but the response is always scoped to the token's own verified
sub, reads go through the same M2M credentials already used for the non-JWT lookup paths, and write subjects still require the user's own management-scoped token. Please double-check the read/write split holds in your review.cc @emsearcy — this implements condition 1 of your linuxfoundation/lfx-self-serve#1216 recommendation; flagging in case you intended a different token for SS to pass.
Testing
ExpectedAudiences), multi-audtokens, andMetadataLookuptoken retention (management kept / LFX v2 verified-but-not-forwarded / unknown audience rejected).go test ./...,gofmt,go vetall clean.🤖 Generated with Claude Code