You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We have a use-case for filtering the scopes that go into an access_token, based on the Resource Owner's "roles" - e.g., if you have the role hr-user you can have payslip.view in the scopes of access tokens issued for you, but not the payslip.edit scope - even if the Client is allowed to request it.
There is no way to easily change the OAuth2Authorization#authorizedScopes() before it is created/saved.
The token itself, when it is a JWT, can be customized with an OAuth2TokenCustomizer<JwtEncodingContext> that acts on the scope claim, but the token response has the full list of authorized scopes.
Expected Behavior
When the OAuth2Authorization object is created and saved in the OAuth2Service, either through OAuth2AuthorizationCodeRequestAuthenticationProvider or OAuth2AuthorizationConsentAuthenticationProvider, I want to be able to alter the scopes.
Current workaround
Currently, we work around this by creating a custom AuthenticationProvider that wraps around both OAuth2AuthorizationCodeRequestAuthenticationProvider and OAuth2AuthorizationConsentAuthenticationProvider:
publicclassAppSsoAuthorizationCodeRequestAuthenticationProviderimplementsAuthenticationProvider {
// Either an OAuth2AuthorizationCodeRequestAuthenticationProvider or an OAuth2AuthorizationConsentAuthenticationProviderprivatefinalAuthenticationProviderdelegate;
privatefinalOAuth2AuthorizationServiceauthorizationService;
publicAppSsoAuthorizationCodeRequestAuthenticationProvider(AuthenticationProviderdelegate,
OAuth2AuthorizationServiceauthorizationService) {
this.delegate = delegate;
this.authorizationService = authorizationService;
}
@OverridepublicAuthenticationauthenticate(Authenticationauthentication) throwsAuthenticationException {
// This may throw an OAuth2AuthorizationCodeRequestAuthenticationException; in// this case we rethrow.varauthResult = delegate.authenticate(authentication);
// This does not happen with our supported cases, but in the case of the device// grant type, OAuth2AuthorizationConsentAuthenticationProvider will return null.if (authResult == null) {
returnnull;
}
// When an authorization request comes in, and is valid, BUT the user is not// authenticated, an OAuth2AuthorizationCodeRequestAuthenticationToken is// returned, that is marked as !authenticated. This is a special case signaling// that the end-user must log-in first. In this case, we just follow through.//// The rest of the filter chain will save the incoming request in the session and// redirect the user to the login page. Once they are logged in, the saved request// will be replayed.if (!authResult.isAuthenticated()) {
returnauthResult;
}
// Sometimes the authentication flow returns a// OAuth2AuthorizationConsentAuthenticationToken when consent is required.// In that case, we just follow through. Otherwise we grab the result.if (!(authResultinstanceofOAuth2AuthorizationCodeRequestAuthenticationTokenauthCodeAuthResult)) {
returnauthResult;
}
// We load the authorization from the repo, change the scopes, and re-save it.varauthCode = authCodeAuthResult.getAuthorizationCode();
varauthorization = authorizationService.findByToken(authCode.getTokenValue(),
newOAuth2TokenType(OAuth2ParameterNames.CODE));
// Filter the scopes based on the principalvarfilteredScopes = filterScopes(authorization.getAuthorizedScopes(), authResult.getPrincipal());
varnewAuthorization = OAuth2Authorization.from(authorization).authorizedScopes(filteredScopes).build();
authorizationService.save(newAuthorization);
//@formatter:offreturnnewOAuth2AuthorizationCodeRequestAuthenticationToken(
authCodeAuthResult.getAuthorizationUri(),
authCodeAuthResult.getClientId(),
authResultPrincipalAuthentication,
authCodeAuthResult.getAuthorizationCode(),
authCodeAuthResult.getRedirectUri(),
authCodeAuthResult.getState(),
filteredScopes
);
//@formatter:on
}
@Overridepublicbooleansupports(Class<?> authentication) {
returndelegate.supports(authentication);
}
privateSet<String> filterScopes(Set<String> authorizedScopes, Objectprincipal) {
// business logic
}
}
The text was updated successfully, but these errors were encountered:
@Suvink excellent question, this is a classic pattern, but not 100% obvious. You register it with the AuthorizationServerConfigurer using an object post-processor. In your security configuration:
Perfect. Initially we tried to register this with web security config but it didn't work. Then registered it with auth server configs and it works perfectly fine.
Thanks a lot for the support!
Context
We have a use-case for filtering the scopes that go into an
access_token
, based on the Resource Owner's "roles" - e.g., if you have the rolehr-user
you can havepayslip.view
in the scopes of access tokens issued for you, but not thepayslip.edit
scope - even if the Client is allowed to request it.There is no way to easily change the
OAuth2Authorization#authorizedScopes()
before it is created/saved.The token itself, when it is a JWT, can be customized with an
OAuth2TokenCustomizer<JwtEncodingContext>
that acts on the scope claim, but the token response has the full list of authorized scopes.Expected Behavior
When the
OAuth2Authorization
object is created and saved in theOAuth2Service
, either throughOAuth2AuthorizationCodeRequestAuthenticationProvider
orOAuth2AuthorizationConsentAuthenticationProvider
, I want to be able to alter the scopes.Current workaround
Currently, we work around this by creating a custom
AuthenticationProvider
that wraps around bothOAuth2AuthorizationCodeRequestAuthenticationProvider
andOAuth2AuthorizationConsentAuthenticationProvider
:The text was updated successfully, but these errors were encountered: