I have a Java back end application running behind Nginx and spring security for SSO .My back end app lacks a mechanism to remember cookie sessions because of which SSO request could be initiated by one java instance and assertion might reach to other instance . The existing default implementation requires the validation of the InResponseTo
attribute if it's present. The default implementation is based on http session which keep tracks of session via cookies.The purpose of keeping cookie is to remember id attribute and later match with InResponseTo
to protect from replay attack. InResponseTo
is optional atribute in SAML2.0 spec. I want to know if there's a way to disable the InResponseTo
validation while still utilizing the default validation provided by OpenSaml4AuthenticationProvider
. Notably, SAML2 considers the 'InResponseTo' attribute optional. What is the best method to maintain default validation but bypass InResponseTo
through back end configuration settings?
My application basic configuration looks like below .
@Configuration
public class ApplicationConfiguration {
@Autowired
SamlSuccessHandler successHandler;
@Bean
SecurityFilterChain configure(HttpSecurity http) throws Exception {
return http.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
).saml2Login(saml2->{
saml2.loginProcessingUrl("/saml/SSO")
.successHandler(successHandler);
}).build();
}
}
application.yml
spring:
security:
saml2:
relyingparty:
registration:
sap-account400:
entity-id: my_entity_id
identityprovider:
entity-id: https://my-service.com
singlesignon.sign-request: true
assertingparty:
metadata-uri: https://okta.com/1234
decryption:
credentials:
- private-key-location: classpath:private_key_encryption.pem
certificate-location: classpath:certificate_encryption.crt
signing:
credentials:
- private-key-location: classpath:private_key.pem
certificate-location: classpath:certificate.crt
acs:
location: http://localhost:8080/saml/SSO
To disable the InResponseTo
validation, you will need to customize OpenSaml4AuthenticationProvider
. By default, it validates the status code, the InResponseTo
attribute, the Destination
attribute, and the Issuer
attribute.
The simplest way to do this is to remove the InResponseTo
validation result like so:
@Component
final class ResponseValidator implements Converter<Response, Saml2ResponseValidatorResult> {
private final Converter<ResponseToken, Saml2ResponseValidatorResult> delegate = OpenSaml4AuthenticationProvider.createDefaultResponseValidator();
@Override
public Saml2ResponseValidatorResult convert(ResponseToken response) {
Saml2ResponseValidatorResult result = this.delegate.convert(response);
Collection<Saml2Error> errors = result.getErrors().stream()
.filter((error) -> !error.getErrorCode().equals(INVALID_IN_RESPONSE_TO))
.collect(Collectors.toList());
return Saml2ResponseValidatorResult.failure(errors);
}
}
...
@Bean
AuthenticationProvider authenticationProvider(ResponseValidator validator) {
OpenSaml4AuthenticationProvider authenticationProvider =
new OpenSaml4AuthenticationProvider();
authenticationProvider.setResponseValidator(validator);
return authenticationProvider;
}
However, I'd recommend that you first try and configure your IdP to not include information that you do not intend to validate.
Instead of disabling validation, consider storing the requests in some other shared storage (e.g. a cache) on the backend. You can customize Saml2AuthenticationRequestsRepository
with relative ease to this end. To be fully SAML 2.0 compliant, a form of caching is already needed (see line 602).