I want to build a site hosted with Spring Boot and I would like to use AWS SSO as the SAML identity provider for authentication. I have built a PoC application and tried to follow AWS configuration instructions and the Spring SAML examples I could find, but when I browse to my site (on localhost), AWS SSO successfully opens but then fails with "Bad Input".
In my PoC application (which only has code for the authentication and an index page) I have:
spring-security-saml2-service-provider
dependency (Spring Boot v2.6.2)spring:
security:
saml2:
relyingparty:
registration:
metadata:
signing.credentials:
- private-key-location: classpath:key.pem
certificate-location: classpath:cert.pem
identityprovider:
metadata-uri: https://portal.sso.eu-west-1.amazonaws.com/saml/metadata/my-custom-applications-metadata-uri
@Bean
RelyingPartyRegistrationResolver relyingPartyRegistrationResolver(
RelyingPartyRegistrationRepository registrations) {
return new DefaultRelyingPartyRegistrationResolver((id) -> registrations.findByRegistrationId("metadata"));
}
@Bean
FilterRegistrationBean<Saml2MetadataFilter> metadata(RelyingPartyRegistrationResolver registrations) {
Saml2MetadataFilter metadata = new Saml2MetadataFilter(registrations, new OpenSamlMetadataResolver());
FilterRegistrationBean<Saml2MetadataFilter> filter = new FilterRegistrationBean<>(metadata);
filter.setOrder(-101);
return filter;
}
http://localhost:8080/saml2/service-provider-metadata/metadata
) and entered it into the AWS custom application config. This set the ACS to http://localhost:8080/login/saml2/sso/metadata
and audience to http://localhost:8080/saml2/service-provider-metadata/metadata
which seems correct. My Application start URL and Relay States are blank. In the Attributes Mapping I have set Subject
to ${user.email}
with format emailAddress
.I have used the SAML-tracer plugin to try to figure out what happens when I make a request to localhost:8080/
. We end up making a SAML POST (see below) to AWS, AWS reroutes to GET https://portal.sso.eu-west-1.amazonaws.com/token/whoAmI
which succeeds, and then finally reroutes to GET https://portal.sso.eu-west-1.amazonaws.com/saml/v2/assertion/very-long-id
which fails with 400 Bad Request
which lands us on a page in AWS SSO where something went wrong with the message {message: "Bad input", __type: "com.amazonaws.switchboard.portal#InvalidRequestException"}
. I tried checking CloudTrail to find more info but it just logs the events AssumeRoleWithSAML
followed by ConsoleLogin
which both succeed. This is the SAML data as displayed by SAML-tracer which my application POSTs to AWS (replaced info that may be sensitive):
<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
AssertionConsumerServiceURL="http://localhost:8080/login/saml2/sso/metadata"
Destination="https://portal.sso.eu-west-1.amazonaws.com/saml/assertion/insert-long-id"
ID="a-long-id"
IssueInstant="2022-01-10T13:59:52.963Z"
ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Version="2.0"
>
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://localhost:8080/saml2/service-provider-metadata/metadata</saml2:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<ds:Reference URI="#Anot-sure-if-secret-random-characters">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<ds:DigestValue>some-more-characters</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>a-long-base-64-encoded-block-of-characters</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>a-long-encoded-certificate</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
</saml2p:AuthnRequest>
I have tried to find more information on how AWS SSO expects the data to be sent or what "Bad Input" actually means, but it has been really difficult to find. I have also experimented a bit with trying to send the request without signing with my priv key/cert but that didn't seem to get me anywhere. I am suspecting that either the key/cert process is wrong or that I have not set up AWS correctly, but I am not sure how to proceed. Does anyone have any ideas?
The error was that the IdP certificate wasn't added to the spring application.
To do this, download the AWS certificate in AWS SSO when configuring your custom application, then put that certificate at src/main/resources/credentials/idp-certificate.crt
.
Everything worked well after this step, including using localhost
ACS URLs.
I wrote a short tutorial on how to do it at https://maxk.se/posts/aws-sso-spring-boot/