How to Map SAML Attributes when Auth0 is the IDP in the SAML2 Addon

Problem Statement

There is a SAML Mappings misconfiguration in the Application’s SAML2 Addon.

Symptoms

Attribute misconfiguration can result in a number of unexpected behaviors. The following is not an exhaustive list:

  • User enters username and password successfully, but fails to sign in to the application. The Logs and Users pages in the Auth0 Dashboard show successful login events.
  • Application is missing critical information about the user (e.g. name or email)

Troubleshooting

In the event that you encounter the scenario where the user successfully logs in with the IDP, a successful login event shows up in the Auth0 logs, but the application rejects ther sign-in attempt or the user’s profile attributes are incorrect.

The next step is to check that the user’s profile contains the necessary user profile attributes.

  1. Navigate to your Auth0 Dashboard > User Management > Users.

  2. Find and click on the specific user to open up their profile. If there are multiple rows for a given user, be sure to open up the record associated with the correct connection.

  3. On the user’s profile, you can view their details in one of two ways. You can use the Details tab or the Raw JSON tab. This shows you what attributes Auth0 has received from the Identity Provider. If an attribute is missing, check with the Identity Provider to confirm that it has the attribute and that it is returning that attribute to Auth0.

Relevant Docs

Cause

The SAML attributes are incorrectly mapped or not mapped at all.

Solution

The solution is to map the SAML attributes to the correct property when Auth0 is the Identity Provider (IdP).

When Auth0 is the IdP there are two ways to map attributes, namely through the SAML2 Addon (preferred), and Rules.

SAML2 Addon Settings:
You can configure the SAML2 Addon settings by navigating to your Auth0 Dashboard > Applications > Application with SAML2 Addon > Addons > SAML2 > Web App > Settings.

IMPORTANT: Note that the mappings object in the SAML2 Addon can only work with root-level profile attributes.

Please review the sample IdP user profile and relevant solution for your use-case:


Sample IdP User Profile:

Before we continue, we will be using the same sample IdP user profile for each case.

//SAMPLE IdP User Profile
{
   "created_at": "2021-06-21T13:26:08.579Z",
   "email": "testuser@example.com",
...
   "fav_food": "hamburgers",
   "user_metadata": {
       "fav_book": "Harry Potter and the Prisoner of Azkaban"
   }
...
}

Case 1: No mappings object

When using the SAML2 Addon, there will be an empty mappings object by default.

In the examples that follow, we’ll take a look at how to customize how fav_food and user_metadata.fav_book and map them to the SAML Response. Here, the goal is to show a base example of how Auth0 will populate the SAML Response when we do not define a mappings object.

As shown in the example below, we can see that "fav_food": "hamburgers gets mapped to the http://schemas.auth0.com/fav_food attribute in the SAML Response with the hamburgers value, whereas the "user_metadata": { "fav_book": "Harry Potter and the Prisoner of Azkaban" } does not appear in the SAML response at all.

Resulting SAML Response that the IdP sends:

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_e30cb5f29249a82846eb" InResponseTo="_e33996d83f953ce46225185b3a1c0ad8" Version="2.0" IssueInstant="2021-11-03T21:34:42.493Z" Destination="https://example-dev-tenant.us.auth0.com/login/callback">
...
       <saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
           <saml:Attribute Name="http://schemas.auth0.com/fav_food" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
               <saml:AttributeValue xsi:type="xs:string">
                   hamburgers
               </saml:AttributeValue>
           </saml:Attribute>
...
       </saml:AttributeStatement>
   </saml:Assertion>
</samlp:Response>

Case 2: Standard mappings example

Recall in the earlier example that not customizing the mappings object resulted in a http://schemas.auth0.com/fav_food attribute in the SAML Response with the "hamburgers" value.

Next, let us map the attributes in the Mappings Object of the SAML2 Addon settings to account for that.

After doing so, notice how the "hamburgers" value is the same in the SAML Response, but the attribute name in the SAML Response has been changed from the default http://schemas.auth0.com/fav_food to http://schemas.auth0.com/dinner.

Configuring the SAML2 Addon mappings object:

"mappings": {
   "fav_food": "http://schemas.auth0.com/dinner"
 }

Resulting SAML Response that the IdP sends:

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_e30cb5f29249a82846eb" InResponseTo="_e33996d83f953ce46225185b3a1c0ad8" Version="2.0" IssueInstant="2021-11-03T21:34:42.493Z" Destination="https://example-dev-tenant.us.auth0.com/login/callback">
...
       <saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
           <saml:Attribute Name="http://schemas.auth0.com/dinner" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
               <saml:AttributeValue xsi:type="xs:string">
                   hamburgers
               </saml:AttributeValue>
           </saml:Attribute>
...
       </saml:AttributeStatement>
   </saml:Assertion>
</samlp:Response>

Case 3: Mapping the same value to multiple attributes

