spring-authorization-server
spring-authorization-server copied to clipboard
Provide more flexibility on when to display consent page
Expected Behavior
When logging in via OAuth 2.1 dance, the consent is only requested once. For more security/compliance-sensitive applications, it would be nice to have a simple way to enforce the consent screen on every login so that the consent is re-granted.
We would like to be able to configure, i.e.:
final RegisteredClient oidcClient = RegisteredClient.withId(UUID.randomUUID().toString())
// ...
// Consent.ALWAYS / Consent.ONCE / Consent.NEVER
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(Consent.ALWAYS).build())
.build();
Current Behavior
Once consent is granted to given scopes, the consent screen is not shown.
We are able to configure:
final RegisteredClient oidcClient = RegisteredClient.withId(UUID.randomUUID().toString())
// ...
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
.build();
Context
We are mostly trying to have a consistent user flow, where the sequence of screens is the same for each login. The additional reason is that we would like the user to re-confirm the consent granted to the third-party app.
Related gh-1363
I've been eager to contribute for some time now and this looks like something I can tackle.
@jgrandja If this is something that you want to support, I will gladly work on it.
@petrdvorak
When logging in via OAuth 2.1 dance, the consent is only requested once. For more security/compliance-sensitive applications, it would be nice to have a simple way to enforce the consent screen on every login so that the consent is re-granted.
I believe you are looking for support for the OIDC parameter prompt=consent
. Please see this comment. Can you confirm?
Do you also need similar support for the standard OAuth 2.0 authorization_code
grant flow? Or you just need it for OIDC (login) flow?
Thank you for your interest in contributing @MrJovanovic13.
I will reach out to you as soon as we figure out the scope of work and have it scheduled for a release 👍
@jgrandja This does not seem to be what I am looking for, as this seems to be the client-side control only. (... or, am I missing how this could actually ensure the consent was granted again? Removing the parameter would skip the consent screen, so I do not see why this is even in the specification...)
The intended behavior is more flexibility on when to display consent. With the old Spring OAuth 2.0 support, we actually used to have a fully dynamic configuration of when the consent form is shown based on our custom logic. Therefore, we were able to do things such as:
@Override
public InitConsentFormResponse initConsentForm(String userId, String organizationId, OperationContext operationContext) {
final ApplicationContext applicationContext = operationContext.getApplicationContext();
final String clientId = applicationContext.getId();
final String operationName = operationContext.getName();
// Consent is always required for login_sca operation
if ("login_sca".equals(operationName)) {
return new InitConsentFormResponse(true);
}
final List<String> requestedScopes = applicationContext.getOriginalScopes();
final String consentId;
if (requestedScopes.contains("aisp")) {
consentId = "aisp";
} else if (requestedScopes.contains("pisp")) {
consentId = "pisp";
} else {
consentId = "profile";
}
final boolean consentActive = isConsentActive(userId, consentId, clientId, consentExpirationTimestamp);
return new InitConsentFormResponse(!consentActive);
}
... so, always require consent for login, and sometimes - i.e., every 180 days - for other operations, such as payment or XS2A (access to an account).
@petrdvorak Thanks for the code sample.
It looks like you need a hook into OAuth2AuthorizationCodeRequestAuthenticationProvider.requireAuthorizationConsent()
(and access to OAuth2AuthorizationCodeRequestAuthenticationToken
) so you can evaluate at runtime?
@jgrandja Yes, this would be ideal.
nice addition.
@petrdvorak Looks like this customization capability will be useful for our users. We'll look at adding an enhancement as per comment.
@MrJovanovic13 We now know the scope of work as per comment. Let me know if this is still something you would like to take on.
@jgrandja Yes, I would still like to take this on.
@MrJovanovic13 Great, I've assigned it to you.
I think what we need to add is something along the lines of:
OAuth2AuthorizationCodeRequestAuthenticationProvider.setRequiresAuthorizationConsent(Predicate<OAuth2AuthorizationCodeRequestAuthenticationContext> requiresAuthorizationConsent)
This pattern is used in the following implementations:
OAuth2AuthorizationCodeRequestAuthenticationProvider.setAuthenticationValidator()
OAuth2AuthorizationConsentAuthenticationProvider.setAuthorizationConsentCustomizer()
OidcUserInfoAuthenticationProvider.setUserInfoMapper()
OAuth2ClientCredentialsAuthenticationProvider.setAuthenticationValidator()
Please review those implementations to become familiar with the pattern as I believe the same pattern will work here as well.
Thanks!