-
Notifications
You must be signed in to change notification settings - Fork 6.2k
Description
After migration from Spring OAuth2 Authorization Server to Spring Security 7.x which now contains it, the prompt=none OIDC parameter does not work as expected.
Support for prompt=none parameter was added in Spring Authorization Server 1.4, see spring-projects/spring-authorization-server#501
In case the user is not authenticated and the parameter is set to none, an OAuth2Error was thrown from OAuth2AuthorizationCodeRequestAuthenticationProvider and handled in OAuth2AuthorizationEndpointFilter by a respective AuthenticationFailureHandler, which by default responded with 301 redirect, if redirect_uri is set.
In Spring Security 7.x OAuth2AuthorizationEndpointFilter is applied after AuthorizationFilter (see #18251). Therefore, if the user is not authenticated, but the security chain requires authorization, the above handling cannot be reached.
To Reproduce
Enable OAuth2 Authentication Server, configure security filter chains similar to the example in the guide. Let's assume a client with ID client and allowed redirect URI /silent-refresh.html is registered and PKCE is not mandatory.
Being unauthenticated, send a request to authorization endpoint with following parameters:
client_id=[client], response_type=[code], scope=[openid], redirect_uri=[/silent-refresh.html], prompt=[none]
Expected behavior
HTTP 30x with redirect to /silent-refresh.html having parameter error=login_required in the redirect URI.
See OIDC Core 1.0.
Actual behavior
Redirect to login form /login, if an authentication entry point was set similar to the guide. Or HTTP 401 in general case.
Sample
Please see the test case in https://github.com/kuzjka/spring-security-7-oidc-prompt
The test passes with Spring Boot 3.5.10 / Spring Authorization Server 1.5.5, see spring_boot_3 branch
Suggestions and reflections
We already have a validation filter, which contains parts of OAuth2 logic and is applied earlier in the chain. I guess, extending it or inserting an additional filter responsible for prompt=none logic will do the thing. I'll try it as a workaround for a sample project.