Customize claims issued in the SAML token for enterprise applications

Today, the Microsoft identity platform supports single sign-on (SSO) with most enterprise applications, including both applications pre-integrated in the Azure AD app gallery and custom applications. When a user authenticates to an application through the Microsoft identity platform using the SAML 2.0 protocol, the Microsoft identity platform sends a token to the application (via an HTTP POST). And then, the application validates and uses the token to log the user in instead of prompting for a username and password. These SAML tokens contain pieces of information about the user known as claims.

A claim is information that an identity provider states about a user inside the token they issue for that user. In SAML token, this data is typically contained in the SAML Attribute Statement. The user’s unique ID is typically represented in the SAML Subject also called as Name Identifier.

By default, the Microsoft identity platform issues a SAML token to your application that contains a NameIdentifier claim with a value of the user’s username (also known as the user principal name) in Azure AD, which can uniquely identify the user. The SAML token also contains other claims that include the user’s email address, first name, and last name.

To view or edit the claims issued in the SAML token to the application, open the application in Azure portal. Then open the User Attributes & Claims section.

Open the User Attributes & Claims section in the Azure portal

There are two possible reasons why you might need to edit the claims issued in the SAML token:

  • The application requires the NameIdentifier or NameID claim to be something other than the username (or user principal name) stored in Azure AD.
  • The application has been written to require a different set of claim URIs or claim values.

Editing nameID

To edit the NameID (name identifier value):

  1. Open the Name identifier value page.

  2. Select the attribute or transformation you want to apply to the attribute. Optionally, you can specify the format you want the NameID claim to have.

    Edit the NameID (name identifier) value

NameID format

If the SAML request contains the element NameIDPolicy with a specific format, then the Microsoft identity platform will honor the format in the request.

If the SAML request doesn't contain an element for NameIDPolicy, then the Microsoft identity platform will issue the NameID with the format you specify. If no format is specified, the Microsoft identity platform will use the default source format associated with the claim source selected. If a transformation results in a null or illegal value, Azure AD will send a persistent pairwise identifier in the nameIdentifier.

From the Choose name identifier format dropdown, you can select one of the following options.

NameID format Description
Default Microsoft identity platform will use the default source format.
Persistent Microsoft identity platform will use Persistent as the NameID format.
Email address Microsoft identity platform will use EmailAddress as the NameID format.
Unspecified Microsoft identity platform will use Unspecified as the NameID format.
Windows domain qualified name Microsoft identity platform will use the WindowsDomainQualifiedName format.

Transient NameID is also supported, but isn't available in the dropdown and can't be configured on Azure's side. To learn more about the NameIDPolicy attribute, see Single sign-On SAML protocol.

Attributes

Select the desired source for the NameIdentifier (or NameID) claim. You can select from the following options.

Name Description
Email Email address of the user
userprincipalName User principal name (UPN) of the user
onpremisessamaccountname SAM account name that has been synced from on-premises Azure AD
objectid Objectid of the user in Azure AD
employeeid Employee ID of the user
Directory extensions Directory extensions synced from on-premises Active Directory using Azure AD Connect Sync
Extension Attributes 1-15 On-premises extension attributes used to extend the Azure AD schema
pairwiseid​ Persistent form of user identifier

For more info, see Table 3: Valid ID values per source.

You can also assign any constant (static) value to any claims, which you define in Azure AD. The steps below outline how to assign a constant value:

  1. In the Azure portal, on the User Attributes & Claims section, click on the Edit icon to edit the claims.

  2. Click on the required claim which you want to modify.

  3. Enter the constant value without quotes in the Source attribute as per your organization and click Save.

    Org Attributes & Claims section in the Azure portal

  4. The constant value will be displayed as below.

    Edit Attributes & Claims section in the Azure portal

Special claims - transformations

You can also use the claims transformations functions.

