Skip to content

Commit f00cf9f

Browse files
author
Kalyan Krishna
authored
Merge pull request #3 from Azure-Samples/cleanup2018
Cleanup2018
2 parents 20307e6 + 1db5b5c commit f00cf9f

File tree

4 files changed

+54
-45
lines changed

4 files changed

+54
-45
lines changed

README.md

Lines changed: 48 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,22 @@ or Microsoft personal accounts (formerly live account) to use your Web API.
2121
### Overview
2222

2323
This sample presents a Web API running on ASP.NET Core 2.0, protected by Azure AD OAuth Bearer Authentication. The Web API is exercised by a .NET Desktop WPF application.
24-
The .Net application uses the Active Directory Authentication Library (ADAL.Net) to obtain a JWT access token through the [OAuth 2.0](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-code) protocol. The access token is sent to the ASP.NET Core Web API, which authenticates the user using the ASP.NET JWT Bearer Authentication middleware.
24+
The .Net application uses the Active Directory Authentication Library [MSAL.NET](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet) to obtain a JWT access token through the [OAuth 2.0](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-code) protocol. The access token is sent to the ASP.NET Core Web API, which authenticates the user using the ASP.NET JWT Bearer Authentication middleware.
2525

2626
![Topology](./ReadmeFiles/topology.png)
2727

