feat: JWT role extractor for RBAC without interactive OAuth#1840
Draft
lrudolph333 wants to merge 4 commits into
Draft
feat: JWT role extractor for RBAC without interactive OAuth#1840lrudolph333 wants to merge 4 commits into
lrudolph333 wants to merge 4 commits into
Conversation
When kafbat is configured with oauth2ResourceServer to validate bearer JWTs, the RBAC authority extractors were not invoked, causing JWT- authenticated requests to bypass role-based access control entirely. This adds a configurable ReactiveJwtAuthenticationConverter that extracts roles and username from JWT claims, matches them against configured RBAC role subjects (provider=OAUTH), and produces an authentication token whose principal implements RbacUser — making the existing RBAC enforcement work seamlessly for bearer token requests. Configuration: auth.oauth2.resource-server-rbac.roles-claim: "ter" auth.oauth2.resource-server-rbac.username-claim: "tei" Closes: kafbat#1828 Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
|
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:
✨ 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 |
… default role Support IdPs like Slack Toolbelt where roles live in custom claims (e.g. `ter`) rather than standard `sub`. Adds: - `entity-type-claim` config for coarse-grained access by token type (e.g. all `nebula` service tokens get a `service` RBAC role) - `default-role` fallback when no subject mapping matches - New subject type `entity-type` for RBAC role definitions Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
…ations When auth.type=OAUTH2 is set but no OAuth2 client providers are configured, the app previously threw "OAuth2 authentication is enabled but no providers specified." This change makes interactive login beans (client registration repository, token response client, user services, logout handler) conditional on having client registrations, allowing kafbat to run purely as an OAuth2 resource server validating bearer JWTs. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
…server-only mode Spring Security's ReactiveOAuth2ClientConfiguration requires a ReactiveClientRegistrationRepository bean to exist even when no OAuth2 client login flow is configured. Returning null caused NoSuchBeanDefinitionException. Instead, provide a no-op lambda implementation that returns Mono.empty() for any registration lookup. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Resolves #1828
When kafbat is configured with
oauth2ResourceServerto validate bearer JWTs, the RBAC authority extractors do not run — JWT-authenticated requests bypass role-based access control entirely because Spring Security's defaultJwtAuthenticationTokenprincipal is aJwtobject, not anRbacUser.This PR adds a configurable
ReactiveJwtAuthenticationConverterthat:sub)provider: oauth,type: user/role)RbacJwtAuthenticationTokenwhose principal implementsRbacUser, making existing RBAC enforcement work seamlessly for bearer token requestsConfiguration
RBAC role definitions work unchanged:
Changes
OAuthProperties.java— AddedResourceServerRbacconfig class withrolesClaim/usernameClaimRbacJwtUser.java— New record implementingRbacUserfor JWT principalsRbacJwtAuthenticationToken.java— CustomAbstractAuthenticationTokenwithRbacJwtUserprincipalRbacReactiveJwtAuthenticationConverter.java— Converter wiring JWT claims → RBAC role matchingOAuthSecurityConfig.java— Wires converter into resource server JWT path when config is presentBackward Compatibility
resource-server-rbacis not configured, behavior is completely unchanged (no converter installed)oauth2Loginflow and all provider-specific extractors are unaffectedprovider: oauthsubjects work for both login and resource server pathsTest plan
RbacReactiveJwtAuthenticationConverterTest— 10 cases covering role lists, comma-separated strings, username matching,subfallback, empty groups, regex subjectsJwtResourceServerRbacTest— 6 cases using WireMock JWKS + RSA-signed JWTs verifying end-to-end decode → role extraction → principal creation🤖 Generated with Claude Code