Skip to content

Commit 6f42a04

Browse files
authored
Merge pull request #93220 from MicrosoftDocs/master
10/24 AM Publish
2 parents 7efb2a6 + e772952 commit 6f42a04

File tree

99 files changed

+700
-822
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+700
-822
lines changed

articles/active-directory/develop/active-directory-saml-claims-customization.md

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,21 @@ services: active-directory
66
documentationcenter: ''
77
author: rwike77
88
manager: CelesteDG
9-
editor: ''
10-
119
ms.assetid: f1daad62-ac8a-44cd-ac76-e97455e47803
1210
ms.service: active-directory
1311
ms.subservice: develop
1412
ms.workload: identity
1513
ms.tgt_pltfrm: na
1614
ms.devlang: na
17-
ms.topic: conceptual
18-
ms.date: 10/01/2019
15+
ms.topic: article
16+
ms.date: 10/22/2019
1917
ms.author: ryanwi
2018
ms.reviewer: luleon, paulgarn, jeedes
2119
ms.custom: aaddev
2220
ms.collection: M365-identity-device-management
2321
---
2422

25-
# How to: Customize claims issued in the SAML token for enterprise applications
23+
# How to: customize claims issued in the SAML token for enterprise applications
2624

2725
Today, Azure Active Directory (Azure AD) supports single sign-on (SSO) with most enterprise applications, including both applications pre-integrated in the Azure AD app gallery as well as custom applications. When a user authenticates to an application through Azure AD using the SAML 2.0 protocol, Azure AD 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*.
2826

@@ -39,7 +37,7 @@ There are two possible reasons why you might need to edit the claims issued in t
3937
* The application requires the `NameIdentifier` or NameID claim to be something other than the username (or user principal name) stored in Azure AD.
4038
* The application has been written to require a different set of claim URIs or claim values.
4139

42-
## Editing NameID
40+
## Editing nameID
4341

4442
To edit the NameID (name identifier value):
4543

@@ -74,8 +72,8 @@ Select the desired source for the `NameIdentifier` (or NameID) claim. You can se
7472
| Email | Email address of the user |
7573
| userprincipalName | User principal name (UPN) of the user |
7674
| onpremisessamaccount | SAM account name that has been synced from on-premises Azure AD |
77-
| objectid | objectid of the user in Azure AD |
78-
| employeeid | employeeid of the user |
75+
| objectid | Objectid of the user in Azure AD |
76+
| employeeid | Employee ID of the user |
7977
| Directory extensions | Directory extensions [synced from on-premises Active Directory using Azure AD Connect Sync](../hybrid/how-to-connect-sync-feature-directory-extensions.md) |
8078
| Extension Attributes 1-15 | On-premises extension attributes used to extend the Azure AD schema |
8179

@@ -87,15 +85,15 @@ You can also assign any constant (static) value to any claims which you define i
8785

8886
1. Click on the required claim which you want to modify.
8987

90-
1. Enter the constant value in the **Source attribute** as per your organization and click **Save**.
88+
1. Enter the constant value without quotes in the **Source attribute** as per your organization and click **Save**.
9189

9290
![Open the User Attributes & Claims section in the Azure portal](./media/active-directory-saml-claims-customization/organization-attribute.png)
9391

9492
1. The constant value will be displayed as below.
9593

9694
![Open the User Attributes & Claims section in the Azure portal](./media/active-directory-saml-claims-customization/edit-attributes-claims.png)
9795

98-
### Special claims - Transformations
96+
### Special claims - transformations
9997

10098
You can also use the claims transformations functions.
10199

@@ -114,31 +112,68 @@ To add application-specific claims:
114112
1. 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.
115113
1. 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.
116114

117-
### Application-specific claims - Transformations
115+
### Claim transformations
118116