2828
> This sample is very similar to the [active-directory-dotnet-native-aspnetcore](https://github.com/Azure-Samples/active-directory-dotnet-native-aspnetcore) sample except that that one is for the Azure AD V1 endpoint
29-
> and the token is acquired using ADAL.NET, whereas this sample is for the V2 endpoint, and the token is acquired using MSAL.NET. The Web API was also modified to accept both V1 and V2 tokens.
29+
> and the token is acquired using [MSAL.NET](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet), whereas this sample is for the V2 endpoint, and the token is acquired using MSAL.NET. The Web API was also modified to accept both V1 and V2 tokens.
3030
3131
### User experience with this sample
3232

33-
The Web API (TodoListService) maintains an in-memory collection of to-do items per authenticated user. Several applications signed-in under the same identity share the same to-do list.
33+
The Web API (TodoListService) maintains an in-memory collection of to-do items per authenticated user. Several applications signed-in under the same identities share the same to-do list.
3434

3535
The WPF application (TodoListClient) enables a user to:
3636

37-
- Sign in. The first time a user signs it, a consent screen is presented letting him/her consent for the application accessing the TodoList Service and the Azure Active Directory. When s/he has signed-in, the user sees the list of to-do items exposed by Web API for the signed-in identity
38-
- add more to-do items (buy clicking on Add item).
37+
- Sign in. The first time a user signs in, a consent screen is presented letting the user consent for the application accessing the TodoList Service and the Azure Active Directory.
38+
- When the user has signed-in, the user sees the list of to-do items exposed by Web API for the signed-in identity
39+
- The user can add more to-do items (y clicking on *Add item* button.
3940

4041
Next time a user runs the application, the user is signed-in with the same identity as the application maintains a cache on disk. Users can clear the cache (which will also have the effect of signing them out)
4142

@@ -66,7 +67,7 @@ There are two projects in this sample. Each needs to be separately registered in
6667

6768
#### Navigate to the Application registration portal
6869

69-
Sign in in [apps.dev.microsoft.com/](apps.dev.microsoft.com/). From there, you can add converged applications
70+
Sign in to [application registration portal](apps.dev.microsoft.com/). From there, you can add converged applications.
7071

7172
#### Register the TodoListClient-v2 app
7273

@@ -87,7 +88,7 @@ Sign in in [apps.dev.microsoft.com/](apps.dev.microsoft.com/). From there, you c
8788
1. In the *Platforms* section, click on the **Add Platform** button and then on **Web API**
8889
1. Copy the scope proposed by default to access your web api as a user. It's in the form ``api://<Application ID>/access_as_user``
8990
1. In the *Web API platform*, in the *Pre-authorized applications* section click on **Add application**
90-
1. In the *application ID* field, paste the application ID of the client application as pasted from the registration
91+
1. In the *application ID* field, paste the application ID of the `TodoListClient-v2` application as pasted from the registration
9192
1. In the *Scope* field, click on the **Select** combo box and select the scope for this Web API `api://<Application ID>/access_as_user`
9293
1. Press the **Save** button at the bottom of the page.
9394

@@ -109,20 +110,21 @@ Value | Meaning
109110
`organizations` | users can sign in with any Work and School account
110111
`consumers` | users can sign in with a Microsoft Personal account
111112
a GUID or domain name | users can only sign in with an account for a specific organization described by its tenant ID (GUID) or domain name
113+
|
112114

113115
#### Configure the TodoListService C# project
114116

115117
1. Open the solution in Visual Studio.
116-
1. In the TodoListService project, open the `appsettings.json` file.
117-
1. Find the `ClientId` property and replace the value with the Application ID (Client ID) property of the Service application, that you registered earlier.
118-
1. [Optional] if you want to limit sign-in to users in your organization, also update
118+
1. In the *TodoListService* project, open the `appsettings.json` file.
119+
1. Find the `ClientId` property and replace the value with the Application ID (Client ID) property of the *TodoListService-v2* application, that you registered earlier.
120+
1. [Optional] if you want to limit sign-in to users in your organization, also update the following
119121
- The `Domain` property, replacing the existing value with your AAD tenant domain, for example, contoso.onmicrosoft.com.
120122
- The `TenantId` property replacing the existing value with the Tenant ID.
121123

122124
#### Configure the TodoListClient C# project
123125

124126
1. In the TodoListClient project, open `App.config`.
125-
1. Find the app key `ida:ClientId` and replace the value with the ApplicationID (Client ID) for the TodoListClient-v2 app copied from the app registration page.
127+
1. Find the app key `ida:ClientId` and replace the value with the ApplicationID (Client ID) for the *TodoListClient-v2* app copied from the app registration page.
126128
1. Find the app key `todo:TodoListScope` and replace the value with the scope of the TodoListService-v2 application copied from the app registration (of the form ``api://<Application ID of service>/access_as_user``)
127129
1. [Optional] If you want your application to work only in your organization (only in your tenant) you'll also need to Find the app key `ida:Tenant` and replace the value with your AAD Tenant ID (GUID). Alternatively you can also use your AAD tenant Name (for example, contoso.onmicrosoft.com)
128130
1. [Optional] If you changed the default URL for your service application, find the app key `todo:TodoListBaseAddress` and replace the value with the base address of the TodoListService project.
@@ -133,11 +135,11 @@ Clean the solution, rebuild the solution, and run it. You might want to go into
133135

134136
When you start the Web API, you'll get an empty web page. This is expected.
135137

136-
Explore the sample by signing in into the TodoList client, adding items to the To Do list, removing the user account (clearing the cache), and starting again. As explained, 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 because the sample implements a persistent cache for ADAL, and remembers the tokens from the previous run.
138+
Explore the sample by signing in into the TodoList client, adding items to the To Do list, removing the user account (clearing the cache), and starting again. As explained, 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 because the sample implements a persistent cache for MSAL, and remembers the tokens from the previous run.
137139

138-
NOTE: Remember, the To Do list is stored in memory in this TodoListService sample. Each time you run the TodoListService API, your To Do list will get emptied.
140+
NOTE: Remember, the To-Do list is stored in memory in this `TodoListService-v2` sample. Each time you run the TodoListService API, your To-Do list will get emptied.
139141

140-
## How was the code created?
142+
## How was the code created ?
141143

142144
### Code for the service
143145

@@ -166,8 +168,7 @@ namespace TodoListService.Models
166168
}
167169
```
168170

169-
Under the `Controllers` folder, rename the file `ValuesController.cs` to `TodoListController.cs`.
170-
Make sure the content is the following:
171+
Under the `Controllers` folder, rename the file `ValuesController.cs` to `TodoListController.cs` and copy the following content in this file:
171172

172173
```CSharp
173174
using Microsoft.AspNetCore.Authorization;
@@ -206,28 +207,25 @@ namespace TodoListService.Controllers
206207
This code gets the todo list items associated with their owner, which is the identity of the user using the Web API. It also adds todo list items associated with the same user.
207208
There is no persistence as implementing token persistence on the service side would be beyond the scope of this sample
208209

209-
The code of the `Configure` method in `AzureAdServiceCollectionExtension` was also modified to accept tokens coming from the V2 endpoint:
210+
Make the following changes in the `AzureAdServiceCollectionExtension.cs` file.
210211

211212
```CSharp
212-
public void Configure(string name, JwtBearerOptions options)
213-
{
214-
options.Audience = _azureOptions.ClientId;
215-
options.Authority = $"{_azureOptions.Instance}{_azureOptions.Tenant}/v2.0/";
213+
using Microsoft.IdentityModel.Tokens;
214+
```
216215

217-
// Instead of using the default validation (validating against a single tenant, as we do in line of business apps),
218-
// we inject our own multitenant validation logic (which even accepts both V1 and V2 tokens)
219-
options.TokenValidationParameters.ValidateIssuer = true;
220-
options.TokenValidationParameters.IssuerValidator = ValidateIssuer;
221-
}
216+
```Text
217+
The code of the overloaded `Configure` method is also modified to accept tokens coming from the V2 endpoint:
218+
```
222219

220+
```CSharp
223221
/// <summary>
224222
/// Validate the issuer.
225223
/// </summary>
226224
/// <param name="issuer">Issuer to validate (will be tenanted)</param>
227225
/// <param name="securityToken">Received Security Token</param>
228226
/// <param name="validationParameters">Token Validation parameters</param>
229227
/// <remarks>The issuer is considered as valid if it has the same http scheme and authority as the
230-
/// authority from the configuration file, has a tenant Id, and optionnally v2.0 (this web api
228+
/// authority from the configuration file, has a tenant Id, and optionally v2.0 (this web api
231229
/// accepts both V1 and V2 tokens)</remarks>
232230
/// <returns>The <c>issuer</c> if it's valid, or otherwise <c>null</c></returns>
233231
private string ValidateIssuer(string issuer, SecurityToken securityToken, TokenValidationParameters validationParameters)
@@ -257,6 +255,18 @@ private string ValidateIssuer(string issuer, SecurityToken securityToken, TokenV
257255
return null;
258256
}
259257
}
258+
259+
public void Configure(string name, JwtBearerOptions options)
260+
{
261+
options.Audience = _azureOptions.ClientId;
262+
options.Authority = $"{_azureOptions.Instance}{_azureOptions.TenantId}/v2.0/";
263+
264+
// Instead of using the default validation (validating against a single tenant, as we do in line of business apps),
265+
// we inject our own multitenant validation logic (which even accepts both V1 and V2 tokens)
266+
options.TokenValidationParameters.ValidateIssuer = true;
267+
options.TokenValidationParameters.IssuerValidator = ValidateIssuer;
268+
}
269+
260270
```
261271

262272
#### Change the App URL
@@ -301,12 +311,12 @@ This project has one WebApp / Web API projects. To deploy it to Azure Web Sites,
301311
for example, [https://TodoListService-contoso.azurewebsites.net](https://TodoListService-contoso.azurewebsites.net).
302312
3. Run the client! If you are trying multiple different client types (for example, .Net, Windows Store, Android, iOS) you can have them all call this one published web API.
303313

304-
> NOTE: Remember, the To Do list is stored in memory in this TodoListService sample. Azure Web Sites will spin down your web site if it is inactive, and your To Do list will get emptied.
314+
> NOTE: Remember, the To-Do list is stored in memory in this TodoListService sample. Azure Web Sites will spin down your web site if it is inactive, and your To Do list will get emptied.
305315
Also, if you increase the instance count of the web site, requests will be distributed among the instances. To Do will, therefore, not be the same on each instance.
306316

307317
## Community Help and Support
308318

309-
Use [Stack Overflow](http://stackoverflow.com/questions/tagged/adal) to get support from the community.
319+
Use [Stack Overflow](http://stackoverflow.com/questions/tagged/msal) to get support from the community.
310320
Ask your questions on Stack Overflow first and browse existing issues to see if someone has asked your question before.
311321
Make sure that your questions or comments are tagged with [`msal` `dotnet`].
312322

@@ -320,16 +330,15 @@ If you'd like to contribute to this sample, see [CONTRIBUTING.MD](/CONTRIBUTING.
320330

321331
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information, see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [[email protected]](mailto:[email protected]) with any additional questions or comments.
322332

323-
## More information
324-
325-
To understand better how the client code acquires a token, see ADAL.NET's conceptual documentation:
326-
327-
- [Recommended pattern to acquire a token](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/AcquireTokenSilentAsync-using-a-cached-token#recommended-call-pattern-in-public-client-applications)
328-
- [Acquiring tokens interactively in public client applications](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Acquiring-tokens-interactively)
329-
- [Customizing Token cache serialization](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/token-cache-serialization)
333+
For more information, visit the following links:
330334

331-
### Other documentation / samples
335+
- To learn more about the code, visit [Conceptual documentation for MSAL.NET](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki#conceptual-documentation) and in particular:
336+
- [Acquiring tokens with authorization codes on web apps](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Acquiring-tokens-with-authorization-codes-on-web-apps)
337+
- [Customizing Token cache serialization](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/token-cache-serialization)
332338

333-
This sample is for the Azure AD V2 enpoint the same as [Calling a ASP.NET Core Web API from a WPF application using Azure AD](https://github.com/Azure-Samples/active-directory-dotnet-native-aspnetcore) which is for the Azure AD V1 endpoint.
339+
- Articles about the Azure AD V2 endpoint [http://aka.ms/aaddevv2](http://aka.ms/aaddevv2), with a focus on:
340+
- [Azure Active Directory v2.0 and OAuth 2.0 On-Behalf-Of flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols-oauth-on-behalf-of)
334341

335-
For more information about how the protocols work in this scenario and other scenarios, see [Authentication Scenarios for Azure AD](https://go.microsoft.com/fwlink/?LinkId=394414).
342+
- [Introduction to Identity on ASP.NET Core](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity?view=aspnetcore-2.1&tabs=visual-studio%2Caspnetcore2x)
343+
- [AuthenticationBuilder](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.authentication.authenticationbuilder?view=aspnetcore-2.0)
344+
- [Azure Active Directory with ASP.NET Core](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/azure-active-directory/?view=aspnetcore-2.1)

TodoListClient/App.config

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
- 'consumers' to sign-in only Microsoft personal accounts
1616
-->
1717
<add key="ida:Tenant" value="common" />
18-
<add key="ida:ClientId" value="[Enter the Application ID (Client ID) of your application from the portal, e.g. b3682cc7-8b30-4bd2-aaba-080c6bf0fd31]" />
18+
<add key="ida:ClientId" value="[Enter_client_ID_Of_TodoListClient-v2_from_Azure_Portal,_e.g._784d7a5a-4a49-4d1d-b328-5812070f366f]" />
1919

2020
<!--
2121
todo:TodoListScope is the scope of the Web API you want to call. This can be:
@@ -24,7 +24,7 @@
2424
- a scope corresponding to a V1 application (for instance <GUID>/user_impersonation, where <GUID> is the
2525
clientId of a V1 application, created in the https://portal.azure.com portal.
2626
-->
27-
<add key="todo:TodoListScope" value="[Enter the scope of the application, e.g. api://b3682cc7-8b30-4bd2-aaba-080c6bf0fd31/access_as_user]" />
27+
<add key="todo:TodoListScope" value="api://[Enter_client_ID_Of_TodoListService-v2_from_Azure_Portal,_e.g._2ec40e65-ba09-4853-bcde-bcb60029e596]/access_as_user" />
2828
<add key="todo:TodoListBaseAddress" value="https://localhost:44351/" />
2929
</appSettings>
3030
</configuration>

TodoListService/Extensions/AzureAdAuthenticationBuilderExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public void Configure(string name, JwtBearerOptions options)
5050
/// <param name="securityToken">Received Security Token</param>
5151
/// <param name="validationParameters">Token Validation parameters</param>
5252
/// <remarks>The issuer is considered as valid if it has the same http scheme and authority as the
53-
/// authority from the configuration file, has a tenant Id, and optionnally v2.0 (this web api
53+
/// authority from the configuration file, has a tenant Id, and optionally v2.0 (this web api
5454
/// accepts both V1 and V2 tokens)</remarks>
5555
/// <returns>The <c>issuer</c> if it's valid, or otherwise <c>null</c></returns>
5656
private string ValidateIssuer(string issuer, SecurityToken securityToken, TokenValidationParameters validationParameters)

TodoListService/appsettings.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
{
22
"AzureAd": {
33
"Instance": "https://login.microsoftonline.com/",
4-
"ClientId": "11111111-1111-1111-11111111111111111",
4+
"ClientId": "[Enter_client_ID_Of_TodoListService-v2_from_Azure_Portal,_e.g._2ec40e65-ba09-4853-bcde-bcb60029e596]",
55

66
/*
77
The Domain and TenantId are only needed if you want to accept access tokens
88
from a sigle tenant (line of business app)
99
Otherwise you can leave them blank
1010
*/
1111
"Domain": "qualified.domain.name", // for instance contoso.onmicrosoft.com
12-
"TenantId": "common" // 'common' or 'organizations' or 'consumers'
13-
// or tenant ID like '22222222-2222-2222-2222-222222222222'
12+
"TenantId": "common" // 'common' or 'organizations' or 'consumers'
13+
// or enter Directory ID Of tenant, e.g.contoso.onmicrosoft.com from Azure Portal, e.g. 14c2f153-90a7-4689-9db7-9543bf084dad
1414
},
1515
"Logging": {
1616
"IncludeScopes": false,

0 commit comments

Comments
 (0)