Skip to content

Commit 77e3678

Browse files
author
Matthew Henderson
committed
updating protocol reference
1 parent 9283fb5 commit 77e3678

File tree

1 file changed

+55
-44
lines changed

1 file changed

+55
-44
lines changed

articles/app-service/overview-managed-identity.md

Lines changed: 55 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: Learn how managed identities work in Azure App Service and Azure Fu
44
author: mattchenderson
55

66
ms.topic: article
7-
ms.date: 03/04/2020
7+
ms.date: 04/14/2020
88
ms.author: mahender
99
ms.reviewer: yevbronsh
1010

@@ -17,7 +17,8 @@ ms.reviewer: yevbronsh
1717
1818
This topic shows you how to create a managed identity for App Service and Azure Functions applications and how to use it to access other resources. A managed identity from Azure Active Directory (AAD) allows your app to easily access other AAD-protected resources such as Azure Key Vault. The identity is managed by the Azure platform and does not require you to provision or rotate any secrets. For more about managed identities in AAD, see [Managed identities for Azure resources](../active-directory/managed-identities-azure-resources/overview.md).
1919

20-
Your application can be granted two types of identities:
20+
Your application can be granted two types of identities:
21+
2122
- A **system-assigned identity** is tied to your application and is deleted if your app is deleted. An app can only have one system-assigned identity.
2223
- A **user-assigned identity** is a standalone Azure resource that can be assigned to your app. An app can have multiple user-assigned identities.
2324

