spring-projects / spring-authorization-server

Spring Authorization Server
https://spring.io/projects/spring-authorization-server
Apache License 2.0
4.86k stars 1.29k forks source link

Customize `post_logout_redirect_uri` validation in OIDC RP-initiated logout #1693

Closed Kehrlann closed 1 month ago

Kehrlann commented 2 months ago

Context

In local development scenarios, some auth servers relax some specified constraints. For example, in Tanzu, we have use-cases where we remove redirect_uri validation in OAuth2AuthorizationCodeRequestAuthenticationProvider through the OAuth2AuthorizationCoderRequestAuthenticationProvider#setAuthenticationValidator hook.

Feature request

We want to turn off post_logout_redirect_uri validation in OidcLogoutAuthenticationProvider, but it is currently hardcoded.

We would like to have a similar #setAuthenticationValidator in OidcLogoutAuthenticationProvider. We are interested in the redirect uri validation, but maybe this extends to the client identity (e.g. aud claim).

Workaround

For our workaround, we have custom OidcLogoutAuthenticationProvider that wraps around the original, and modifies the client registration (not great). We rely on our custom RegisteredClientRepository and RegisteredClient implementations:

class SsoOidcLogoutAuthenticationProvider implements AuthenticationProvider {

    private final OidcLogoutAuthenticationProvider delegate;

    private final OAuth2AuthorizationService authorizationService;

    private final SsoRegisteredClientRepository registeredClientRepository;

    public SsoOidcLogoutAuthenticationProvider(OidcLogoutAuthenticationProvider delegate,
            OAuth2AuthorizationService authorizationService, SsoRegisteredClientRepository registeredClientRepository) {
        this.delegate = delegate;
        this.authorizationService = authorizationService;
        this.registeredClientRepository = registeredClientRepository;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        OidcLogoutAuthenticationToken initialAuth = (OidcLogoutAuthenticationToken) authentication;

        OAuth2Authorization authorization = this.authorizationService.findByToken(initialAuth.getIdTokenHint(),
                new OAuth2TokenType(OidcParameterNames.ID_TOKEN));
        // ... handle error
        SsoRegisteredClient registeredClient = this.registeredClientRepository
            .findById(authorization.getRegisteredClientId());
        // ... handle missing redirect_uri

        // 🚨 Here we modify the registered client to add the current request's
        // post logout redirect uri to the allow-list
        registeredClient.addPostLogoutUri(initialAuth.getPostLogoutRedirectUri());

        return this.delegate.authenticate(initialAuth);
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return this.delegate.supports(authentication);
    }

}

Happy to contribute a PR if that's a valid use-case.

jgrandja commented 2 months ago

@Kehrlann Thanks for the details and we can certainly add this enhancement. Would you be interested in submitting a PR that adds OidcLogoutAuthenticationProvider.setAuthenticationValidator()?

Kehrlann commented 2 months ago

@jgrandja Yes, happy to submit a PR. I’ll look at it next week.