-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Description
Expected Behavior
When sending additional parameters from a consent-form, these additional parameters should by accessable by User-Code.
The OAuth2AuthorizationConsent should be customizable by a user-definable component before being passed to the OAuth2AuthorizationService.
Current Behavior
When sending additional parameters from a consent-form, these additional parameters are present inside the OAuth2AuthorizationCodeRequestAuthenticationToken.
The OAuth2AuthorizationConsent is created only using the authorized scopes.
Context
In my OAuth2-Server, a user can create multiple entities.
On the consent-page, the user can review all requested scopes and select which of its entities the client should be given access to.
My consent-page HTML looks like this:
<form method="post" th:action="@{/oauth2/authorize}">
<input type="hidden" name="client_id" th:value="${clientId}" />
<input type="hidden" name="state" th:value="${state}" />
<div th:each="entity : ${entities}">
<p>
<input type="checkbox" th:name="${'entity:' + entity.id}" th:text="${entity.displayName}" checked />
</p>
</div>
<hr />
<div th:each="scope : ${scopes}">
<input type="hidden" name="scope" th:value="${scope}" />
<p th:text="${scope}"></p>
</div>
<button type="submit">Submit</button>
<!--<button type="reset">Cancel</button>-->
</form>
I need some way to know which entities have been selected by the user on the consent-page.
In my case, all selected entity-ids are present in the OAuth2AuthorizationCodeRequestAuthenticationToken.getAdditionalParameters(), but these are never passed to any User-Code.
Ideally, I'd like to customize the OAuth2AuthorizationConsent before it's being passed to the OAuth2AuthorizationService with access to the additional parameters.
As a workaround, I currently use a custom OAuth2AuthorizationCodeRequestAuthenticationProvider:
private static final ThreadLocal<Map<String, Object>> ADDITIONAL_PARAMETERS = new ThreadLocal<>();
public CustomOAuth2AuthorizationCodeRequestAuthenticationProvider(RegisteredClientRepository registeredClientRepository, OAuth2AuthorizationService authorizationService, OAuth2AuthorizationConsentService authorizationConsentService) {
super(registeredClientRepository, authorizationService, authorizationConsentService);
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
final OAuth2AuthorizationCodeRequestAuthenticationToken authorizationCodeRequestAuthentication = (OAuth2AuthorizationCodeRequestAuthenticationToken) authentication;
final Map<String, Object> additionalParameters = authorizationCodeRequestAuthentication.getAdditionalParameters();
ADDITIONAL_PARAMETERS.set(additionalParameters);
try {
return super.authenticate(authorizationCodeRequestAuthentication);
} finally {
ADDITIONAL_PARAMETERS.remove();
}
}
public static <T> T getAdditionalParameter(String key) {
final Map<String, Object> additionalParameters = ADDITIONAL_PARAMETERS.get();
if (additionalParameters == null) {
throw new IllegalStateException();
}
return (T) additionalParameters.get(key);
}
Side Nodes
The additionalParameters are currently created by passing all Request-Parameters that are not explicitly known (such as scope, client_id and state), but only the first value is actually added to the additionalParameters.
This requires my consent-page to send each selected entity using a different name (like in the example HTML above).
Ideally, I would like to use one name (for example "entity") and send the selected entities with their id as a value (like it works with scope at the moment).