Skip to content

Commit 5ec7be9

Browse files
authored
Merge pull request #101620 from BobbySchmidt2/scenario-protected-web-api
Edit pass: Scenario protected web api
2 parents cd71014 + 89f62b0 commit 5ec7be9

5 files changed

+132
-107
lines changed

articles/active-directory/develop/scenario-protected-web-api-app-configuration.md

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,24 @@ ms.custom: aaddev
2222

2323
# Protected web API: Code configuration
2424

25-
To configure the code for your protected web API, you need to understand what defines APIs as protected, how to configure a bearer token, and how to validate the token.
25+
To configure the code for your protected web API, you need to understand:
2626

27-
## What defines ASP.NET/ASP.NET Core APIs as protected?
27+
- What defines APIs as protected.
28+
- How to configure a bearer token.
29+
- How to validate the token.
2830

29-
Like web apps, the ASP.NET/ASP.NET Core web APIs are "protected" because their controller actions are prefixed with the `[Authorize]` attribute. So the controller actions can be called only if the API is called with an identity that's authorized.
31+
## What defines ASP.NET and ASP.NET Core APIs as protected?
32+
33+
Like web apps, the ASP.NET and ASP.NET Core web APIs are protected because their controller actions are prefixed with the **[Authorize]** attribute. The controller actions can be called only if the API is called with an authorized identity.
3034

3135
Consider the following questions:
3236

33-
- How does the web API know the identity of the app that calls it? (Only an app can call a web API.)
34-
- If the app called the web API on behalf of a user, what's the user's identity?
37+
- Only an app can call a web API. How does the API know the identity of the app that calls it?
38+
- If the app calls the API on behalf of a user, what's the user's identity?
3539

3640
## Bearer token
3741

38-
The information about the identity of the app, and about the user (unless the web app accepts service-to-service calls from a daemon app), is held in the bearer token that's set in the header when the app is called.
42+
The bearer token that's set in the header when the app is called holds information about the app identity. It also holds information about the user unless the web app accepts service-to-service calls from a daemon app.
3943

4044
Here's a C# code example that shows a client calling the API after it acquires a token with Microsoft Authentication Library for .NET (MSAL.NET):
4145

