Skip to content

Commit 1323575

Browse files
authored
Merge pull request #112615 from jmprieur/updateMicrosoftIdentityWeb
Updating scenario landing pages (Microsoft.Identity.Web)
2 parents 1a022eb + 995939f commit 1323575

7 files changed

+141
-465
lines changed

articles/active-directory/develop/scenario-web-app-call-api-acquire-token.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ ms.custom: aaddev
1919

2020
You've built your client application object. Now, you'll use it to acquire a token to call a web API. In ASP.NET or ASP.NET Core, calling a web API is done in the controller:
2121

22-
- Get a token for the web API by using the token cache. To get this token, you call the `AcquireTokenSilent` method.
22+
- Get a token for the web API by using the token cache. To get this token, you call the MSAL `AcquireTokenSilent` method (or the equivalent in Microsoft.Identity.Web).
2323
- Call the protected API, passing the access token to it as a parameter.
2424

2525
# [ASP.NET Core](#tab/aspnetcore)
@@ -51,7 +51,7 @@ public async Task<IActionResult> Profile()
5151
{
5252
// Acquire the access token.
5353
string[] scopes = new string[]{"user.read"};
54-
string accessToken = await tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(scopes);
54+
string accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(scopes);
5555

5656
// Use the access token to call a protected web API.
5757
HttpClient client = new HttpClient();
@@ -158,6 +158,8 @@ def graphcall():
158158
return render_template('display.html', result=graph_data)
159159
```
160160

161+
---
162+
161163
## Next steps
162164

163165
> [!div class="nextstepaction"]

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

Lines changed: 20 additions & 258 deletions
Large diffs are not rendered by default.

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

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ ms.custom: aaddev
1919

2020
Now that you have a token, you can call a protected web API.
2121

22+
## Call a protected web API
23+
24+
Calling a protected web API depends on your language and framework of choice:
25+
2226
# [ASP.NET Core](#tab/aspnetcore)
2327

2428
Here's simplified code for the action of the `HomeController`. This code gets a token to call Microsoft Graph. Code has been added to show how to call Microsoft Graph as a REST API. The URL for the Microsoft Graph API is provided in the appsettings.json file and is read in a variable named `webOptions`:
@@ -37,41 +41,26 @@ Here's simplified code for the action of the `HomeController`. This code gets a
3741
```csharp
3842
public async Task<IActionResult> Profile()
3943
{
40-
var application = BuildConfidentialClientApplication(HttpContext, HttpContext.User);
41-
string accountIdentifier = claimsPrincipal.GetMsalAccountId();
42-
string loginHint = claimsPrincipal.GetLoginHint();
43-
44-
// Get the account.
45-
IAccount account = await application.GetAccountAsync(accountIdentifier);
46-
47-
// Special case for guest users, because the guest ID / tenant ID are not surfaced.
48-
if (account == null)
49-
{
50-
var accounts = await application.GetAccountsAsync();
51-
account = accounts.FirstOrDefault(a => a.Username == loginHint);
52-
}
53-
54-
AuthenticationResult result;
55-
result = await application.AcquireTokenSilent(new []{"user.read"}, account)
56-
.ExecuteAsync();
57-
var accessToken = result.AccessToken;
58-
59-
// Calls the web API (Microsoft Graph in this case).
60-
HttpClient httpClient = new HttpClient();
61-
httpClient.DefaultRequestHeaders.Authorization =
62-
new AuthenticationHeaderValue(Constants.BearerAuthorizationScheme,accessToken);
63-
var response = await httpClient.GetAsync($"{webOptions.GraphApiUrl}/beta/me");
64-
65-
if (response.StatusCode == HttpStatusCode.OK)
66-
{
67-
var content = await response.Content.ReadAsStringAsync();
68-
69-
dynamic me = JsonConvert.DeserializeObject(content);
70-
return me;
71-
}
72-
73-
ViewData["Me"] = me;
74-
return View();
44+
// Acquire the access token.
45+
string[] scopes = new string[]{"user.read"};
46+
string accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(scopes);
47+
48+
// Use the access token to call a protected web API.
49+
HttpClient client = new HttpClient();
50+
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
51+
52+
var response = await httpClient.GetAsync($"{webOptions.GraphApiUrl}/beta/me");
53+
54+
if (response.StatusCode == HttpStatusCode.OK)
55+
{
56+
var content = await response.Content.ReadAsStringAsync();
57+
58+
dynamic me = JsonConvert.DeserializeObject(content);
59+
return me;
60+
}
61+
62+
ViewData["Me"] = me;
63+
return View();
7564
}
7665
```
7766

articles/active-directory/develop/scenario-web-app-call-api-sign-in.md

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -27,35 +27,7 @@ To clear the token-cache entry associated with the account that signed out, your
2727

2828
# [ASP.NET Core](#tab/aspnetcore)
2929

30-
For ASP.NET Core, the interception mechanism is illustrated in the `AddMsal()` method of [WebAppServiceCollectionExtensions.cs#L151-L157](https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/blob/db7f74fd7e65bab9d21092ac1b98a00803e5ceb2/Microsoft.Identity.Web/WebAppServiceCollectionExtensions.cs#L151-L157).
31-
32-
The Logout URL that you previously registered for your application enables you to implement single sign-out. The Microsoft identity platform `logout` endpoint calls your Logout URL. This call happens if the sign-out started from your web app, or from another web app or the browser. For more information, see [Single sign-out](v2-protocols-oidc.md#single-sign-out).
33-
34-
```csharp
35-
public static class WebAppServiceCollectionExtensions
36-
{
37-
public static IServiceCollection AddMsal(this IServiceCollection services, IConfiguration configuration, IEnumerable<string> initialScopes, string configSectionName = "AzureAd")
38-
{
39-
// Code omitted here
40-
41-
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
42-
{
43-
// Code omitted here
44-
45-
// Handling the sign-out: Remove the account from MSAL.NET cache.
46-
options.Events.OnRedirectToIdentityProviderForSignOut = async context =>
47-
{
48-
// Remove the account from MSAL.NET token cache.
49-
var tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService<ITokenAcquisition>();
50-
await tokenAcquisition.RemoveAccountAsync(context).ConfigureAwait(false);
51-
};
52-
});
53-
return services;
54-
}
55-
}
56-
```
57-
58-
The code for `RemoveAccountAsync` is available from [Microsoft.Identity.Web/TokenAcquisition.cs#L264-L288](https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/blob/db7f74fd7e65bab9d21092ac1b98a00803e5ceb2/Microsoft.Identity.Web/TokenAcquisition.cs#L264-L288).
30+
Microsoft.Identity.Web takes care of implementing sign-out for you.
5931

6032
# [ASP.NET](#tab/aspnet)
6133

articles/active-directory/develop/scenario-web-app-sign-user-app-configuration.md

Lines changed: 49 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -203,112 +203,63 @@ The initialization code is different depending on the platform. For ASP.NET Core
203203
204204
# [ASP.NET Core](#tab/aspnetcore)
205205
206-
In ASP.NET Core web apps (and web APIs), the application is protected because you have a `[Authorize]` attribute on the controllers or the controller actions. This attribute checks that the user is authenticated. The code that's initializing the application is in the Startup.cs file.
206+
In ASP.NET Core web apps (and web APIs), the application is protected because you have a `[Authorize]` attribute on the controllers or the controller actions. This attribute checks that the user is authenticated. The code that's initializing the application is in the *Startup.cs* file.
207207
208208
To add authentication with the Microsoft identity platform (formerly Azure AD v2.0), you'll need to add the following code. The comments in the code should be self-explanatory.
209209
210210
> [!NOTE]
211-
> If you start your project with the default ASP.NET Core web project within Visual studio or by using `dotnet new mvc`, the method `AddAzureAD` is available by default. That's because the related packages are automatically loaded.
212-
>
213-
> If you build a project from scratch and are trying to use the following code, we suggest that you add the NuGet package **Microsoft.AspNetCore.Authentication.AzureAD.UI** to your project to make the `AddAzureAD` method available.
211+
> If you start your project with the default ASP.NET Core web project within Visual Studio or by using `dotnet new mvc --auth SingleAuth` or `dotnet new webapp --auth SingleAuth`, you'll see code like the following: `services.AddAuthentication(AzureADDefaults.AuthenticationScheme).AddAzureAD(options => Configuration.Bind("AzureAd", options));`.
212+
>
213+
> This code uses the legacy **Microsoft.AspNetCore.Authentication.AzureAD.UI** NuGet package which is used to create an Azure AD v1.0 application. This article explains how to create a Microsoft identity platform (Azure AD v2.0) application which replaces that code.
214214
215-
The following code is available from [Startup.cs#L33-L34](https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/blob/faa94fd49c2da46b22d6694c4f5c5895795af26d/1-WebApp-OIDC/1-1-MyOrg/Startup.cs#L33-L34).
215+
1. Add the [Microsoft.Identity.Web](https://www.nuget.org/packages/Microsoft.Identity.Web) and [Microsoft.Identity.Web.UI](https://www.nuget.org/packages/Microsoft.Identity.Web.UI) NuGet packages to your project. Remove the Microsoft.AspNetCore.Authentication.AzureAD.UI NuGet package if it's present.
216216
217-
```csharp
218-
public class Startup
219-
{
220-
...
217+
2. Update the code in `ConfigureServices` so that it uses the `AddSignIn` and `AddMicrosoftIdentityUI` methods.
221218
222-
// This method is called by the runtime. Use this method to add services to the container.
223-
public void ConfigureServices(IServiceCollection services)
224-
{
219+
```c#
220+
public class Startup
221+
{
225222
...
226-
// Sign in users with the Microsoft identity platform
227-
services.AddMicrosoftIdentityPlatformAuthentication(Configuration);
228-
229-
services.AddMvc(options =>
230-
{
231-
var policy = new AuthorizationPolicyBuilder()
232-
.RequireAuthenticatedUser()
233-
.Build();
234-
options.Filters.Add(new AuthorizeFilter(policy));
235-
})
236-
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
237-
}
238-
```
239-
240-
The `AddMicrosoftIdentityPlatformAuthentication` extension method is defined in [Microsoft.Identity.Web/WebAppServiceCollectionExtensions.cs#L23](https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/blob/faa94fd49c2da46b22d6694c4f5c5895795af26d/Microsoft.Identity.Web/WebAppServiceCollectionExtensions.cs#L23). It:
241-
242-
- Adds the authentication service.
243-
- Configures options to read the configuration file.
244-
- Configures the OpenID Connect options so that the used authority is the Microsoft identity platform (formerly Azure AD v2.0) endpoint.
245-
- Validates the issuer of the token.
246-
- Ensures that the claims corresponding to name are mapped from the `preferred_username` claim in the ID token.
247-
248-
In addition to the configuration, you can specify the name of the configuration section when calling `AddMicrosoftIdentityPlatformAuthentication`. By default, it's `AzureAd`.
249-
250-
Tracing OpenId Connect middleware events can help you troubleshoot your web application if authentication doesn't work. Setting `subscribeToOpenIdConnectMiddlewareDiagnosticsEvents` to `true` will show you how information gets elaborated by the set of ASP.NET Core middleware as it progresses from the HTTP response to the identity of the user in `HttpContext.User`.
251-
252-
```csharp
253-
/// <summary>
254-
/// Add authentication with the Microsoft identity platform.
255-
/// This method expects the configuration file to have a section named "AzureAd" with the necessary settings to initialize authentication options.
256-
/// </summary>
257-
/// <param name="services">Service collection to which to add this authentication scheme</param>
258-
/// <param name="configuration">The Configuration object</param>
259-
/// <param name="subscribeToOpenIdConnectMiddlewareDiagnosticsEvents">
260-
/// Set to true if you want to debug, or just understand the OpenID Connect events.
261-
/// </param>
262-
/// <returns></returns>
263-
public static IServiceCollection AddMicrosoftIdentityPlatformAuthentication(
264-
this IServiceCollection services,
265-
IConfiguration configuration,
266-
string configSectionName = "AzureAd",
267-
bool subscribeToOpenIdConnectMiddlewareDiagnosticsEvents = false)
268-
{
269-
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
270-
.AddAzureAD(options => configuration.Bind(configSectionName, options));
271-
services.Configure<AzureADOptions>(options => configuration.Bind(configSectionName, options));
272-
273-
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
274-
{
275-
// Per the following code, this application signs in users in any work or school
276-
// accounts and any Microsoft personal accounts.
277-
// If you want to direct Azure AD to restrict the users who can sign in, change
278-
// the tenant value of the appsettings.json file in the following way:
279-
// - Only work or school accounts => 'organizations'
280-
// - Only Microsoft personal accounts => 'consumers'
281-
// - Work or school and personal accounts => 'common'
282-
// If you want to restrict the users who can sign in to only one tenant,
283-
// set the tenant value in the appsettings.json file to the tenant ID
284-
// or domain of this organization.
285-
options.Authority = options.Authority + "/v2.0/";
286-
287-
// If you want to restrict the users who can sign in to several organizations,
288-
// set the tenant value in the appsettings.json file to 'organizations', and add the
289-
// issuers you want to accept to the options.TokenValidationParameters.ValidIssuers collection.
290-
options.TokenValidationParameters.IssuerValidator = AadIssuerValidator.GetIssuerValidator(options.Authority).Validate;
291-
292-
// Set nameClaimType to be preferred_username.
293-
// This change is needed because certain token claims from the Azure AD v1 endpoint
294-
// (on which the original .NET Core template is based) are different from the Microsoft identity platform endpoint.
295-
// For more details, see [ID tokens](https://docs.microsoft.com/azure/active-directory/develop/id-tokens)
296-
// and [Access tokens](https://docs.microsoft.com/azure/active-directory/develop/access-tokens).
297-
options.TokenValidationParameters.NameClaimType = "preferred_username";
298-
299-
// ...
300-
301-
if (subscribeToOpenIdConnectMiddlewareDiagnosticsEvents)
302-
{
303-
OpenIdConnectMiddlewareDiagnostics.Subscribe(options.Events);
304-
}
305-
});
306-
return services;
307-
}
308-
...
309-
```
310-
311-
The `AadIssuerValidator` class enables the issuer of the token to be validated in many cases. This class works with a v1.0 or v2.0 token, a single-tenant or multitenant application, or an application that signs in users with their personal Microsoft accounts in the Azure public cloud or national clouds. It's available from [Microsoft.Identity.Web/Resource/AadIssuerValidator.cs](https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/blob/master/Microsoft.Identity.Web/Resource/AadIssuerValidator.cs).
223+
// This method gets called by the runtime. Use this method to add services to the container.
224+
public void ConfigureServices(IServiceCollection services)
225+
{
226+
services.AddSignIn(Configuration, "AzureAd");
227+
228+
services.AddRazorPages().AddMvcOptions(options =>
229+
{
230+
var policy = new AuthorizationPolicyBuilder()
231+
.RequireAuthenticatedUser()
232+
.Build();
233+
options.Filters.Add(new AuthorizeFilter(policy));
234+
}).AddMicrosoftIdentityUI();
235+
```
236+
237+
3. In the `Configure` method in *Startup.cs*, enable authentication with a call to `app.UseAuthentication();`
238+
239+
```c#
240+
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
241+
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
242+
{
243+
// more code here
244+
app.UseAuthentication();
245+
app.UseAuthorization();
246+
// more code here
247+
}
248+
```
249+
250+
In the code above:
251+
- The `AddSignIn` extension method is defined in **Microsoft.Identity.Web**. It:
252+
- Adds the authentication service.
253+
- Configures options to read the configuration file (here from the "AzureAD" section)
254+
- Configures the OpenID Connect options so that the authority is the Microsoft identity platform endpoint.
255+
- Validates the issuer of the token.
256+
- Ensures that the claims corresponding to name are mapped from the `preferred_username` claim in the ID token.
257+
258+
- In addition to the configuration object, you can specify the name of the configuration section when calling `AddSignIn`. By default, it's `AzureAd`.
259+
260+
- `AddSignIn` has other parameters for advanced scenarios. For example, tracing OpenID Connect middleware events can help you troubleshoot your web application if authentication doesn't work. Setting the optional parameter `subscribeToOpenIdConnectMiddlewareDiagnosticsEvents` to `true` will show you how information is processed by the set of ASP.NET Core middleware as it progresses from the HTTP response to the identity of the user in `HttpContext.User`.
261+
262+
- The `AddMicrosoftIdentityUI` extension method is defined in **Microsoft.Identity.Web.UI**. It provides a default controller to handle sign-out.
312263
313264
# [ASP.NET](#tab/aspnet)
314265

articles/active-directory/develop/scenario-web-app-sign-user-production.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ Make sure you understand possible issues with new versions of the Chrome browser
3939
> [!div class="nextstepaction"]
4040
> [How to handle SameSite cookie changes in Chrome browser](howto-handle-samesite-cookie-changes-chrome-browser.md)
4141
42+
The Microsoft.Identity.Web NuGet package handles the most common SameSite issues.
43+
4244
### Scenario for calling web APIs
4345

4446
After your web app signs in users, it can call web APIs on behalf of the signed-in users. Calling web APIs from the web app is the object of the following scenario:

0 commit comments

Comments
 (0)