Integrating AWS SSO with Auth0

John Wheeler
6 min readJul 18, 2021

Every SSO integration presents a new set of challenges as you connect technologies based on standards that can have different implementations for each vendor. Often you can apply design patterns previously used and follow best practice and vendor documentation to enable your use case and minimize or reduce user friction.

I wanted to integrate Auth0 (as the IdP) with AWS SSO (as the SP) and my primary goal was to use Topcoder handles as the nameIdentifier. Topcoder requires users to select a unique handle or id during the account registration process that is immutable where as the email that a handle is tied to can change. My goal was to use this immutable attribute as the foreign key or NameID into AWS SSO. Provisioning users in AWS requires a similar immutable value for the Username.

Reviewing the requirements for SSO on AWS using a separate IDP

AWS SSO requires a SAML nameID format of email address (that is, urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress)

This and the following on the same page

The value of the nameID field in assertions must be an RFC 2822 (https://tools.ietf.org/html/rfc2822) addr-spec compliant (“name@domain.com”) string (https://tools.ietf.org/html/rfc2822#section-3.4.1)

led me to believe that the NameID would have to be an email address.

Looking at how AWS manages SSO users and groups

AWS SSO implements a user name that is the primary identifier for your users. Although most people set the user name equal to a user’s email address, AWS SSO and the SAML standard do not require this.

This seems a bit contradictory. I decided to see if AWS would allow a non addre-spec compliant NameID.

Auth0 Setup

Start by creating an application in Auth0. I called my application AWS SSO and selected Regular Web Application.

Client application in Auth0

Let’s get the required X.509 certificate for AWS and continue configuring there. Scroll to the bottom of the application look under the Advanced Settings, Certificates.

PEM certificate from Auth0 application

Auth0 provides three options for the certificate format. AWS doesn’t document the format they require, but does indicate the file type needed when you attempt to upload the certificate, a PEM file.

We’ll need to come back to Auth0 but lets grab some data that’s needed in AWS before we leave. Still in the Advanced Settings section, select Endpoints . The tab has three sections OAuth, SAML, and WS-Federtion. Under the SAML section, grab the URL SAML Protocol URL similar to the one below.

https://topcoder.auth0.com/samlp/JEdcxesyouareawizardharryYhUjjHgYyQ

AWS SSO Setup

Let’s move to AWS now and configure SSO. Login the console and follow the initial step to enable SSO.

  1. Sign in to the AWSManagement Console with your AWS Organizations management account credentials.
  2. Open the AWS SSO console.
  3. Choose Enable AWS SSO.

Once enabled, AWS SSO creates a service-linked role in all accounts within the organization in AWS Organizations. AWS SSO also creates the same service-linked role in every account that is subsequently added to your organization. This role allows AWS SSO to access each account’s resources on your behalf.

After you have enabled SSO, you should see a screen similar to this

Select Settings and under Identity source -> Authentication click View details. At the bottom of the page we can upload our certificate. Click Manage certificates then Import certificate

Locate the file you downloaded from Auth0 and click Import certificate. Once the certificate is uploaded you should be able to see some meta data extracted from it including the Common Name (CN), created, and expires date.

Certificate Upload

Click on the bread crumb SAML 2.0 authentication at the top to return the previous page, then click Edit identity provider metadata

Fill in the URL from Auth0 in the step above and provide the IdP issuer URL. Your URL may be different if you’ve set a custom domain. Also fill in the IdP issuer URL if it’s different. This should be completed when you upload the certificate above. Save any changes.

This is the last of the configuration on the AWS side. We need to collect a few bits of information and go back to Auth0. On the settings pages, grab the AWS SSO ACS URL and the AWS SSO issuer URL.

AWS SAML configuration

Auth0 configuration continued

Take the AWS SSO ACS URL and put this in the Allowed Callbak URL'son

Select Addons and you should see something similar to this.

Client Addons

Select the SAML2 WEB APP. This is where we’ll customize the SAML assertion back to AWS. The dialog has two tabs and starts on the Usage tab. Select the Settings tab and update the Application Callback URL with the AWS SSO ACS URL and the Settings section with the following

{
“destination”: “https://us-east-1.signin.aws.amazon.com/platform/saml/acs/yoururl",
“mappings”: {
“email”: “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
“nickname”: “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"
},
“createUpnClaim”: false,
“passthroughClaimsWithNoMapping”: false,
“mapUnknownClaimsAsIs”: false,
“mapIdentities”: false,
“nameIdentifierFormat”: “urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress”,
“nameIdentifierProbes”: [
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"
]
}

After some trial and error, I came up with the config above. This article helped with some of the values. Topcoder assigns the users handle to the “nickname” in the Auth0 profile. In the mappings section, you can see that I’ve mapped nickname to the nameidentifier.

mappings (object): The mappings between the Auth0 user profile and the output attributes on the SAML Assertion. Each “name” (left side) represents the property name on the Auth0 user profile. Each “value” (right side) is the name (including namespace) for the resulting SAML attribute in the assertion. Default mapping is shown above.

Save the config above and click Debug button to test with AWS. Below is a portion of a valid SAML assertion sent to AWS. I was able to send the handle attribute to to AWS SSO as the nameIdentifier.

<samlp:Response xmlns:samlp=”urn:oasis:names:tc:SAML:2.0:protocol” ID=”_debb5ec504e6db472282" Version=”2.0" IssueInstant=”2021–07–18T19:04:15.999Z” Destination=”https://us-east-1.signin.aws.amazon.com/platform/saml/acs/youracsurl">
<saml:Issuer xmlns:saml=”urn:oasis:names:tc:SAML:2.0:assertion”>urn:topcoder.auth0.com</saml:Issuer>
<samlp:Status>
<samlp:StatusCode Value=”urn:oasis:names:tc:SAML:2.0:status:Success”/>
</samlp:Status>
<saml:Assertion xmlns:saml=”urn:oasis:names:tc:SAML:2.0:assertion” Version=”2.0" ID=”_OrtI6i75xMNyUftxqac4pnEGUVjjJLDr” IssueInstant=”2021–07–18T19:04:15.978Z”>
<saml:Issuer>urn:topcoder.auth0.com</saml:Issuer>
-------------------------SNIP--------------------
<saml:Subject>
<saml:NameID Format=”urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress”>jswheeler</saml:NameID>
<saml:SubjectConfirmation Method=”urn:oasis:names:tc:SAML:2.0:cm:bearer”>
<saml:SubjectConfirmationData NotOnOrAfter=”2021–07–18T20:04:15.978Z” Recipient=”https://manage.auth0.com/tester/samlp”/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore=”2021–07–18T19:04:15.978Z” NotOnOrAfter=”2021–07–18T20:04:15.978Z”>
<saml:AudienceRestriction>
<saml:Audience>https://us-east-1.signin.aws.amazon.com/platform/saml/d-906762d05b</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant=”2021–07–18T19:04:15.978Z” SessionIndex=”_xsEJ6N9g8_avO8b1exwpBx1DV0-DDieD”>
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement xmlns:xs=”http://www.w3.org/2001/XMLSchema” xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<saml:Attribute Name=”http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" NameFormat=”urn:oasis:names:tc:SAML:2.0:attrname-format:uri”>
<saml:AttributeValue xsi:type=”xs:string”>jwheeler@topcoder.com</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name=”http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" NameFormat=”urn:oasis:names:tc:SAML:2.0:attrname-format:uri”>
<saml:AttributeValue xsi:type=”xs:string”>jswheeler</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>

Provisioning user in AWS SSO.

Auth0 doesn’t support SCIM so I’m not able to auto provision users. This isn’t too onerous as we don’t have a lot of users with this access. With this change I can add the user with their topcoder handle, so the the Username is not the users email but the handle they’ve chosen on the Topcoder platform.

Thoughts

I was able to piece this configuration based on what I could find in the AWS docs linked in this article and reviewing several of the setups that Auth0 listed as well as the manual configuration here. Where I spent most of my trouble shooting time was trying to understand AWS errors from the SAML assertion. I think there documentation does cover a lot of this, but it’s in a few different places. Hopefully this helps others.

--

--

John Wheeler

Security professional, Mac enthusiast, writing code when I have to.