@@ -54,6 +55,7 @@ The following steps will walk you through creating a web app and assigning it an
5455
```azurecli-interactive
5556
az login
5657
```
58+
5759
2. Create a web application using the CLI. For more examples of how to use the CLI with App Service, see [App Service CLI samples](../app-service/samples-cli.md):
5860
5961
```azurecli-interactive
@@ -81,10 +83,10 @@ The following steps will walk you through creating a web app and assigning it an
8183
```azurepowershell-interactive
8284
# Create a resource group.
8385
New-AzResourceGroup -Name myResourceGroup -Location $location
84-
86+
8587
# Create an App Service plan in Free tier.
8688
New-AzAppServicePlan -Name $webappname -Location $location -ResourceGroupName myResourceGroup -Tier Free
87-
89+
8890
# Create a web app.
8991
New-AzWebApp -Name $webappname -Location $location -AppServicePlan $webappname -ResourceGroupName myResourceGroup
9092
```
@@ -100,18 +102,20 @@ The following steps will walk you through creating a web app and assigning it an
100102
An Azure Resource Manager template can be used to automate deployment of your Azure resources. To learn more about deploying to App Service and Functions, see [Automating resource deployment in App Service](../app-service/deploy-complex-application-predictably.md) and [Automating resource deployment in Azure Functions](../azure-functions/functions-infrastructure-as-code.md).
101103
102104
Any resource of type `Microsoft.Web/sites` can be created with an identity by including the following property in the resource definition:
105+
103106
```json
104107
"identity": {
105108
"type": "SystemAssigned"
106-
}
109+
}
107110
```
108111

109-
> [!NOTE]
112+
> [!NOTE]
110113
> An application can have both system-assigned and user-assigned identities at the same time. In this case, the `type` property would be `SystemAssigned,UserAssigned`
111114
112115
Adding the system-assigned type tells Azure to create and manage the identity for your application.
113116

114117
For example, a web app might look like the following:
118+
115119
```json
116120
{
117121
"apiVersion": "2016-08-01",
@@ -135,6 +139,7 @@ For example, a web app might look like the following:
135139
```
136140

137141
When the site is created, it has the following additional properties:
142+
138143
```json
139144
"identity": {
140145
"type": "SystemAssigned",
@@ -145,7 +150,6 @@ When the site is created, it has the following additional properties:
145150

146151
The tenantId property identifies what AAD tenant the identity belongs to. The principalId is a unique identifier for the application's new identity. Within AAD, the service principal has the same name that you gave to your App Service or Azure Functions instance.
147152

148-
149153
## Add a user-assigned identity
150154

151155
Creating an app with a user-assigned identity requires that you create the identity and then add its resource identifier to your app config.
@@ -173,21 +177,23 @@ First, you'll need to create a user-assigned identity resource.
173177
An Azure Resource Manager template can be used to automate deployment of your Azure resources. To learn more about deploying to App Service and Functions, see [Automating resource deployment in App Service](../app-service/deploy-complex-application-predictably.md) and [Automating resource deployment in Azure Functions](../azure-functions/functions-infrastructure-as-code.md).
174178

175179
Any resource of type `Microsoft.Web/sites` can be created with an identity by including the following block in the resource definition, replacing `<RESOURCEID>` with the resource ID of the desired identity:
180+
176181
```json
177182
"identity": {
178183
"type": "UserAssigned",
179184
"userAssignedIdentities": {
180185
"<RESOURCEID>": {}
181186
}
182-
}
187+
}
183188
```
184189

185-
> [!NOTE]
190+
> [!NOTE]
186191
> An application can have both system-assigned and user-assigned identities at the same time. In this case, the `type` property would be `SystemAssigned,UserAssigned`
187192
188193
Adding the user-assigned type tells Azure to use the user-assigned identity specified for your application.
189194

190195
For example, a web app might look like the following:
196+
191197
```json
192198
{
193199
"apiVersion": "2016-08-01",
@@ -215,6 +221,7 @@ For example, a web app might look like the following:
215221
```
216222

217223
When the site is created, it has the following additional properties:
224+
218225
```json
219226
"identity": {
220227
"type": "UserAssigned",
@@ -229,7 +236,6 @@ When the site is created, it has the following additional properties:
229236

230237
The principalId is a unique identifier for the identity that's used for AAD administration. The clientId is a unique identifier for the application's new identity that's used for specifying which identity to use during runtime calls.
231238

232-
233239
## Obtain tokens for Azure resources
234240

235241
An app can use its managed identity to get tokens to access other resources protected by AAD, such as Azure Key Vault. These tokens represent the application accessing the resource, and not any specific user of the application.
@@ -245,56 +251,61 @@ There is a simple REST protocol for obtaining a token in App Service and Azure F
245251

246252
An app with a managed identity has two environment variables defined:
247253

248-
- MSI_ENDPOINT - the URL to the local token service.
249-
- MSI_SECRET - a header used to help mitigate server-side request forgery (SSRF) attacks. The value is rotated by the platform.
254+
- IDENTITY_ENDPOINT - the URL to the local token service.
255+
- IDENTITY_HEADER - a header used to help mitigate server-side request forgery (SSRF) attacks. The value is rotated by the platform.
250256

251-
The **MSI_ENDPOINT** is a local URL from which your app can request tokens. To get a token for a resource, make an HTTP GET request to this endpoint, including the following parameters:
257+
The **IDENTITY_ENDPOINT** is a local URL from which your app can request tokens. To get a token for a resource, make an HTTP GET request to this endpoint, including the following parameters:
252258

253-
> |Parameter name|In|Description|
254-
> |-----|-----|-----|
255-
> |resource|Query|The AAD resource URI of the resource for which a token should be obtained. This could be one of the [Azure services that support Azure AD authentication](../active-directory/managed-identities-azure-resources/services-support-managed-identities.md#azure-services-that-support-azure-ad-authentication) or any other resource URI.|
256-
> |api-version|Query|The version of the token API to be used. "2017-09-01" is currently the only version supported.|
257-
> |secret|Header|The value of the MSI_SECRET environment variable. This header is used to help mitigate server-side request forgery (SSRF) attacks.|
258-
> |clientid|Query|(Optional unless for user-assigned) The ID of the user-assigned identity to be used. If omitted, the system-assigned identity is used.|
259+
> | Parameter name | In | Description |
260+
> |-------------------|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
261+
> | resource | Query | The AAD resource URI of the resource for which a token should be obtained. This could be one of the [Azure services that support Azure AD authentication](../active-directory/managed-identities-azure-resources/services-support-managed-identities.md#azure-services-that-support-azure-ad-authentication) or any other resource URI. |
262+
> | api-version | Query | The version of the token API to be used. Please use "2019-08-01" or later. |
263+
> | X-IDENTITY-HEADER | Header | The value of the IDENTITY_HEADER environment variable. This header is used to help mitigate server-side request forgery (SSRF) attacks. |
264+
> | client_id | Query | (Optional) The client ID of the user-assigned identity to be used. Cannot be used on a request that includes `principal_id`, `mi_res_id`, or `object_id`. If all ID parameters (`client_id`, `principal_id`, `object_id`, and `mi_res_id`) are omitted, the system-assigned identity is used. |
265+
> | principal_id | Query | (Optional) The principal ID of the user-assigned identity to be used. `object_id` is an alias that may be used instead. Cannot be used on a request that includes client_id, mi_res_id, or object_id. If all ID parameters (`client_id`, `principal_id`, `object_id`, and `mi_res_id`) are omitted, the system-assigned identity is used. |
266+
> | mi_res_id | Query | (Optional) The Azure resource ID of the user-assigned identity to be used. Cannot be used on a request that includes `principal_id`, `client_id`, or `object_id`. If all ID parameters (`client_id`, `principal_id`, `object_id`, and `mi_res_id`) are omitted, the system-assigned identity is used. |
259267
260268
> [!IMPORTANT]
261-
> If you are attempting to obtain tokens for user-assigned identities, you must include the `clientid` property. Otherwise the token service will attempt to obtain a token for a system-assigned identity, which may or may not exist.
269+
> If you are attempting to obtain tokens for user-assigned identities, you must include one of the optional properties. Otherwise the token service will attempt to obtain a token for a system-assigned identity, which may or may not exist.
262270
263271
A successful 200 OK response includes a JSON body with the following properties:
264272

265-
> |Property name|Description|
266-
> |-------------|----------|
267-
> |access_token|The requested access token. The calling web service can use this token to authenticate to the receiving web service.|
268-
> |expires_on|The time when the access token expires. The date is represented as the number of seconds from 1970-01-01T0:0:0Z UTC until the expiration time. This value is used to determine the lifetime of cached tokens.|
269-
> |resource|The App ID URI of the receiving web service.|
270-
> |token_type|Indicates the token type value. The only type that Azure AD supports is Bearer. For more information about bearer tokens, see [The OAuth 2.0 Authorization Framework: Bearer Token Usage (RFC 6750)](https://www.rfc-editor.org/rfc/rfc6750.txt).|
273+
> | Property name | Description |
274+
> |---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
275+
> | access_token | The requested access token. The calling web service can use this token to authenticate to the receiving web service. |
276+
> | client_id | The client ID of the identity that was used. |
277+
> | expires_on | The timespan when the access token expires. The date is represented as the number of seconds from "1970-01-01T0:0:0Z UTC" (corresponds to the token's `exp` claim). |
278+
> | not_before | The timespan when the access token takes effect, and can be accepted. The date is represented as the number of seconds from "1970-01-01T0:0:0Z UTC" (corresponds to the token's `nbf` claim). |
279+
> | resource | The resource the access token was requested for, which matches the `resource` query string parameter of the request. |
280+
> | token_type | Indicates the token type value. The only type that Azure AD supports is FBearer. For more information about bearer tokens, see [The OAuth 2.0 Authorization Framework: Bearer Token Usage (RFC 6750)](https://www.rfc-editor.org/rfc/rfc6750.txt). |
271281
272-
This response is the same as the [response for the AAD service-to-service access token request](../active-directory/develop/v2-oauth2-client-creds-grant-flow.md#get-a-token).
282+
This response is the same as the [response for the AAD service-to-service access token request](../active-directory/develop/v1-oauth2-client-creds-grant-flow.md#service-to-service-access-token-response).
273283

274284
> [!NOTE]
275-
> Environment variables are set up when the process first starts, so after enabling a managed identity for your application, you may need to restart your application, or redeploy its code, before `MSI_ENDPOINT` and `MSI_SECRET` are available to your code.
285+
> An older version of this protocol, using the "2017-09-01" API version, used the `secret` header instead of `X-IDENTITY-HEADER` and only accepted the `clientid` property for user-assigned. It also returned the `expires_on` in a timestamp format. MSI_ENDPOINT can be used as an alias for IDENTITY_ENDPOINT, and MSI_SECRET can be used as an alias for IDENTITY_HEADER.
276286
277287
### REST protocol examples
278288

279289
An example request might look like the following:
280290

281-
```
282-
GET /MSI/token?resource=https://vault.azure.net&api-version=2017-09-01 HTTP/1.1
291+
```http
292+
GET /MSI/token?resource=https://vault.azure.net&api-version=2019-08-01 HTTP/1.1
283293
Host: localhost:4141
284-
Secret: 853b9a84-5bfa-4b22-a3f3-0b9a43d9ad8a
294+
X-IDENTITY-HEADER: 853b9a84-5bfa-4b22-a3f3-0b9a43d9ad8a
285295
```
286296

287297
And a sample response might look like the following:
288298

289-
```
299+
```http
290300
HTTP/1.1 200 OK
291301
Content-Type: application/json
292302
293303
{
294304
"access_token": "eyJ0eXAi…",
295-
"expires_on": "09/14/2017 00:00:00 PM +00:00",
305+
"expires_on": "1586984735",
296306
"resource": "https://vault.azure.net",
297-
"token_type": "Bearer"
307+
"token_type": "Bearer",
308+
"client_id": "5E29463D-71DA-4FE0-8E69-999B57DB23B0"
298309
}
299310
```
300311

@@ -310,8 +321,8 @@ private readonly HttpClient _client;
310321
// ...
311322
public async Task<HttpResponseMessage> GetToken(string resource) {
312323
var request = new HttpRequestMessage(HttpMethod.Get,
313-
String.Format("{0}/?resource={1}&api-version=2017-09-01", Environment.GetEnvironmentVariable("MSI_ENDPOINT"), resource));
314-
request.Headers.Add("Secret", Environment.GetEnvironmentVariable("MSI_SECRET"));
324+
String.Format("{0}/?resource={1}&api-version=2019-08-01", Environment.GetEnvironmentVariable("IDENTITY_ENDPOINT"), resource));
325+
request.Headers.Add("X-IDENTITY-HEADER", Environment.GetEnvironmentVariable("IDENTITY_HEADER"));
315326
return await _client.SendAsync(request);
316327
}
317328
```
@@ -322,9 +333,9 @@ public async Task<HttpResponseMessage> GetToken(string resource) {
322333
const rp = require('request-promise');
323334
const getToken = function(resource, cb) {
324335
let options = {
325-
uri: `${process.env["MSI_ENDPOINT"]}/?resource=${resource}&api-version=2017-09-01`,
336+
uri: `${process.env["IDENTITY_ENDPOINT"]}/?resource=${resource}&api-version=2019-08-01`,
326337
headers: {
327-
'Secret': process.env["MSI_SECRET"]
338+
'X-IDENTITY-HEADER': process.env["IDENTITY_HEADER"]
328339
}
329340
};
330341
rp(options)
@@ -338,12 +349,12 @@ const getToken = function(resource, cb) {
338349
import os
339350
import requests
340351

341-
msi_endpoint = os.environ["MSI_ENDPOINT"]
342-
msi_secret = os.environ["MSI_SECRET"]
352+
identity_endpoint = os.environ["IDENTITY_ENDPOINT"]
353+
identity_header = os.environ["IDENTITY_HEADER"]
343354

344355
def get_bearer_token(resource_uri):
345-
token_auth_uri = f"{msi_endpoint}?resource={resource_uri}&api-version=2017-09-01"
346-
head_msi = {'Secret':msi_secret}
356+
token_auth_uri = f"{identity_endpoint}?resource={resource_uri}&api-version=2019-08-01"
357+
head_msi = {'X-IDENTITY-HEADER':identity_header}
347358

348359
resp = requests.get(token_auth_uri, headers=head_msi)
349360
access_token = resp.json()['access_token']
@@ -355,8 +366,8 @@ def get_bearer_token(resource_uri):
355366

356367
```powershell
357368
$resourceURI = "https://<AAD-resource-URI-for-resource-to-obtain-token>"
358-
$tokenAuthURI = $env:MSI_ENDPOINT + "?resource=$resourceURI&api-version=2017-09-01"
359-
$tokenResponse = Invoke-RestMethod -Method Get -Headers @{"Secret"="$env:MSI_SECRET"} -Uri $tokenAuthURI
369+
$tokenAuthURI = $env:IDENTITY_ENDPOINT + "?resource=$resourceURI&api-version=2019-08-01"
370+
$tokenResponse = Invoke-RestMethod -Method Get -Headers @{"X-IDENTITY-HEADER"="$env:IDENTITY_HEADER"} -Uri $tokenAuthURI
360371
$accessToken = $tokenResponse.access_token
361372
```
362373

0 commit comments

Comments
 (0)