Function Description
ExtractMailPrefix() Removes the domain suffix from either the email address or the user principal name. This extracts only the first part of the user name being passed through (for example, "joe_smith" instead of joe_smith@contoso.com).
ToLower() Converts the characters of the selected attribute into lowercase characters.
ToUpper() Converts the characters of the selected attribute into uppercase characters.

Adding application-specific claims

To add application-specific claims:

  1. In User Attributes & Claims, select Add new claim to open the Manage user claims page.
  2. Enter the name of the claims. The value doesn't strictly need to follow a URI pattern, per the SAML spec. If you need a URI pattern, you can put that in the Namespace field.
  3. Select the Source where the claim is going to retrieve its value. You can select a user attribute from the source attribute dropdown or apply a transformation to the user attribute before emitting it as a claim.

Claim transformations

To apply a transformation to a user attribute:

  1. In Manage claim, select Transformation as the claim source to open the Manage transformation page.

  2. Select the function from the transformation dropdown. Depending on the function selected, you'll have to provide parameters and a constant value to evaluate in the transformation. Refer to the table below for more information about the available functions.

  3. (preview) Treat source as multivalued is a checkbox indicating if the transform should be applied to all values or just the first. By default, transformations will only be applied to the first element in a multi value claim, by checking this box it ensures it's applied to all. This checkbox will only be enabled for multivalued attributes, for example user.proxyaddresses.

  4. To apply multiple transformations, click on Add transformation. You can apply a maximum of two transformations to a claim. For example, you could first extract the email prefix of the user.mail. Then, make the string upper case.

    Multiple claims transformation

You can use the following functions to transform claims.