@@ -52,7 +56,9 @@ HttpResponseMessage response = await _httpClient.GetAsync(apiUri);
5256
```
5357

5458
> [!IMPORTANT]
55-
> The bearer token was requested by a client application to the Microsoft identity platform endpoint *for the web API*. The web API is the only application that should verify the token and view the claims it contains. Client apps should never try to inspect the claims in tokens. (The web API could require, in the future, that the token be encrypted. This requirement would prevent access for client apps that can view access tokens.)
59+
> A client application requests the bearer token to the Microsoft identity platform endpoint *for the web API*. The web API is the only application that should verify the token and view the claims it contains. Client apps should never try to inspect the claims in tokens.
60+
>
61+
> In the future, the web API might require that the token be encrypted. This requirement would prevent access for client apps that can view access tokens.
5662

5763
## JwtBearer configuration
5864

@@ -88,9 +94,9 @@ This section describes how to configure a bearer token.
8894

8995
### Code initialization
9096

91-
When an app is called on a controller action that holds an `[Authorize]` attribute, ASP.NET/ASP.NET Core looks at the bearer token in the Authorization header of the calling request and extracts the access token. The token is then forwarded to the JwtBearer middleware, which calls Microsoft IdentityModel Extensions for .NET.
97+
When an app is called on a controller action that holds an **[Authorize]** attribute, ASP.NET and ASP.NET Core extract the access token from the Authorization header's bearer token. The access token is then forwarded to the JwtBearer middleware, which calls Microsoft IdentityModel Extensions for .NET.
9298

93-
In ASP.NET Core, this middleware is initialized in the Startup.cs file:
99+
In ASP.NET Core, this middleware is initialized in the Startup.cs file.
94100

95101
```csharp
96102
using Microsoft.AspNetCore.Authentication.JwtBearer;
@@ -102,7 +108,7 @@ The middleware is added to the web API by this instruction:
102108
services.AddAzureAdBearer(options => Configuration.Bind("AzureAd", options));
103109
```
104110

105-
Currently, the ASP.NET Core templates create Azure Active Directory (Azure AD) web APIs that sign in users within your organization or any organization, not with personal accounts. But you can easily change them to use the Microsoft identity platform endpoint by adding this code to the Startup.cs file:
111+
Currently, the ASP.NET Core templates create Azure Active Directory (Azure AD) web APIs that sign in users within your organization or any organization. They don't sign in users with personal accounts. But you can change the templates to use the Microsoft identity platform endpoint by adding this code to Startup.cs:
106112

107113
```csharp
108114
services.Configure<JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, options =>
@@ -124,40 +130,42 @@ services.Configure<JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationSche
124130
});
125131
```
126132

127-
This code snippet is extracted from the ASP.NET Core Web Api incremental tutorial in [Microsoft.Identity.Web/WebApiServiceCollectionExtensions.cs#L50-L63](https://github.com/Azure-Samples/active-directory-dotnet-native-aspnetcore-v2/blob/154282843da2fc2958fad151e2a11e521e358d42/Microsoft.Identity.Web/WebApiServiceCollectionExtensions.cs#L50-L63). The `AddProtectedWebApi` method, which does a lot more, is called from the Startup.cs
133+
The preceding code snippet is extracted from the ASP.NET Core web API incremental tutorial in [Microsoft.Identity.Web/WebApiServiceCollectionExtensions.cs#L50-L63](https://github.com/Azure-Samples/active-directory-dotnet-native-aspnetcore-v2/blob/154282843da2fc2958fad151e2a11e521e358d42/Microsoft.Identity.Web/WebApiServiceCollectionExtensions.cs#L50-L63). The **AddProtectedWebApi** method, which does more than the snippet shows, is called from Startup.cs.
128134
129135
## Token validation
130136

131-
The JwtBearer middleware, like the OpenID Connect middleware in web apps, is directed by `TokenValidationParameters` to validate the token. The token is decrypted (as needed), the claims are extracted, and the signature is verified. The middleware then validates the token by checking for this data:
137+
In the preceding snippet, the JwtBearer middleware, like the OpenID Connect middleware in web apps, validates the token based on the value of `TokenValidationParameters`. The token is decrypted as needed, the claims are extracted, and the signature is verified. The middleware then validates the token by checking for this data:
132138

133-
- It's targeted for the web API (audience).
134-
- It was issued for an app that's allowed to call the web API (sub).
135-
- It was issued by a trusted security token service (STS) (issuer).
136-
- Its lifetime is in range (expiry).
137-
- It wasn't tampered with (signature).
139+
- Audience: The token is targeted for the web API.
140+
- Sub: It was issued for an app that's allowed to call the web API.
141+
- Issuer: It was issued by a trusted security token service (STS).
142+
- Expiry: Its lifetime is in range.
143+
- Signature: It wasn't tampered with.
138144

139-
There can also be special validations. For example, it's possible to validate that signing keys (when embedded in a token) are trusted and that the token isn't being replayed. Finally, some protocols require specific validations.
145+
There can also be special validations. For example, it's possible to validate that signing keys, when embedded in a token, are trusted and that the token isn't being replayed. Finally, some protocols require specific validations.
140146

141147
### Validators
142148

143-
The validation steps are captured in validators, which are all in the [Microsoft IdentityModel Extensions for .NET](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) open-source library, in one source file: [Microsoft.IdentityModel.Tokens/Validators.cs](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/master/src/Microsoft.IdentityModel.Tokens/Validators.cs).
149+
The validation steps are captured in validators, which are provided by the [Microsoft IdentityModel Extensions for .NET](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) open-source library. The validators are defined in the library source file [Microsoft.IdentityModel.Tokens/Validators.cs](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/master/src/Microsoft.IdentityModel.Tokens/Validators.cs).
144150
145-
The validators are described in this table:
151+
This table describes the validators:
146152

147153
| Validator | Description |
148154
|---------|---------|
149-
| `ValidateAudience` | Ensures the token is for the application that validates the token (for me). |
150-
| `ValidateIssuer` | Ensures the token was issued by a trusted STS (from someone I trust). |
151-
| `ValidateIssuerSigningKey` | Ensures the application validating the token trusts the key that was used to sign the token. (Special case where the key is embedded in the token. Not usually required.) |
152-
| `ValidateLifetime` | Ensures the token is still (or already) valid. The validator checks if the lifetime of the token (`notbefore` and `expires` claims) is in range. |
153-
| `ValidateSignature` | Ensures the token hasn't been tampered with. |
154-
| `ValidateTokenReplay` | Ensures the token isn't replayed. (Special case for some onetime use protocols.) |
155+
| **ValidateAudience** | Ensures the token is for the application that validates the token for you. |
156+
| **ValidateIssuer** | Ensures the token was issued by a trusted STS, meaning it's from someone you trust. |
157+
| **ValidateIssuerSigningKey** | Ensures the application validating the token trusts the key that was used to sign the token. There's a special case where the key is embedded in the token. But this case doesn't usually arise. |
158+
| **ValidateLifetime** | Ensures the token is still or already valid. The validator checks if the lifetime of the token is in the range specified by the **notbefore** and **expires** claims. |
159+
| **ValidateSignature** | Ensures the token hasn't been tampered with. |
160+
| **ValidateTokenReplay** | Ensures the token isn't replayed. There's a special case for some onetime-use protocols. |
161+
162+
The validators are associated with properties of the **TokenValidationParameters** class. The properties are initialized from the ASP.NET and ASP.NET Core configuration.
155163

156-
The validators are all associated with properties of the `TokenValidationParameters` class, themselves initialized from the ASP.NET/ASP.NET Core configuration. In most cases, you won't have to change the parameters. There's one exception, for apps that aren't single tenants. (That is, web apps that accept users from any organization or from personal Microsoft accounts.) In this case, the issuer must be validated.
164+
In most cases, you don't need to change the parameters. Apps that aren't single tenants are exceptions. These web apps accept users from any organization or from personal Microsoft accounts. Issuers in this case must be validated.
157165

158166
## Token validation in Azure Functions
159167

160-
It's also possible to validate incoming access tokens in Azure functions. You can find examples of validating tokens in Azure functions in [Dotnet](https://github.com/Azure-Samples/ms-identity-dotnet-webapi-azurefunctions), [NodeJS](https://github.com/Azure-Samples/ms-identity-nodejs-webapi-azurefunctions), and [Python](https://github.com/Azure-Samples/ms-identity-python-webapi-azurefunctions).
168+
You can also validate incoming access tokens in Azure Functions. You can find examples of such validation in [Microsoft .NET](https://github.com/Azure-Samples/ms-identity-dotnet-webapi-azurefunctions), [NodeJS](https://github.com/Azure-Samples/ms-identity-nodejs-webapi-azurefunctions), and [Python](https://github.com/Azure-Samples/ms-identity-python-webapi-azurefunctions).
161169
162170
## Next steps
163171

0 commit comments

Comments
 (0)