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
Copy file name to clipboardExpand all lines: articles/active-directory/develop/scenario-web-app-call-api-acquire-token.md
+25-17Lines changed: 25 additions & 17 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -182,26 +182,34 @@ public ModelAndView getUserFromGraph(HttpServletRequest httpRequest, HttpServlet
182
182
183
183
# [Python](#tab/python)
184
184
185
-
In the Python sample, the code that calls Microsoft Graph is in [app.py#L53-L62](https://github.com/Azure-Samples/ms-identity-python-webapp/blob/48637475ed7d7733795ebeac55c5d58663714c60/app.py#L53-L62).
186
-
187
-
The code attempts to get a token from the token cache. Then, after setting the authorization header, it calls the web API. If it can't get a token, it signs the user in again.
188
-
189
-
```python
190
-
@app.route("/graphcall")
191
-
defgraphcall():
192
-
token = _get_token_from_cache(app_config.SCOPE)
193
-
ifnot token:
194
-
return redirect(url_for("login"))
195
-
graph_data = requests.get( # Use token to call downstream service.
In the Python sample, the code that calls the API is in [app.py#L60-71](https://github.com/Azure-Samples/ms-identity-python-webapp/blob/0.5.0/app.py#L60-71).
186
+
187
+
The code attempts to get a token from the token cache. If it can't get a token, it redirects the user to the sign-in route. Otherwise, it can proceed to call the API.
Copy file name to clipboardExpand all lines: articles/active-directory/develop/scenario-web-app-call-api-app-configuration.md
+45-57Lines changed: 45 additions & 57 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -92,7 +92,7 @@ Instead of a client secret, you can provide a client certificate. The following
92
92
93
93
## Startup.cs
94
94
95
-
Your web app will need to acquire a token for the downstream API. You specify it by adding the `.EnableTokenAcquisitionToCallDownstreamApi()` line after `.AddMicrosoftIdentityWebApp(Configuration)`. This line exposes the `ITokenAcquisition` service that you can use in your controller and page actions. However, as you'll see in the following two options, it can be done more simply. You'll also need to choose a token cache implementation, for example `.AddInMemoryTokenCaches()`, in *Startup.cs*:
95
+
Your web app needs to acquire a token for the downstream API. You specify it by adding the `.EnableTokenAcquisitionToCallDownstreamApi()` line after `.AddMicrosoftIdentityWebApp(Configuration)`. This line exposes the `ITokenAcquisition` service that you can use in your controller and page actions. However, as you'll see in the following two options, it can be done more simply. You'll also need to choose a token cache implementation, for example `.AddInMemoryTokenCaches()`, in *Startup.cs*:
96
96
97
97
```csharp
98
98
usingMicrosoft.Identity.Web;
@@ -113,7 +113,7 @@ Your web app will need to acquire a token for the downstream API. You specify it
113
113
}
114
114
```
115
115
116
-
The scopes passed to `EnableTokenAcquisitionToCallDownstreamApi` are optional, and enable your web app to request the scopes and the user's consent to those scopes when they log in. If you don't specify the scopes, *Microsoft.Identity.Web*will enable an incremental consent experience.
116
+
The scopes passed to `EnableTokenAcquisitionToCallDownstreamApi` are optional, and enable your web app to request the scopes and the user's consent to those scopes when they sign in. If you don't specify the scopes, *Microsoft.Identity.Web*enables an incremental consent experience.
117
117
118
118
If you don't want to acquire the token yourself, *Microsoft.Identity.Web* provides two mechanisms for calling a web API from a web app. The option you choose depends on whether you want to call Microsoft Graph or another API.
119
119
@@ -172,7 +172,7 @@ To call a web API other than Microsoft Graph, *Microsoft.Identity.Web* provides
172
172
173
173
As with web APIs, you can choose various token cache implementations. For details, see [Microsoft.Identity.Web - Token cache serialization](https://aka.ms/ms-id-web/token-cache-serialization) on GitHub.
174
174
175
-
The following image shows the various possibilities of *Microsoft.Identity.Web* and their impact on the *Startup.cs* file:
175
+
The following image shows the various possibilities of *Microsoft.Identity.Web* and their effect on the *Startup.cs* file:
176
176
177
177
:::image type="content" source="media/scenarios/microsoft-identity-web-startup-cs.svg" alt-text="Block diagram showing service configuration options in startup dot C S for calling a web API and specifying a token cache implementation":::
178
178
@@ -187,7 +187,7 @@ For ASP.NET, you'll subscribe to middleware OIDC events:
187
187
188
188
- You'll let ASP.NET Core request an authorization code by means of the Open ID Connect middleware. ASP.NET or ASP.NET Core will let the user sign in and consent.
189
189
- You'll subscribe the web app to receive the authorization code. This subscription is done by using a C# delegate.
190
-
- When the authorization code is received, you'll use MSAL libraries to redeem it. The resulting access tokens and refresh tokens are stored in the token cache. The cache can be used in other parts of the application, such as controllers, to acquire other tokens silently.
190
+
- When the authorization code is received, the code uses MSAL libraries to redeem it. The resulting access tokens and refresh tokens are stored in the token cache. The cache can be used in other parts of the application, such as controllers, to acquire other tokens silently.
191
191
192
192
Code examples in this article and the following one are extracted from the [ASP.NET Web app sample](https://github.com/Azure-Samples/ms-identity-aspnet-webapp-openidconnect). You might want to refer to that sample for full implementation details.
193
193
@@ -198,8 +198,9 @@ The sample currently lets MSAL for Java produce the authorization-code URL and h
198
198
199
199
# [Python](#tab/python)
200
200
201
-
Code examples in this article and the following one are extracted from the [Python web application calling Microsoft Graph](https://github.com/Azure-Samples/ms-identity-python-webapp), a web-app sample that uses MSAL.Python.
202
-
The sample currently lets MSAL.Python produce the authorization-code URL and handles the navigation to the authorization endpoint for the Microsoft identity platform. You might want to refer to the sample for full implementation details.
201
+
Code snippets in this article and the following are extracted from the [Python web application calling Microsoft graph](https://github.com/Azure-Samples/ms-identity-python-webapp) sample using the [identity package](https://pypi.org/project/identity/) (a wrapper around MSAL Python).
202
+
203
+
The sample uses the identity package to produce the authorization-code URL and handles the navigation to the authorization endpoint for the Microsoft identity platform. You might want to refer to the sample for full implementation details.
203
204
204
205
---
205
206
@@ -211,7 +212,7 @@ Microsoft.Identity.Web simplifies your code by setting the correct OpenID Connec
211
212
212
213
# [ASP.NET](#tab/aspnet)
213
214
214
-
ASP.NET handles things similarly to ASP.NET Core, except that the configuration of OpenID Connect and the subscription to the `OnAuthorizationCodeReceived` event happen in the [App_Start\Startup.Auth.cs](https://github.com/Azure-Samples/ms-identity-aspnet-webapp-openidconnect/blob/a2da310539aa613b77da1f9e1c17585311ab22b7/WebApp/App_Start/Startup.Auth.cs) file. The concepts are also similar to those in ASP.NET Core, except that in ASP.NET you must specify the `RedirectUri` in [Web.config#L15](https://github.com/Azure-Samples/ms-identity-aspnet-webapp-openidconnect/blob/master/WebApp/Web.config#L15). This configuration is a bit less robust than the one in ASP.NET Core, because you'll need to change it when you deploy your application.
215
+
ASP.NET handles things similarly to ASP.NET Core, except that the configuration of OpenID Connect and the subscription to the `OnAuthorizationCodeReceived` event happen in the [App_Start\Startup.Auth.cs](https://github.com/Azure-Samples/ms-identity-aspnet-webapp-openidconnect/blob/a2da310539aa613b77da1f9e1c17585311ab22b7/WebApp/App_Start/Startup.Auth.cs) file. The concepts are also similar to those in ASP.NET Core, except that in ASP.NET you must specify the `RedirectUri` in [Web.config#L15](https://github.com/Azure-Samples/ms-identity-aspnet-webapp-openidconnect/blob/master/WebApp/Web.config#L15). This configuration is a bit less robust than the one in ASP.NET Core, because you need to change it when you deploy your application.
215
216
216
217
Here's the code for Startup.Auth.cs:
217
218
@@ -351,29 +352,17 @@ The `getAuthResultByAuthCode` method is defined in [AuthHelper.java#L176](https:
351
352
352
353
# [Python](#tab/python)
353
354
354
-
The authorization code flow is requested as shown in [Web app that signs in users: Code configuration](scenario-web-app-sign-user-app-configuration.md?tabs=python#initialization-code). The code is then received on the `authorized` function, which Flask routes from the `/getAToken` URL. See [app.py#L30-L44](https://github.com/Azure-Samples/ms-identity-python-webapp/blob/e03be352914bfbd58be0d4170eba1fb7a4951d84/app.py#L30-L44) for the full context of this code:
355
-
356
-
```python
357
-
@app.route("/getAToken") # Its absolute URL must match your app's redirect_uri set in AAD.
358
-
defauthorized():
359
-
if request.args['state'] != session.get("state"):
360
-
return redirect(url_for("login"))
361
-
cache = _load_cache()
362
-
result = _build_msal_app(cache).acquire_token_by_authorization_code(
363
-
request.args['code'],
364
-
scopes=app_config.SCOPE, # Misspelled scope would cause an HTTP 400 error here.
See [Web app that signs in users: Code configuration](scenario-web-app-sign-user-app-configuration.md?tabs=python#initialization-code) to understand how the Python sample gets the authorization code.
356
+
357
+
The Microsoft sign-in screen sends the authorization code to the `/getAToken` URL that was specified in the app registration. The `auth_response` route handles that URL, calling `auth.complete_login` to process the authorization code, and then either returning an error or redirecting to the home page.
See [app.py](https://github.com/Azure-Samples/ms-identity-python-webapp/blob/0.5.0/app.py#L36-41) for the full context of that code.
373
362
374
363
---
375
364
376
-
Instead of a client secret, the confidential client application can also prove its identity by using a client certificate, or a client assertion.
365
+
Instead of a client secret, the confidential client application can also prove its identity by using a client certificate or a client assertion.
377
366
The use of client assertions is an advanced scenario, detailed in [Client assertions](msal-net-client-assertions.md).
378
367
379
368
## Token cache
@@ -384,7 +373,7 @@ The use of client assertions is an advanced scenario, detailed in [Client assert
384
373
385
374
# [ASP.NET Core](#tab/aspnetcore)
386
375
387
-
The ASP.NET core tutorial uses dependency injection to let you decide the token cache implementation in the Startup.cs file for your application. Microsoft.Identity.Web comes with pre-built token-cache serializers described in [Token cache serialization](msal-net-token-cache-serialization.md). An interesting possibility is to choose ASP.NET Core [distributed memory caches](/aspnet/core/performance/caching/distributed#distributed-memory-cache):
376
+
The ASP.NET core tutorial uses dependency injection to let you decide the token cache implementation in the Startup.cs file for your application. Microsoft.Identity.Web comes with prebuilt token-cache serializers described in [Token cache serialization](msal-net-token-cache-serialization.md). An interesting possibility is to choose ASP.NET Core [distributed memory caches](/aspnet/core/performance/caching/distributed#distributed-memory-cache):
388
377
389
378
```csharp
390
379
// Use a distributed token cache by adding:
@@ -423,7 +412,7 @@ The web-app implementation can use the ASP.NET session or the server memory. For
423
412
424
413
425
414
First, to use these implementations:
426
-
- add the Microsoft.Identity.Web NuGet package. These token cache serializers are not brought in MSAL.NET directly to avoid unwanted dependencies. In addition to a higher level for ASP.NET Core, Microsoft.Identity.Web brings classes that are helpers for MSAL.NET,
415
+
- add the Microsoft.Identity.Web NuGet package. These token cache serializers aren't brought in MSAL.NET directly to avoid unwanted dependencies. In addition to a higher level for ASP.NET Core, Microsoft.Identity.Web brings classes that are helpers for MSAL.NET,
427
416
- In your code, use the Microsoft.Identity.Web namespace:
428
417
429
418
```csharp
@@ -453,7 +442,7 @@ public static class MsalAppBuilder
453
442
}
454
443
```
455
444
456
-
Instead of `clientapp.AddInMemoryTokenCache()`, youcanalsousemoreadvancedcacheserializationimplementationslikeRedis, SQL, CosmosDB, ordistributedmemory. Here'sanexampleforRedis:
445
+
Instead of `clientapp.AddInMemoryTokenCache()`, youcanalsousemoreadvancedcacheserializationimplementationslikeRedis, SQL, CosmosDB, ordistributedmemory. Here'sanexampleforRedis:
457
446
458
447
```csharp
459
448
clientapp.AddDistributedTokenCache(services =>
@@ -503,41 +492,40 @@ The detail of the `SessionManagementHelper` class is provided in the [MSAL sampl
503
492
504
493
# [Python](#tab/python)
505
494
506
-
In the Python sample, one cache per account is ensured by recreating a confidential client application for each request and then serializing it in the Flask session cache:
507
-
508
-
```python
509
-
from flask import Flask, render_template, session, request, redirect, url_for
510
-
from flask_session import Session # https://pythonhosted.org/Flask-Session
511
-
import msal
512
-
import app_config
495
+
In the Python sample, the identity package takes care of the token cache, using the global `session` object for storage.
513
496
497
+
Flask has built-in support for sessions stored in a cookie, but due to the length of the identity cookies, the sample uses the [Flask-session](https://flask-session.readthedocs.io/) package instead. Everything is initialized in *app.py*:
For production, you should use [a setting](https://flask-session.readthedocs.io/en/latest/#configuration) that persists across multiple instances and deploys of your app, such as "sqlachemy" or "redis".
536
504
537
505
---
538
506
539
507
## Next steps
540
508
541
509
At this point, when the user signs in, a token is stored in the token cache. Let's see how it's then used in other parts of the web app.
542
510
543
-
[Remove accounts from the cache on global sign-out](scenario-web-app-call-api-sign-in.md)
511
+
# [ASP.NET Core](#tab/aspnetcore)
512
+
513
+
Move on to the next article in this scenario,
514
+
[Remove accounts from the cache on global sign out](scenario-web-app-call-api-sign-in.md?tabs=aspnetcore).
515
+
516
+
# [ASP.NET](#tab/aspnet)
517
+
518
+
Move on to the next article in this scenario,
519
+
[Remove accounts from the cache on global sign out](scenario-web-app-call-api-sign-in.md?tabs=aspnet).
520
+
521
+
# [Java](#tab/java)
522
+
523
+
Move on to the next article in this scenario,
524
+
[Remove accounts from the cache on global sign out](scenario-web-app-call-api-sign-in.md?tabs=java).
525
+
526
+
# [Python](#tab/python)
527
+
528
+
Move on to the next article in this scenario,
529
+
[Remove accounts from the cache on global sign out](scenario-web-app-call-api-sign-in.md?tabs=python).
0 commit comments