Function Description
ExtractMailPrefix() Removes the domain suffix from either the email address or the user principal name. This extracts only the first part of the user name being passed through (for example, "joe_smith" instead of joe_smith@contoso.com).
Join() Creates a new value by joining two attributes. Optionally, you can use a separator between the two attributes. For NameID claim transformation, the Join() function has specific behavior when the transformation input has a domain part. It will remove the domain part from input before joining it with the separator and the selected parameter. For example, if the input of the transformation is ‘joe_smith@contoso.com’ and the separator is ‘@’ and the parameter is ‘fabrikam.com’, this will result in joe_smith@fabrikam.com.
ToLowercase() Converts the characters of the selected attribute into lowercase characters.
ToUppercase() Converts the characters of the selected attribute into uppercase characters.
Contains() Outputs an attribute or constant if the input matches the specified value. Otherwise, you can specify another output if there’s no match.
For example, if you want to emit a claim where the value is the user’s email address if it contains the domain “@contoso.com”, otherwise you want to output the user principal name. To do this, you would configure the following values:
Parameter 1(input): user.email
Value: "@contoso.com"
Parameter 2 (output): user.email
Parameter 3 (output if there's no match): user.userprincipalname
EndWith() Outputs an attribute or constant if the input ends with the specified value. Otherwise, you can specify another output if there’s no match.
For example, if you want to emit a claim where the value is the user’s employee ID if the employee ID ends with “000”, otherwise you want to output an extension attribute. To do this, you would configure the following values:
Parameter 1(input): user.employeeid
Value: "000"
Parameter 2 (output): user.employeeid
Parameter 3 (output if there's no match): user.extensionattribute1
StartWith() Outputs an attribute or constant if the input starts with the specified value. Otherwise, you can specify another output if there’s no match.
For example, if you want to emit a claim where the value is the user’s employee ID if the country/region starts with "US", otherwise you want to output an extension attribute. To do this, you would configure the following values:
Parameter 1(input): user.country
Value: "US"
Parameter 2 (output): user.employeeid
Parameter 3 (output if there's no match): user.extensionattribute1
Extract() - After matching Returns the substring after it matches the specified value.
For example, if the input's value is "Finance_BSimon", the matching value is "Finance_", then the claim's output is "BSimon".
Extract() - Before matching Returns the substring until it matches the specified value.
For example, if the input's value is "BSimon_US", the matching value is "_US", then the claim's output is "BSimon".
Extract() - Between matching Returns the substring until it matches the specified value.
For example, if the input's value is "Finance_BSimon_US", the first matching value is "Finance_", the second matching value is "_US", then the claim's output is "BSimon".
ExtractAlpha() - Prefix Returns the prefix alphabetical part of the string.
For example, if the input's value is "BSimon_123", then it returns "BSimon".
ExtractAlpha() - Suffix Returns the suffix alphabetical part of the string.
For example, if the input's value is "123_Simon", then it returns "Simon".
ExtractNumeric() - Prefix Returns the prefix numerical part of the string.
For example, if the input's value is "123_BSimon", then it returns "123".
ExtractNumeric() - Suffix Returns the suffix numerical part of the string.
For example, if the input's value is "BSimon_123", then it returns "123".
IfEmpty() Outputs an attribute or constant if the input is null or empty.
For example, if you want to output an attribute stored in an extensionattribute if the employee ID for a given user is empty. To do this, you would configure the following values:
Parameter 1(input): user.employeeid
Parameter 2 (output): user.extensionattribute1
Parameter 3 (output if there's no match): user.employeeid
IfNotEmpty() Outputs an attribute or constant if the input isn't null or empty.
For example, if you want to output an attribute stored in an extensionattribute if the employee ID for a given user is not empty. To do this, you would configure the following values:
Parameter 1(input): user.employeeid
Parameter 2 (output): user.extensionattribute1
Substring() – Fixed Length (Preview) Extracts parts of a string claim type, beginning at the character at the specified position, and returns the specified number of characters.
SourceClaim - The claim source which the transform should be executed.
StartIndex - The zero-based starting character position of a substring in this instance.
Length - The length in characters of the substring.
For example:
sourceClaim – PleaseExtractThisNow
StartIndex – 6
Length – 11
Output: ExtractThis
Substring() – EndOfString (Preview) Extracts parts of a string claim type, beginning at the character at the specified position, and returns the rest of the claim from the specified start index.
SourceClaim - The claim source which the transform should be executed.
StartIndex - The zero-based starting character position of a substring in this instance.
For example:
sourceClaim – PleaseExtractThisNow
StartIndex – 6
Output: ExtractThisNow
RegexReplace() (Preview) RegexReplace() transformation accepts as input parameters:
- Parameter 1: a user attribute as regex input
- An option to trust the source as multivalued
- Regex pattern
- Replacement pattern. The replacement pattern may contain static text format along with reference pointing to regex output groups and additional input parameters.

Additional instructions on how to use RegexReplace() Transformation described below.

If you need additional transformations, submit your idea in the feedback forum in Azure AD under the SaaS application category.

How to use the RegexReplace() Transformation

Screenshot of RegexReplace() Transformation Illustration.

  1. Select the edit button (pencil icon) to open the claims transformation blade.

  2. Select the “RegexReplace()” option from the “Transformation” options to use regex-based claims transformation method for claims transformation.

  3. “Parameter 1” is the source user input attribute which will be an input for the regular expression transformation. For example, user.mail which will have user email address such as admin@contoso.com.

  4. Some input user attributes can be multi-value user attributes. If the selected user attribute supports multiple values and the user wants to use multiple values for the transformation, they need to check the “Treat source as multivalued” checkbox. If an administrator checks the checkbox, all values will be used for regex match, otherwise only the first value will be used.

  5. The “Regex pattern” textbox accepts a regular expression which will be evaluated against the value of user attribute selected as “parameter 1”. For example a regular expression to extract user alias from the user’s email address would be represented as: “(?'domain'^.*?)(?i)(@contoso.com)$”

  6. By using the “Add additional parameter” button, an administrator can choose more user attributes, which can be used for the transformation. The values of the additional attributes would then be merged with regex transformation output. Currently, up to five additional parameters are supported.

    To illustrate, let's use user.country attribute as an input parameter. The value of this attribute is “US”. To merge this into the replacement pattern the administrator needs to refer to it as {country} inside the replacement pattern. Once the administrator selects the user attribute for the parameter, an info balloon for the parameter will explain how the parameter can be used inside the replacement pattern.
    Screenshot of RegexReplace() Info Bubble Illustration.

  7. The “Replacement pattern” textbox accepts the replacement pattern. Replacement pattern is the text template, which contains placeholders for regex outcome group name, input parameter group name, and static text value. All group names must be wrapped inside the curly braces such as {group-name}. Let’s say the administration wants to use user alias with some other domain name e.g. xyz.com and merge country name with it. In this case the replacement pattern would be “{country}.{domain}@xyz.com”, where {country} will be the value of input parameter and {domain} will be the group output from the regular expression evaluation. In such a case, the expected outcome will be “US.swmal@xyz.com”

  8. RegexReplace() transformation will be evaluated only if the value of the selected user attribute for “Parameter 1” matches with the regular expression provided in “Regex pattern” textbox. If they do not match, the default claim value will be added to the token. To validate regular expression against the input parameter value, a test experience is available within the transform blade. This test experience operates on dummy values only. When additional input parameters are used, the name of the parameter will be added to the test result instead of the actual value. You can see a sample output in point 18. To access the test section an administrator can select the “Test transformation” button. Screenshot of RegexReplace() Test Transformation.

  9. Regex-based claims transformations are not limited to the first transformation and can be used as the second level transformation as well. Any other transformation method can be used as the first transformation.

  10. If RegexReplace() is selected as a second level transformation, output of first level transformation will be used as an input for the second level transformation. The second level regex expression should match the output of the first transformation else the transformation won't be applied.

  11. Same as point 5 above, “Regex pattern” is the regular expression for the second level transformation.

  12. These are the inputs user attributes for the second level transformations.

  13. Administrators can delete the selected input parameter if they don’t need it anymore.

  14. Once administrator selects “Test transformation”, the “Test transformation” section will be displayed, and “Test transformation” button goes away.

  15. Select the close or (X) button to hide the test section and re-render the “Test transformation” button again on the blade.

  16. The “Test regex input” textbox accepts the dummy input, which will be used as an input for regular expression test evaluation. In case regex-based claims transformation is configured as a second level transformation, the administrator needs to provided a dummy value, which would be the expected output of the first transformation.

  17. Once the administrator provides the test regex input and configures the “Regex pattern”, “Replacement pattern” and “Input parameters”, they can evaluate the expression by clicking on the “Run test” button.

  18. If evaluation succeeds, an output of test transformation will be rendered against the “Test transformation result” label.

  19. The administrator can remove the second level transformation by using “Remove transformation” button.

  20. When a regex input value is configured against the “Parameter 1” which doesn't matches the “Regular expression”, the transformation is skipped. In such cases, the administrator can configure the alternate user attribute, which will be added to the token for the claim by checking the checkbox for “Specify output if no match”.

  21. If an administrator wants to return alternate user attribute in case of no match and checked the “Specify output if no match” checkbox, they can select alternate user attribute by using the dropdown. This dropdown is available against “Parameter 3 (output if no match)”.

  22. At the bottom of the blade a full summary of the format is displayed which explains the meaning of transformation in simple text.

  23. Once the administrator is satisfied with the configuration settings for the transformation, they can save it to claims policy by selecting the “Add” button. Changes won’t be saved unless the administrator manually selects the “Save” toolbar button available on “Manage Claim” blade.

RegexReplace() transformation is also available for the group claims transformations. Screenshot of RegexReplace() Group Claims Transformation.

RegexReplace() Transform Validations

Input parameters with duplicate user attributes aren't allowed. If duplicate user attributes are selected, the following validation message will be rendered after the administrator selects “Add” or “Run test” button.

Screenshot of RegexReplace() Validation Duplicate User.

When unused input parameters found, the following message will be rendered on click of “Add” and “Run test” button click. Defined input parameters should have respective usage into the Replacement pattern text.

Screenshot of RegexReplace() Validation Input Parameter.

With test experience, if provided test regex input doesn't match with the provided regular expression then following message will be displayed. This validation needs input value hence it won’t be applied when user clicks on “Add” button.

Screenshot of RegexReplace() Validation Test Regex Failed Regular Expression.

With test experience, when source for the groups into the replacement pattern not found user will receive following message. This validation won’t be applied when user clicks on “Add” button.

Screenshot of RegexReplace() Validation Test Regex Groups Not Found.

Add the UPN claim to SAML tokens

The http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn claim is part of the SAML restricted claim set, so you can't add it in the User Attributes & Claims section. As a workaround, you can add it as an optional claim through App registrations in the Azure portal.

Open the app in App registrations and select Token configuration and then Add optional claim. Select the SAML token type, choose upn from the list, and click Add to get the claim in the token.

Emitting claims based on conditions

You can specify the source of a claim based on user type and the group to which the user belongs.

The user type can be:

  • Any: All users are allowed to access the application.
  • Members: Native member of the tenant
  • All guests: User is brought over from an external organization with or without Azure AD.
  • AAD guests: Guest user belongs to another organization using Azure AD.
  • External guests: Guest user belongs to an external organization that doesn't have Azure AD.

One scenario where this is helpful is when the source of a claim is different for a guest and an employee accessing an application. You may want to specify that if the user is an employee the NameID is sourced from user.email, but if the user is a guest then the NameID is sourced from user.extensionattribute1.

To add a claim condition:

  1. In Manage claim, expand the Claim conditions.
  2. Select the user type.
  3. Select the group(s) to which the user should belong. You can select up to 50 unique groups across all claims for a given application.
  4. Select the Source where the claim is going to retrieve its value. You can select a user attribute from the source attribute dropdown or apply a transformation to the user attribute before emitting it as a claim.

The order in which you add the conditions are important. Azure AD first evaluates all conditions with source Attribute and then evaluates all conditions with source Transformation to decide which value to emit in the claim. Conditions with the same source are evaluated from top to bottom. The last value, which matches the expression will be emitted in the claim. Transformations such as IsNotEmpty and Contains act like additional restrictions.

For example, Britta Simon is a guest user in the Contoso tenant. Britta belongs to another organization that also uses Azure AD. Given the below configuration for the Fabrikam application, when Britta tries to sign in to Fabrikam, the Microsoft identity platform will evaluate the conditions as follows.

First, the Microsoft identity platform verifies if Britta's user type is All guests. Since, this is true then the Microsoft identity platform assigns the source for the claim to user.extensionattribute1. Second, the Microsoft identity platform verifies if Britta's user type is AAD guests, since this is also true then the Microsoft identity platform assigns the source for the claim to user.mail. Finally, the claim is emitted with value user.mail for Britta.

Screenshot of claims conditional configuration.

As another example, consider when Britta Simon tries to sign in and the following configuration is used. Azure AD first evaluates all conditions with source Attribute. Because Britta's user type is AAD guests, user.mail is assigned as the source for the claim. Next, Azure AD evaluates the transformations. Because Britta is a guest, user.extensionattribute1 is now the new source for the claim. Because Britta is in AAD guests, user.othermail is now the source for this claim. Finally, the claim is emitted with value user.othermail for Britta.

Screenshot of more claims conditional configuration.

As a final example, let’s consider what happens if Britta has no user.othermail configured or it's empty. In both cases the condition entry is ignored, and the claim will fall back to user.extensionattribute1 instead.

Advanced SAML Claims Options

The following table lists advanced options that can be configured for an application.

Option Description
Append application ID to issuer Automatically adds the application ID to the issuer claim. This option ensures a unique claim value for each instance when there are multiple instances of the same application. This setting is ignored if a custom signing key isn't configured for the application.
Override audience claim Allows for the overriding of the audience claim sent to the application. The value provided must be a valid absolute URI. This setting is ignored if a custom signing key isn't configured for the application.
Include attribute name format If selected, Azure Active Directory adds an additional attribute called NameFormat that describes the format of the name to restricted, core, and optional claims for the application. For more information, see, Claims mapping policy type

Next steps