There may be scenarios where mapping the SAML Response to multiple attributes with the same value is required.

In this case, there is the option to map the same value from the user profile to multiple attributes in the SAML Response.

How to configure the SAML2 Addon mappings object:

"mappings": {
   "fav_food": [
     "http://schemas.auth0.com/breakfast",
     "http://schemas.auth0.com/lunch",
     "http://schemas.auth0.com/dinner"
   ]
 }

Resulting SAML Response that the IdP sends:

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_e30cb5f29249a82846eb" InResponseTo="_e33996d83f953ce46225185b3a1c0ad8" Version="2.0" IssueInstant="2021-11-03T21:34:42.493Z" Destination="https://example-dev-tenant.us.auth0.com/login/callback">
...
       <saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
           <saml:Attribute Name="http://schemas.auth0.com/breakfast" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
               <saml:AttributeValue xsi:type="xs:string">
                   hamburgers
               </saml:AttributeValue>
           </saml:Attribute>
           <saml:Attribute Name="http://schemas.auth0.com/lunch" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
               <saml:AttributeValue xsi:type="xs:string">
                   hamburgers
               </saml:AttributeValue>
           </saml:Attribute>
           <saml:Attribute Name="http://schemas.auth0.com/dinner" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
               <saml:AttributeValue xsi:type="xs:string">
                   hamburgers
               </saml:AttributeValue>
           </saml:Attribute>
...
       </saml:AttributeStatement>
   </saml:Assertion>
</samlp:Response>

Case 4: Mapping user_metadata/app_metadata into claims in the SAML Response

In the earlier example in Case #1, recall that using the default mapping object resulted in the absence of the user_metadata values in the SAML Response.

Given that the SAML2 Addon mappings object can only work with root-level profile attributes, this example shows how to map the user_metadata properties to the user object using a Rule.

The root-level profile attribute added to the user object in the Rule will only be there for the login transaction and will not persist in the user’s profile. Doing so allows the attributes to be accessible from the mappings objects in the SAML2 Addon settings for login.

How to configure the Rule on the IdP tenant:

function (user, context, callback) {
   if (user.user_metadata && user.user_metadata.fav_book) {
     user.fav_book = user.user_metadata.fav_book;
   }
   return callback(null, user, context);
 }

How to configure the SAML2 Addon mappings object:

"mappings": {
   "fav_book": "http://schemas.auth0.com/reading_list"
 }

Resulting SAML Response that the IdP sends:

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_e61ea301467608dce733" InResponseTo="_02bef4dfcc0aa532c8ba2d3ec1f3785a" Version="2.0" IssueInstant="2021-11-10T21:30:53.510Z" Destination="https://example-dev-tenant.us.auth0.com/login/callback">
...
       <saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
...
           <saml:Attribute Name="http://schemas.auth0.com/reading_list" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
               <saml:AttributeValue xsi:type="xs:string">
                   Harry Potter and the Prisoner of Azkaban
               </saml:AttributeValue>
           </saml:Attribute>
...
       </saml:AttributeStatement>
   </saml:Assertion>
</samlp:Response>

Case 5: Mapping hard-coded values that don’t exist in the user profile to the SAML Response

Similar to the example above of mapping user_metadata properties, there is also the option to use a Rule for mapping hard-coded values that don’t exist in the user profile to the SAML Response since the mappings object in the SAML2 Addon can only work with root-level profile attributes.

Note that the root-level profile attribute added to the user object in the Rule will only be there for the login transaction and will not persist in the user’s profile. Doing so allows the attributes to be accessible from the mappings objects in the SAML2 Addon settings for login.

How to configure the Rule on the IdP tenant:

function (user, context, callback) {
   // add the hard-coded value to the user object so that it can be accessed in the mappings object in the SAML2 Addon
   user.awsRole = "arn:aws:iam::XXXXXXX:role/sso-to-admin,arn:aws:iam::XXXXXXXX:saml-provider/auth0-dev";
   return callback(null, user, context);
 }

How to configure the SAML2 Addon mappings object:

"mappings": {
   "awsRole": "https://aws.amazon.com/SAML/Attributes/Role"
 }

Resulting SAML Response that the IdP sends:

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_e61ea301467608dce733" InResponseTo="_02bef4dfcc0aa532c8ba2d3ec1f3785a" Version="2.0" IssueInstant="2021-11-10T21:30:53.510Z" Destination="https://example-dev-tenant.us.auth0.com/login/callback">
...
       <saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
...
           <saml:Attribute Name="https://aws.amazon.com/SAML/Attributes/Role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
               <saml:AttributeValue xsi:type="xs:string">
                   arn:aws:iam::XXXXXXX:role/sso-to-admin,arn:aws:iam::XXXXXXXX:saml-provider/auth0-dev
               </saml:AttributeValue>
           </saml:Attribute>
...
       </saml:AttributeStatement>
   </saml:Assertion>
</samlp:Response>

2 Likes