Skip to content

Commit 1782634

Browse files
authored
Merge pull request #100125 from hpsin/patch-51
Add trailing slash notice
2 parents b249df6 + b08c7fc commit 1782634

File tree

1 file changed

+19
-10
lines changed

1 file changed

+19
-10
lines changed

articles/active-directory/develop/v2-permissions-and-consent.md

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ ms.workload: identity
1414
ms.tgt_pltfrm: na
1515
ms.devlang: na
1616
ms.topic: conceptual
17-
ms.date: 12/10/2019
17+
ms.date: 1/3/2020
1818
ms.author: ryanwi
1919
ms.reviewer: hirsin, jesakowi, jmprieur
2020
ms.custom: aaddev
@@ -165,13 +165,16 @@ To see a code sample that implements the steps, see the [admin-restricted scopes
165165

166166
### Request the permissions in the app registration portal
167167

168-
The admin consent does not accept a scope parameter, so any permissions being requested must be statically defined in the application's registration. In general, it's best practice to ensure that the permissions statically defined for a given application are a superset of the permissions that it will be requesting dynamically/incrementally.
168+
Applications are able to note which permissions they require (both delegated and application) in the app registration portal. This allows use of the `/.default` scope and the Azure Portal's "Grant admin consent" option. In general, it's best practice to ensure that the permissions statically defined for a given application are a superset of the permissions that it will be requesting dynamically/incrementally.
169+
170+
> [!NOTE]
171+
Application permissions can only be requested through the use of [`/.default`](#the-default-scope) - so if your app needs application permissions, make sure they're listed in the app registration portal.
169172

170173
#### To configure the list of statically requested permissions for an application
171174

172175
1. Go to your application in the [Azure portal – App registrations](https://go.microsoft.com/fwlink/?linkid=2083908) experience, or [create an app](quickstart-register-app.md) if you haven't already.
173176
2. Locate the **API Permissions** section, and within the API permissions click Add a permission.
174-
3. Select **Microsoft Graph** from the list of available APIs and then add the permissions that your app requires.
177+
3. Select your preferred resource (e.g. **Microsoft Graph**) from the list of available APIs and then add the permissions that your app requires.
175178
3. **Save** the app registration.
176179

177180
### Recommended: Sign the user into your app
@@ -202,7 +205,7 @@ When you're ready to request permissions from your organization's admin, you can
202205
| `client_id` | Required | The **Application (client) ID** that the [Azure portal – App registrations](https://go.microsoft.com/fwlink/?linkid=2083908) experience assigned to your app. |
203206
| `redirect_uri` | Required |The redirect URI where you want the response to be sent for your app to handle. It must exactly match one of the redirect URIs that you registered in the app registration portal. |
204207
| `state` | Recommended | A value included in the request that will also be returned in the token response. It can be a string of any content you want. Use the state to encode information about the user's state in the app before the authentication request occurred, such as the page or view they were on. |
205-
|`scope` | Required | Defines the set of permissions being requested by the application. This can be either static (using /.default) or dynamic scopes. This can include the OIDC scopes (`openid`, `profile`, `email`). |
208+
|`scope` | Required | Defines the set of permissions being requested by the application. This can be either static (using [`/.default`](#the-default-scope)) or dynamic scopes. This can include the OIDC scopes (`openid`, `profile`, `email`). If you need application permissions, you must use `/.default` to request the statically configured list of permissions. |
206209

207210

208211
At this point, Azure AD requires a tenant administrator to sign in to complete the request. The administrator is asked to approve all the permissions that you have requested in the `scope` parameter. If you've used a static (`/.default`) value, it will function like the v1.0 admin consent endpoint and request consent for all scopes found in the required permissions for the app.
@@ -261,9 +264,9 @@ For more information about the OAuth 2.0 protocol and how to get access tokens,
261264

262265
## The /.default scope
263266

264-
You can use the `/.default` scope to help migrate your apps from the v1.0 endpoint to the Microsoft identity platform endpoint. This is a built-in scope for every application that refers to the static list of permissions configured on the application registration. A `scope` value of `https://graph.microsoft.com/.default` is functionally the same as the v1.0 endpoints `resource=https://graph.microsoft.com` - namely, it requests a token with the scopes on Microsoft Graph that the application has registered for in the Azure portal.
267+
You can use the `/.default` scope to help migrate your apps from the v1.0 endpoint to the Microsoft identity platform endpoint. This is a built-in scope for every application that refers to the static list of permissions configured on the application registration. A `scope` value of `https://graph.microsoft.com/.default` is functionally the same as the v1.0 endpoints `resource=https://graph.microsoft.com` - namely, it requests a token with the scopes on Microsoft Graph that the application has registered for in the Azure portal. It is constructed using the resource URI + `/.default` (e.g. if the resource URI is `https://contosoApp.com`, then the scope requested would be `https://contosoApp.com/.default`). See the [section on trailing slashes](#trailing-slash-and-default) for cases where you must include a second slash to correctly request the token.
265268

266-
The /.default scope can be used in any OAuth 2.0 flow, but is necessary in the [On-Behalf-Of flow](v2-oauth2-on-behalf-of-flow.md) and [client credentials flow](v2-oauth2-client-creds-grant-flow.md).
269+
The /.default scope can be used in any OAuth 2.0 flow, but is necessary in the [On-Behalf-Of flow](v2-oauth2-on-behalf-of-flow.md) and [client credentials flow](v2-oauth2-client-creds-grant-flow.md), as well as when using the v2 admin consent endpoint to request application permissions.
267270

268271
> [!NOTE]
269272
> Clients can't combine static (`/.default`) and dynamic consent in a single request. Thus, `scope=https://graph.microsoft.com/.default+mail.read` will result in an error due to the combination of scope types.
@@ -278,15 +281,15 @@ Because `/.default` is functionally identical to the `resource`-centric v1.0 end
278281

279282
#### Example 1: The user, or tenant admin, has granted permissions
280283

281-
The user (or a tenant administrator) has granted the client the Microsoft Graph permissions `mail.read` and `user.read`. If the client makes a request for `scope=https://graph.microsoft.com/.default`, then no consent prompt will be shown regardless of the contents of the client applications registered permissions for Microsoft Graph. A token would be returned containing the scopes `mail.read` and `user.read`.
284+
In this example, the user (or a tenant administrator) has granted the client the Microsoft Graph permissions `mail.read` and `user.read`. If the client makes a request for `scope=https://graph.microsoft.com/.default`, then no consent prompt will be shown regardless of the contents of the client applications registered permissions for Microsoft Graph. A token would be returned containing the scopes `mail.read` and `user.read`.
282285

283286
#### Example 2: The user hasn't granted permissions between the client and the resource
284287

285-
No consent for the user exists between the client and Microsoft Graph. The client has registered for the `user.read` and `contacts.read` permissions, as well as the Azure Key Vault scope `https://vault.azure.net/user_impersonation`. When the client requests a token for `scope=https://graph.microsoft.com/.default`, the user will see a consent screen for the `user.read`, `contacts.read`, and the Key Vault `user_impersonation` scopes. The token returned will have just the `user.read` and `contacts.read` scopes in it.
288+
In this example, no consent for the user exists between the client and Microsoft Graph. The client has registered for the `user.read` and `contacts.read` permissions, as well as the Azure Key Vault scope `https://vault.azure.net/user_impersonation`. When the client requests a token for `scope=https://graph.microsoft.com/.default`, the user will see a consent screen for the `user.read`, `contacts.read`, and the Key Vault `user_impersonation` scopes. The token returned will have just the `user.read` and `contacts.read` scopes in it and only be usable against Microsoft Graph.
286289

287290
#### Example 3: The user has consented and the client requests additional scopes
288291

289-
The user has already consented to `mail.read` for the client. The client has registered for the `contacts.read` scope in its registration. When the client makes a request for a token using `scope=https://graph.microsoft.com/.default` and requests consent through `prompt=consent`, then the user will see a consent screen for only and all the permissions registered by the application. `contacts.read` will be present in the consent screen, but `mail.read` will not. The token returned will be for Microsoft Graph and will contain `mail.read` and `contacts.read`.
292+
In this example, the user has already consented to `mail.read` for the client. The client has registered for the `contacts.read` scope in its registration. When the client makes a request for a token using `scope=https://graph.microsoft.com/.default` and requests consent through `prompt=consent`, then the user will see a consent screen for all (and only) the permissions registered by the application. `contacts.read` will be present in the consent screen, but `mail.read` will not. The token returned will be for Microsoft Graph and will contain `mail.read` and `contacts.read`.
290293

291294
### Using the /.default scope with the client
292295

@@ -303,7 +306,13 @@ response_type=token //code or a hybrid flow is also possible here
303306
&state=1234
304307
```
305308

306-
This produces a consent screen for all registered permissions (if applicable based on the above descriptions of consent and `/.default`), then returns an id_token, rather than an access token. This behavior exists for certain legacy clients moving from ADAL to MSAL, and should not be used by new clients targeting the Microsoft identity platform endpoint.
309+
This produces a consent screen for all registered permissions (if applicable based on the above descriptions of consent and `/.default`), then returns an id_token, rather than an access token. This behavior exists for certain legacy clients moving from ADAL to MSAL, and **should not** be used by new clients targeting the Microsoft identity platform endpoint.
310+
311+
### Trailing slash and /.default
312+
313+
Some resource URIs have a trailing slash (`https://contoso.com/` as opposed to `https://contoso.com`), which can cause problems with token validation. This can occur primarily when requesting a token for Azure Resource Management (`https://management.azure.com/`), which has a trailing slash on their resource URI and requires it to be present when the token is requested. Thus, when requesting a token for `https://management.azure.com/` and using `/.default`, you must request `https://management.azure.com//.default` - note the double slash!
314+
315+
In general - if you've validated that the token is being issued, and the token is being rejected by the API that should accept it, consider adding a second slash and trying again. This happens because the login server emits a token with the audience matching the URIs in the `scope` parameter - with `/.default` removed from the end. If this removes the trailing slash, the login server still processes the request and validates it against the resource URI, even though they no longer match - this is non-standard and should not be relied on by your application.
307316

308317
## Troubleshooting permissions and consent
309318

0 commit comments

Comments
 (0)