With the deprecated Saml2AuthenticationRequestContext it was possible to set a custom RelayState, but with the new OpenSamlAuthenticationRequestResolver it is always initialized to:
String relayState = UUID.randomUUID().toString();
I don't see a way to overcome this without implementing my own AuthenticationRequestResolver, is there a reason for this?
Comment From: jzheaux
Hi, @exeba. The purpose of deprecating the other classes was to simplify the API to a single interface. So, to have a custom relay state, you create a custom resolver that delegates like so:
@Bean
Saml2AuthenticationRequestResolver authenticationRequestResolver(
RelyingPartyRegistrationResolver registrations) {
OpenSaml4AuthenticationRequestResolver authenticationRequests =
new OpenSaml4AuthenticationRequestResolver(registrations);
return (request) -> {
Saml2PostAuthenticationRequest post = authenticationRequests.resolve(request);
RelyingPartyRegistration registration = registrations.resolve(request, "registration-id");
String relayState = resolveCustomRelayState(request);
return Saml2PostAuthenticationRequest.withRelyingPartyRegistration(registration)
.samlRequest(post.getSamlRequest())
.authenticationRequestUri(post.getAuthenticationRequestUri())
.relayState(relayState)
.build();
}
}
That said, I think this can be simplified. For example, it would be nicer to not have to waste the CPU on generating a relay state if the app is going to override it. To that end, I think we should add a setRelayStateResolver(Converter<HttpServletRequest, String> relayStateResolver) method. The default value would be one that randomly generates the relay state.
The resulting configuration would then instead be:
@Bean
Saml2AuthenticationRequestResolver authenticationRequestResolver(
RelyingPartyRegistrationResolver registrations) {
OpenSaml4AuthenticationRequestResolver authenticationRequests =
new OpenSaml4AuthenticationRequestResolver(registrations);
authenticationRequests.setRelayStateResolver(this::resolveCustomRelayState);
return authenticationRequests;
}
Would this address your concern and, if so, are you able to submit a PR that adds the setter?
Comment From: Martin-Office
Hi @jzheaux, Your bean proposition to set custom relayState look interesting but sadly there is no bean RelyingPartyRegistrationResolver registrations for autowiring. How can I use the instance created by the framework?
In my configuration I only do this:
http.saml2Login(saml -> saml.successHandler(new Saml2AuthenticationSuccessHandler()))
I though of creating a bean with DefaultRelyingPartyRegistrationResolver but this one needs RelyingPartyRegistrationRepository which needs RelyingPartyRegistration(s). I feel like I need to rebuild everything to only set a simple resolver...
Maybe I do not understand how the framework is wired or how to use existing setup with my beans.
In fact how can I create a bean that uses instances that are created after the HttpSecurity build the SecurityFilterChain.
Comment From: Martin-Office
Ok I can use autowiring of Saml2RelyingPartyProperties to avoid hardcoding the configuration...
@Bean
public RelyingPartyRegistrationRepository relyingPartyRegistrations(
Saml2RelyingPartyProperties relyingPartyProperties) {
then it become managable....