119-
You can also use the claims transformations functions.
117+
To apply a transformation to a user attribute:
118+
119+
1. In **Manage claim**, select *Transformation* as the claim source to open the **Manage transformation** page.
120+
2. Select the function from the transformation dropdown. Depending on the function selected, you will 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.
121+
3. To apply multiple transformation, click on **Add transformation**.You can apply a maximum of two transformation to a claim. For example, you could first extract the email prefix of the `user.mail`. Then, make the string upper case.
122+
123+
![Edit the NameID (name identifier) value](./media/active-directory-saml-claims-customization/sso-saml-multiple-claims-transformation.png)
124+
125+
You can use the following functions to transform claims.
120126

121127
| Function | Description |
122128
|----------|-------------|
123129
| **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 [email protected]). |
124-
| **Join()** | Creates a new value by joining two attributes. Optionally, you can use a separator between the two attributes. |
130+
| **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 is restricted to a verified domain. If the selected user identifier value has a domain, it will extract the username to append the selected verified domain. For example, if you select the email ([email protected]) as the user identifier value and select contoso.onmicrosoft.com as the verified domain, this will result in [email protected]. |
125131
| **ToLower()** | Converts the characters of the selected attribute into lowercase characters. |
126132
| **ToUpper()** | Converts the characters of the selected attribute into uppercase characters. |
127133
| **Contains()** | Outputs an attribute or constant if the input matches the specified value. Otherwise, you can specify another output if there’s no match.<br/>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:<br/>*Parameter 1(input)*: user.email<br/>*Value*: "@contoso.com"<br/>Parameter 2 (output): user.email<br/>Parameter 3 (output if there's no match): user.userprincipalname |
128-
| **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.<br/>For example, if you want to emit a claim where the value is the user’s employeeid if the employeeid ends with “000”, otherwise you want to output an extension attribute. To do this, you would configure the following values:<br/>*Parameter 1(input)*: user.employeeid<br/>*Value*: "000"<br/>Parameter 2 (output): user.employeeid<br/>Parameter 3 (output if there's no match): user.extensionattribute1 |
129-
| **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.<br/>For example, if you want to emit a claim where the value is the user’s employeeid if the country/region starts with "US", otherwise you want to output an extension attribute. To do this, you would configure the following values:<br/>*Parameter 1(input)*: user.country<br/>*Value*: "US"<br/>Parameter 2 (output): user.employeeid<br/>Parameter 3 (output if there's no match): user.extensionattribute1 |
134+
| **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.<br/>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:<br/>*Parameter 1(input)*: user.employeeid<br/>*Value*: "000"<br/>Parameter 2 (output): user.employeeid<br/>Parameter 3 (output if there's no match): user.extensionattribute1 |
135+
| **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.<br/>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:<br/>*Parameter 1(input)*: user.country<br/>*Value*: "US"<br/>Parameter 2 (output): user.employeeid<br/>Parameter 3 (output if there's no match): user.extensionattribute1 |
130136
| **Extract() - After matching** | Returns the substring after it matches the specified value.<br/>For example, if the input's value is "Finance_BSimon", the matching value is "Finance_", then the claim's output is "BSimon". |
131137
| **Extract() - Before matching** | Returns the substring until it matches the specified value.<br/>For example, if the input's value is "BSimon_US", the matching value is "_US", then the claim's output is "BSimon". |
132138
| **Extract() - Between matching** | Returns the substring until it matches the specified value.<br/>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". |
133139
| **ExtractAlpha() - Prefix** | Returns the prefix alphabetical part of the string.<br/>For example, if the input's value is "BSimon_123", then it returns "BSimon". |
134140
| **ExtractAlpha() - Suffix** | Returns the suffix alphabetical part of the string.<br/>For example, if the input's value is "123_Simon", then it returns "Simon". |
135141
| **ExtractNumeric() - Prefix** | Returns the prefix numerical part of the string.<br/>For example, if the input's value is "123_BSimon", then it returns "123". |
136142
| **ExtractNumeric() - Suffix** | Returns the suffix numerical part of the string.<br/>For example, if the input's value is "BSimon_123", then it returns "123". |
137-
| **IfEmpty()** | Outputs an attribute or constant if the input is null or empty.<br/>For example, if you want to output an attribute stored in an extensionattribute if the employeeid for a given user is empty. To do this, you would configure the following values:<br/>Parameter 1(input): user.employeeid<br/>Parameter 2 (output): user.extensionattribute1<br/>Parameter 3 (output if there's no match): user.employeeid |
138-
| **IfNotEmpty()** | Outputs an attribute or constant if the input is not null or empty.<br/>For example, if you want to output an attribute stored in an extensionattribute if the employeeid for a given user is not empty. To do this, you would configure the following values:<br/>Parameter 1(input): user.employeeid<br/>Parameter 2 (output): user.extensionattribute1 |
143+
| **IfEmpty()** | Outputs an attribute or constant if the input is null or empty.<br/>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:<br/>Parameter 1(input): user.employeeid<br/>Parameter 2 (output): user.extensionattribute1<br/>Parameter 3 (output if there's no match): user.employeeid |
144+
| **IfNotEmpty()** | Outputs an attribute or constant if the input is not null or empty.<br/>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:<br/>Parameter 1(input): user.employeeid<br/>Parameter 2 (output): user.extensionattribute1 |
139145

140146
If you need additional transformations, submit your idea in the [feedback forum in Azure AD](https://feedback.azure.com/forums/169401-azure-active-directory?category_id=160599) under the *SaaS application* category.
141147

148+
## Emitting claims based on conditions
149+
150+
You can specify the source of a claim based on user type and the group to which the user belongs.
151+
152+
The user type can be:
153+
- **Any**: All users are allowed to access the application.
154+
- **Members**: Native member of the tenant
155+
- **All guests**: User is brought over from an external organization with or without Azure AD.
156+
- **AAD guests**: Guest user belongs to another organization using Azure AD.
157+
- **External guests**: Guest user belongs to an external organization that doesn't have Azure AD.
158+
159+
160+
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.
161+
162+
To add a claim condition:
163+
164+
1. In **Manage claim**, expand the Claim conditions.
165+
2. Select the user type.
166+
3. Select the group(s) to which the user should belong. You can select up to 10 unique groups across all claims for a given application.
167+
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.
168+
169+
The order in which you add the conditions are important. Azure AD evaluates the conditions from top to bottom to decide which value to emit in the claim.
170+
171+
For example, Brita Simon is a guest user in the Contoso tenant. She belongs to another organization that also uses Azure AD. Given the below configuration for the Fabrikam application, when Brita tries to sign in to Fabrikam, Azure AD will evaluate the conditions as follow.
172+
173+
First, Azure AD verifies if Brita's user type is `All guests`. Since, this is true then Azure AD assigns the source for the claim to `user.extensionattribute1`. Second, Azure AD verifies if Brita's user type is `AAD guests`, since this is also true then Azure AD assigns the source for the claim to `user.mail`. Finally, the claim is emitted with value `user.email` for Brita.
174+
175+
![Claims conditional configuration](./media/active-directory-saml-claims-customization/sso-saml-user-conditional-claims.png)
176+
142177
## Next steps
143178

144179
* [Application management in Azure AD](../manage-apps/what-is-application-management.md)
-65.8 KB
Loading
Loading
Loading

articles/active-directory/develop/quickstart-v2-python-daemon.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,10 @@ https://login.microsoftonline.com/Enter_the_Tenant_Id_Here/adminconsent?client_i
138138
139139
#### Step 5: Run the application
140140

141-
You'll need to install MSAL Python once
141+
You'll need to install the dependencies of this sample once
142142

143143
```console
144-
pip install msal
144+
pip install -r requirements.txt
145145
```
146146

147147
Then, run the application via command prompt or console:
@@ -164,7 +164,7 @@ You should see on the console output some Json fragment representing a list of u
164164
You can install MSAL Python by running the following pip command.
165165

166166
```powershell
167-
pip install -r requirements.txt
167+
pip install msal
168168
```
169169

170170
### MSAL initialization

articles/active-directory/develop/scenario-desktop-acquire-token.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ ms.devlang: na
1212
ms.topic: conceptual
1313
ms.tgt_pltfrm: na
1414
ms.workload: identity
15-
ms.date: 07/16/2019
15+
ms.date: 10/24/2019
1616
ms.author: jmprieur
1717
ms.custom: aaddev
1818
#Customer intent: As an application developer, I want to know how to write a Desktop app that calls web APIs using the Microsoft identity platform for developers.
@@ -408,7 +408,7 @@ You can also acquire a token by providing the username and password. This flow i
408408
This flow is **not recommended** because your application asking a user for their password isn't secure. For more information about this problem, see [this article](https://news.microsoft.com/features/whats-solution-growing-problem-passwords-says-microsoft/). The preferred flow for acquiring a token silently on Windows domain joined machines is [Integrated Windows Authentication](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Integrated-Windows-Authentication). Otherwise you can also use [Device code flow](https://aka.ms/msal-net-device-code-flow)
409409
410410
> [!NOTE]
411-
> Although this is useful in some cases (DevOps scenarios), if you want to use Username/password in interactive scenarios where you provide your onw UI, you should really think about how to move away from it. By using username/password you are giving-up a number of things:
411+
> Although this is useful in some cases (DevOps scenarios), if you want to use Username/password in interactive scenarios where you provide your own UI, you should really think about how to move away from it. By using username/password you are giving-up a number of things:
412412
>
413413
> - core tenants of modern identity: password gets fished, replayed. Because we have this concept of a share secret that can be intercepted.
414414
> This is incompatible with passwordless.

articles/active-directory/manage-apps/configure-single-sign-on-non-gallery-applications.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ If the application hasn't been added to your Azure AD tenant, see [Add a non-gal
4848
| Basic SAML Configuration setting | SP-Initiated | idP-Initiated | Description |
4949
|:--|:--|:--|:--|
5050
| **Identifier (Entity ID)** | Required for some apps | Required for some apps | Uniquely identifies the application. Azure AD sends the identifier to the application as the Audience parameter of the SAML token. The application is expected to validate it. This value also appears as the Entity ID in any SAML metadata provided by the application. *You can find this value as the **Issuer** element in the **AuthnRequest** (SAML request) sent by the application.* |
51-
| **Reply URL** | Optional | Required | Specifies where the application expects to receive the SAML token. The reply URL is also referred to as the Assertion Consumer Service (ACS) URL. You can use the additional reply URL fields to specify multiple reply URLs. For example, you might need additional reply URLs for multiple subdomains. Or, for testing purposes you can specify multiple reply URLs (local host and public URLs) at one time. |
51+
| **Reply URL** | Required | Required | Specifies where the application expects to receive the SAML token. The reply URL is also referred to as the Assertion Consumer Service (ACS) URL. You can use the additional reply URL fields to specify multiple reply URLs. For example, you might need additional reply URLs for multiple subdomains. Or, for testing purposes you can specify multiple reply URLs (local host and public URLs) at one time. |
5252
| **Sign-on URL** | Required | Don't specify | When a user opens this URL, the service provider redirects to Azure AD to authenticate and sign on the user. Azure AD uses the URL to start the application from Office 365 or the Azure AD Access Panel. When blank, Azure AD performs IdP-initiated sign-on when a user launches the application from Office 365, the Azure AD Access Panel, or the Azure AD SSO URL.|
5353
| **Relay State** | Optional | Optional | Specifies to the application where to redirect the user after authentication is completed. Typically the value is a valid URL for the application. However, some applications use this field differently. For more information, ask the application vendor.
5454
| **Logout URL** | Optional | Optional | Used to send the SAML Logout responses back to the application.

0 commit comments

Comments
 (0)