You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# How to manually validate a JWT access token using the Microsoft identity platform (formerly Azure Active Directory for developers)
20
+
# How to manually validate a JWT access token using the Microsoft identity platform
21
+
22
+
-[Overview](#overview)
23
+
-[About this sample](#about-this-sample)
24
+
-[Scenario: protecting a Web API - acquiring a token for the protected Web API](#scenario-protecting-a-web-api---acquiring-a-token-for-the-protected-web-api)
25
+
-[Token Validation](#token-validation)
26
+
-[What to validate?](#what-to-validate)
27
+
-[Validating the claims](#validating-the-claims)
28
+
-[Prerequisites](#prerequisites)
29
+
-[Setup](#setup)
30
+
-[Step 1: Clone or download this repository](#step-1--clone-or-download-this-repository)
31
+
-[Register the sample application(s) with your Azure Active Directory tenant](#register-the-sample-applications-with-your-azure-active-directory-tenant)
32
+
-[Choose the Azure AD tenant where you want to create your applications](#choose-the-azure-ad-tenant-where-you-want-to-create-your-applications)
33
+
-[Register the service app (TodoListService-ManualJwt)](#register-the-service-app-todolistservice-manualjwt)
34
+
-[Register the client app (TodoListClient-ManualJwt)](#register-the-client-app-todolistclient-manualjwt)
35
+
-[Running the sample](#running-the-sample)
36
+
-[Explore the sample](#explore-the-sample)
37
+
-[About The Code](#about-the-code)
38
+
-[Providing your own Custom token validation handler](#providing-your-own-custom-token-validation-handler)
39
+
-[How To Recreate This Sample](#how-to-recreate-this-sample)
40
+
-[Creating the TodoListService-ManualJwt Project](#creating-the-todolistservice-manualjwt-project)
41
+
-[Creating the TodoListClient Project](#creating-the-todolistclient-project)
42
+
-[How to deploy this sample to Azure](#how-to-deploy-this-sample-to-azure)
43
+
-[Create and publish the `TodoListService-ManualJwt` to an Azure Web Site](#create-and-publish-the-todolistservice-manualjwt-to-an-azure-web-site)
44
+
-[Update the Active Directory tenant application registration for `TodoListService-ManualJwt`](#update-the-active-directory-tenant-application-registration-for-todolistservice-manualjwt)
45
+
-[Update the `TodoListClient-ManualJwt` to call the `TodoListService-ManualJwt` Running in Azure Web Sites](#update-the-todolistclient-manualjwt-to-call-the-todolistservice-manualjwt-running-in-azure-web-sites)
46
+
-[Azure Government Deviations](#azure-government-deviations)
47
+
-[Troubleshooting](#troubleshooting)
48
+
-[Community Help and Support](#community-help-and-support)
This sample demonstrates how to manually validate an access token issued to a web API protected by the Microsoft Identity Platform. Here a .NET Desktop App (WPF) calls a protected ASP.NET Web API that is secured using Azure AD.
57
+
15
58
## About this sample
16
59
17
60
A Web API that accepts bearer token as a proof of authentication is secured by [validating the token](https://docs.microsoft.com/en-us/azure/active-directory/develop/access-tokens#validating-tokens) they receive from the callers. When a developer generates a skeleton Web API code using [Visual Studio](https://aka.ms/vsdownload), token validation libraries and code to carry out basic token validation is automatically generated for the project. An example of the generated code using the [asp.net security middleware](https://github.com/aspnet/Security) and [Microsoft Identity Model Extension for .NET](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet) to validate tokens is provided below.
@@ -205,7 +248,7 @@ Open the project in your IDE (like Visual Studio or Visual Studio Code) to confi
205
248
1. Open the `TodoListClient\App.Config` file.
206
249
1. Find the key `ida:Tenant` and replace the existing value with your Azure AD tenant name.
207
250
1. Find the key `ida:ClientId` and replace the existing value with the application ID (clientId) of `TodoListClient-ManualJwt` app copied from the Azure portal.
208
-
1. Find the key `todo:TodoListResourceId` and replace the value with the App ID URI you registered earlier, when exposing an API. For instance use `api://<application_id>`.
251
+
1. Find the key `todo:TodoListResourceId` and replace the existing value with the App ID URI you registered earlier, when exposing an API. For instance use `api://<application_id>`.
209
252
1. Find the key `todo:TodoListBaseAddress` and replace the existing value with the base address of `TodoListService-ManualJwt` (by default `https://localhost:44324`).
210
253
211
254
## Running the sample
@@ -214,32 +257,89 @@ Open the project in your IDE (like Visual Studio or Visual Studio Code) to confi
214
257
>
215
258
> Clean the solution, rebuild the solution, and run it. You might want to go into the solution properties and set both projects as startup projects, with the service project starting first.
216
259
260
+
## Explore the sample
261
+
217
262
Explore the sample by signing in, adding items to the To Do list, removing the user account, and starting again. Notice that if you stop the application without removing the user account, the next time you run the application you won't be prompted to sign in again - that is the sample implements a [persistent cache for MSAL](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/token-cache-serialization), and remembers the tokens from the previous run.
218
263
219
-
> Did the sample not work for you as expected? Did you encounter issues trying this sample? Then please reach out to us using the [GitHub Issues](../../issues) page.
264
+
> :information_source:Did the sample not work for you as expected? Did you encounter issues trying this sample? Then please reach out to us using the [GitHub Issues](../../issues) page.
220
265
221
266
> [Consider taking a moment to share your experience with us.](https://forms.office.com/Pages/ResponsePage.aspx?id=v4j5cvGGr0GRqy180BHbR73pcsbpbxNJuZCMKN0lURpUMjFRQjA0RElFUFNPV0dCUVBGQzk0QkhKTiQlQCN0PWcu)
222
267
223
268
## About The Code
224
269
225
-
The manual JWT validation occurs in the [TokenValidationHandler](https://github.com/Azure-Samples/active-directory-dotnet-webapi-manual-jwt-validation/blob/master/TodoListService-ManualJwt/Global.asax.cs#L58) implementation in the `Global.aspx.cs` file in the TodoListService-ManualJwt project. Each time a call is made to the web API, the [TokenValidationHandler.SendAsync()](https://github.com/Azure-Samples/active-directory-dotnet-webapi-manual-jwt-validation/blob/4b80657c5506c8cb30af67b9f61bb6aa68dfca58/TodoListService-ManualJwt/Global.asax.cs#L80) handler is executed:
270
+
The manual JWT validation occurs in the [TokenValidationHandler](https://github.com/Azure-Samples/active-directory-dotnet-webapi-manual-jwt-validation/blob/master/TodoListService-ManualJwt/Global.asax.cs#L58) implementation in the `Global.aspx.cs` file in the TodoListService-ManualJwt project.
271
+
Each time a call is made to the web API, the [TokenValidationHandler.SendAsync()](https://github.com/Azure-Samples/active-directory-dotnet-webapi-manual-jwt-validation/blob/4b80657c5506c8cb30af67b9f61bb6aa68dfca58/TodoListService-ManualJwt/Global.asax.cs#L80) handler is executed:
226
272
227
273
This method:
228
274
229
-
1. gets the token from the Authorization headers
230
-
1. gets the open ID configuration from the Azure AD discovery endpoint
231
-
1. ensures that the web API is consented to and provisioned in the Azure AD tenant from where the access token originated
232
-
1. verifies that the token has not expired
233
-
1. sets the parameters to validate:
275
+
1. Gets the token from the Authorization headers
276
+
1. Gets the open ID configuration, including keys from the Azure AD discovery endpoint
277
+
1. Sets the parameters to validate in `GetTokenValidationParameters()`
234
278
- the audience - the application accepts both its App ID URI and its AppID/clientID
235
279
- the valid issuers - the application accepts both Azure AD V1 and Azure AD V2
236
-
237
-
1. then it delegates to the `JwtSecurityTokenHandler` class (provided by the `Microsoft.IdentityModel.Tokens` library)
280
+
1. Then the token is validated
281
+
1. An asp.net claims principal is created after a successful validation
282
+
1. ensures that the web API is consented to and provisioned in the Azure AD tenant from where the access token originated
283
+
1. Finally, a check for scopes that the web API expects from the caller is carried out
238
284
239
285
The `TokenValidationHandler` class is registered with ASP.NET in the `TodoListService-ManualJwt/Global.asx.cs` file, in the [Application_Start()](https://github.com/Azure-Samples/active-directory-dotnet-webapi-manual-jwt-validation/blob/4b80657c5506c8cb30af67b9f61bb6aa68dfca58/TodoListService-ManualJwt/Global.asax.cs#L54) method.
240
286
241
287
For more validation options, please refer to [TokenValidationParameters.cs](https://docs.microsoft.com/dotnet/api/microsoft.identitymodel.tokens.tokenvalidationparameters?view=azure-dotnet)
242
288
289
+
### Providing your own Custom token validation handler
290
+
291
+
If you do not wish to control the token validation from its very beginning to the end as laid out in the `Global.asax.cs`, but only limit yourself to validate business logic based on claims in the presented token, you can craft a Custom token handler as provided in the example below.
292
+
The provided example, validates to allow callers from a list of whitelisted tenants only.
- [Quickstart: Register an application with the Microsoft identity platform](https://docs.microsoft.com/azure/active-directory/develop/quickstart-register-app)
357
457
- [Quickstart: Configure a client application to access web APIs](https://docs.microsoft.com/azure/active-directory/develop/quickstart-configure-app-access-web-apis)
0 commit comments