Skip to content

Commit 8c373f6

Browse files
authored
Renaming2 (#269)
* Renaming GetAccessTokenOnBehalfOfUserAsync into GetAccessTokenForUserAsync as the OnBehalfOfUser was telling too much about OBO, whereas in the case of a Web App this was not the OBO flow. * Addressing PR feedback
1 parent 794daae commit 8c373f6

File tree

19 files changed

+118
-22
lines changed

19 files changed

+118
-22
lines changed

2-WebApp-graph-user/2-1-Call-MSGraph/AspnetCoreWebApp-calls-Microsoft-Graph.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApp-OpenIDConnect-DotNet
77
EndProject
88
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Identity.Web", "..\..\Microsoft.Identity.Web\Microsoft.Identity.Web.csproj", "{E0CEF26A-6CE6-4505-851B-6580D5564752}"
99
EndProject
10+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Identity.Web.Test", "..\..\Microsoft.Identity.Web.Test\Microsoft.Identity.Web.Test.csproj", "{0EEC3E2E-69D0-4A7F-98D6-4386330F4965}"
11+
EndProject
1012
Global
1113
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1214
Debug|Any CPU = Debug|Any CPU
@@ -21,6 +23,10 @@ Global
2123
{E0CEF26A-6CE6-4505-851B-6580D5564752}.Debug|Any CPU.Build.0 = Debug|Any CPU
2224
{E0CEF26A-6CE6-4505-851B-6580D5564752}.Release|Any CPU.ActiveCfg = Release|Any CPU
2325
{E0CEF26A-6CE6-4505-851B-6580D5564752}.Release|Any CPU.Build.0 = Release|Any CPU
26+
{0EEC3E2E-69D0-4A7F-98D6-4386330F4965}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27+
{0EEC3E2E-69D0-4A7F-98D6-4386330F4965}.Debug|Any CPU.Build.0 = Debug|Any CPU
28+
{0EEC3E2E-69D0-4A7F-98D6-4386330F4965}.Release|Any CPU.ActiveCfg = Release|Any CPU
29+
{0EEC3E2E-69D0-4A7F-98D6-4386330F4965}.Release|Any CPU.Build.0 = Release|Any CPU
2430
EndGlobalSection
2531
GlobalSection(SolutionProperties) = preSolution
2632
HideSolutionNode = FALSE

2-WebApp-graph-user/2-1-Call-MSGraph/Controllers/HomeController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public async Task<IActionResult> Profile()
6161
{
6262
return GraphServiceClientFactory.GetAuthenticatedGraphClient(async () =>
6363
{
64-
string result = await tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(scopes);
64+
string result = await tokenAcquisition.GetAccessTokenForUserAsync(scopes);
6565
return result;
6666
}, webOptions.GraphApiUrl);
6767
}

2-WebApp-graph-user/2-2-TokenCache/Controllers/HomeController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public IActionResult Index()
3131
public async Task<IActionResult> Profile()
3232
{
3333
var accessToken =
34-
await tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(new[] {Constants.ScopeUserRead});
34+
await tokenAcquisition.GetAccessTokenForUserAsync(new[] {Constants.ScopeUserRead});
3535

3636
var me = await graphApiOperations.GetUserInformation(accessToken);
3737
var photo = await graphApiOperations.GetPhotoAsBase64Async(accessToken);

2-WebApp-graph-user/2-3-Multi-Tenant/Controllers/TodoListController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public async Task<IActionResult> Edit(int id)
9797
var userTenant = User.GetTenantId();
9898

9999
// Acquiring token for graph in the signed-in users tenant, so it can be used to retrieve all the users from their tenant
100-
var graphAccessToken = await _tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(new string[] { GraphScope.UserReadAll }, userTenant);
100+
var graphAccessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new string[] { GraphScope.UserReadAll }, userTenant);
101101

102102
TempData["UsersDropDown"] = (await _msGraphService.GetUsersAsync(graphAccessToken))
103103
.Select(u => new SelectListItem

2-WebApp-graph-user/2-3-Multi-Tenant/README-National-Cloud.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,10 +318,10 @@ If a multi-tenant app needs to acquire an access token for Microsoft Graph to be
318318
```csharp
319319
var userTenant = User.GetTenantId();
320320
// Acquiring token for graph using the user's tenant, so it can return all the users from their tenant
321-
var graphAccessToken = await _tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(new string[] { GraphScope.UserReadAll }, userTenant);
321+
var graphAccessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new string[] { GraphScope.UserReadAll }, userTenant);
322322
```
323323

324-
We are acquiring an access token for Graph with the scope `User.Read.All`, to list all the users from the tenant so you can assign a todo item to them. `GetAccessTokenOnBehalfOfUserAsync` is a helper method found on `Microsoft.Identity.Web` project, and it receives a **tenantId** as parameter to acquire a token for the desired authority. For that, we get the current authority from the built `IConfidentialClientApplication` and replace the tenantId. Below is an example of this logic.
324+
We are acquiring an access token for Graph with the scope `User.Read.All`, to list all the users from the tenant so you can assign a todo item to them. `GetAccessTokenForUserAsync` is a helper method found on `Microsoft.Identity.Web` project, and it receives a **tenantId** as parameter to acquire a token for the desired authority. For that, we get the current authority from the built `IConfidentialClientApplication` and replace the tenantId. Below is an example of this logic.
325325

326326
```csharp
327327
string signedUserAuthority = confidentialClientApplication.Authority.Replace(new Uri(confidentialClientApplication.Authority).PathAndQuery, $"/{tenant}/");

2-WebApp-graph-user/2-3-Multi-Tenant/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,10 +294,10 @@ If a multi-tenant app needs to acquire an access token for Microsoft Graph to be
294294
```csharp
295295
var userTenant = User.GetTenantId();
296296
// Acquiring token for graph using the user's tenant, so it can return all the users from their tenant
297-
var graphAccessToken = await _tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(new string[] { GraphScope.UserReadAll }, userTenant);
297+
var graphAccessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new string[] { GraphScope.UserReadAll }, userTenant);
298298
```
299299

300-
We are acquiring an access token for Graph with the scope `User.Read.All`, to list all the users from the tenant so you can assign a todo item to them. `GetAccessTokenOnBehalfOfUserAsync` is a helper method found on `Microsoft.Identity.Web` project, and it receives a **tenantId** as parameter to acquire a token for the desired authority. For that, we get the current authority from the built `IConfidentialClientApplication` and replace the tenantId. Below is an example of this logic.
300+
We are acquiring an access token for Graph with the scope `User.Read.All`, to list all the users from the tenant so you can assign a todo item to them. `GetAccessTokenForUserAsync` is a helper method found on `Microsoft.Identity.Web` project, and it receives a **tenantId** as parameter to acquire a token for the desired authority. For that, we get the current authority from the built `IConfidentialClientApplication` and replace the tenantId. Below is an example of this logic.
301301

302302
```csharp
303303
string signedUserAuthority = confidentialClientApplication.Authority.Replace(new Uri(confidentialClientApplication.Authority).PathAndQuery, $"/{tenant}/");

2-WebApp-graph-user/2-4-Sovereign-Call-MSGraph/Controllers/HomeController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public IActionResult Index()
3131
public async Task<IActionResult> Profile()
3232
{
3333
var accessToken =
34-
await tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(new[] {Constants.ScopeUserRead});
34+
await tokenAcquisition.GetAccessTokenForUserAsync(new[] {Constants.ScopeUserRead});
3535

3636
var me = await graphApiOperations.GetUserInformation(accessToken);
3737
var photo = await graphApiOperations.GetPhotoAsBase64Async(accessToken);

3-WebApp-multi-APIs/Controllers/HomeController.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public IActionResult Index()
3939
public async Task<IActionResult> Profile()
4040
{
4141
var accessToken =
42-
await tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(new[] {Constants.ScopeUserRead});
42+
await tokenAcquisition.GetAccessTokenForUserAsync(new[] {Constants.ScopeUserRead});
4343

4444
var me = await graphApiOperations.GetUserInformation(accessToken);
4545
var photo = await graphApiOperations.GetPhotoAsBase64Async(accessToken);
@@ -56,12 +56,12 @@ public async Task<IActionResult> Profile()
5656
public async Task<IActionResult> Tenants()
5757
{
5858
var accessToken =
59-
await tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(new[] { $"{ArmApiOperationService.ArmResource}user_impersonation" });
59+
await tokenAcquisition.GetAccessTokenForUserAsync(new[] { $"{ArmApiOperationService.ArmResource}user_impersonation" });
6060

6161
var tenantIds = await armOperations.EnumerateTenantsIdsAccessibleByUser(accessToken);
6262
/*
6363
var tenantsIdsAndNames = await graphApiOperations.EnumerateTenantsIdAndNameAccessibleByUser(tenantIds,
64-
async tenantId => { return await tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(new string[] { "Directory.Read.All" }, tenantId); });
64+
async tenantId => { return await tokenAcquisition.GetAccessTokenForUserAsync(new string[] { "Directory.Read.All" }, tenantId); });
6565
*/
6666
ViewData["tenants"] = tenantIds;
6767

@@ -77,7 +77,7 @@ public async Task<IActionResult> Blob()
7777
var scopes = new string[] { "https://storage.azure.com/user_impersonation" };
7878

7979
var accessToken =
80-
await tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(scopes);
80+
await tokenAcquisition.GetAccessTokenForUserAsync(scopes);
8181

8282
// create a blob on behalf of the user
8383
TokenCredential tokenCredential = new TokenCredential(accessToken);

4-WebApp-your-API/Client/Services/TodoListService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ public async Task<IEnumerable<Todo>> GetAsync()
138138

139139
private async Task PrepareAuthenticatedClient()
140140
{
141-
var accessToken = await this._tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(new[] { this._TodoListScope });
141+
var accessToken = await this._tokenAcquisition.GetAccessTokenForUserAsync(new[] { this._TodoListScope });
142142
Debug.WriteLine($"access token-{accessToken}");
143143
this._httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
144144
this._httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

5-WebApp-AuthZ/5-1-Roles/Controllers/AccountController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public async Task<IActionResult> Groups()
4141

4242
GraphServiceClient graphServiceClient = GraphServiceClientFactory.GetAuthenticatedGraphClient(async () =>
4343
{
44-
string result = await tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(scopes);
44+
string result = await tokenAcquisition.GetAccessTokenForUserAsync(scopes);
4545
return result;
4646
}, webOptions.GraphApiUrl);
4747

5-WebApp-AuthZ/5-1-Roles/Controllers/HomeController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public async Task<IActionResult> Profile()
6060
{
6161
return GraphServiceClientFactory.GetAuthenticatedGraphClient(async () =>
6262
{
63-
string result = await tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(scopes);
63+
string result = await tokenAcquisition.GetAccessTokenForUserAsync(scopes);
6464
return result;
6565
}, webOptions.GraphApiUrl);
6666
}

5-WebApp-AuthZ/5-2-Groups/Controllers/UserProfileController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public async Task<IActionResult> Index()
2727
// Using group ids/names in the IsInRole method
2828
// var isinrole = User.IsInRole("8873daa2-17af-4e72-973e-930c94ef7549");
2929

30-
string accessToken = await tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(new[] { Constants.ScopeUserRead, Constants.ScopeDirectoryReadAll });
30+
string accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(new[] { Constants.ScopeUserRead, Constants.ScopeDirectoryReadAll });
3131

3232
User me = await graphService.GetMeAsync(accessToken);
3333
ViewData["Me"] = me;

Microsoft.Identity.Web/ClaimsPrincipalFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public static class ClaimsPrincipalFactory
3030
/// subscriptionStore.GetSubscriptionInfo(notification.SubscriptionId);
3131
/// HttpContext.User = ClaimsPrincipalExtension.FromTenantIdAndObjectId(subscription.TenantId,
3232
/// subscription.UserId);
33-
/// string accessToken = await tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(scopes);
33+
/// string accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(scopes);
3434
/// </code>
3535
/// </example>
3636
public static ClaimsPrincipal FromTenantIdAndObjectId(string tenantId, string objectId)

Microsoft.Identity.Web/ITokenAcquisition.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
55
using Microsoft.AspNetCore.Http;
66
using Microsoft.Identity.Client;
7+
using System;
78
using System.Collections.Generic;
89
using System.Threading.Tasks;
910

@@ -54,8 +55,21 @@ public interface ITokenAcquisition
5455
/// <param name="tenantId">Enables to override the tenant/account for the same identity. This is useful in the
5556
/// cases where a given account is a guest in other tenants, and you want to acquire tokens for a specific tenant</param>
5657
/// <returns>An access token to call on behalf of the user, the downstream API characterized by its scopes</returns>
58+
[Obsolete("Renamed to GetAccessTokenForUserAsync")]
5759
Task<string> GetAccessTokenOnBehalfOfUserAsync(IEnumerable<string> scopes, string tenantId = null);
5860

61+
/// <summary>
62+
/// Typically used from an ASP.NET Core Web App or Web API controller, this method gets an access token
63+
/// for a downstream API on behalf of the user account which claims are provided in the <see cref="HttpContext.User"/>
64+
/// member of the <paramref name="context"/> parameter
65+
/// </summary>
66+
/// <param name="context">HttpContext associated with the Controller or auth operation</param>
67+
/// <param name="scopes">Scopes to request for the downstream API to call</param>
68+
/// <param name="tenantId">Enables to override the tenant/account for the same identity. This is useful in the
69+
/// cases where a given account is guest in other tenants, and you want to acquire tokens for a specific tenant</param>
70+
/// <returns>An access token to call on behalf of the user, the downstream API characterized by its scopes</returns>
71+
Task<string> GetAccessTokenForUserAsync(IEnumerable<string> scopes, string tenantId = null);
72+
5973
/// <summary>
6074
/// Removes the account associated with context.HttpContext.User from the MSAL.NET cache
6175
/// </summary>

Microsoft.Identity.Web/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ public class HomeController : Controller
118118
...
119119
```
120120

121-
Then in your controller actions, you'll need to call: `ITokenAcquisition.GetAccessTokenOnBehalfOfUserAsync` passing the scopes for which to request a token. The other methods of ITokenAcquisition are used from the `AddWebAppCallsProtectedWebApi()` method and similar methods for web APIs (see below).
121+
Then in your controller actions, you'll need to call: `ITokenAcquisition.GetAccessTokenForUserAsync` passing the scopes for which to request a token. The other methods of ITokenAcquisition are used from the `AddWebAppCallsProtectedWebApi()` method and similar methods for web APIs (see below).
122122

123123
```CSharp
124124
[Authorize]
@@ -130,7 +130,7 @@ public class HomeController : Controller
130130
public async Task<IActionResult> Action()
131131
{
132132
string[] scopes = new []{"user.read"};
133-
string token = await tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(scopes);
133+
string token = await tokenAcquisition.GetAccessTokenForUserAsync(scopes);
134134
...
135135
// call the downstream API with the bearer token in the Authorize header
136136
}
@@ -235,7 +235,7 @@ For your web API to call downstream APIs, you'll need to:
235235

236236
<img alt="ScopesRequiredHttpContextExtensions" src="https://user-images.githubusercontent.com/13203188/64253176-f9e3ca80-cf1c-11e9-8fe9-df06cee11c25.png" width="80%"/>
237237

238-
- in your controller actions, to call: `ITokenAcquisition.GetAccessTokenOnBehalfOfUserAsync` passing the scopes for which to request a token.
238+
- in your controller actions, to call: `ITokenAcquisition.GetAccessTokenForUserAsync` passing the scopes for which to request a token.
239239

240240
The following code snippet shows how to combine these steps:
241241

Microsoft.Identity.Web/TokenAcquisition.cs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,34 @@ public async Task AddAccountToCacheFromAuthorizationCodeAsync(AuthorizationCodeR
158158
/// passing the validated token (as a JwtSecurityToken). Calling it from a Web App supposes that
159159
/// you have previously called AddAccountToCacheFromAuthorizationCodeAsync from a method called by
160160
/// OpenIdConnectOptions.Events.OnAuthorizationCodeReceived</remarks>
161+
[Obsolete("Renamed to GetAccessTokenForUserAsync. Please use that method")]
161162
public async Task<string> GetAccessTokenOnBehalfOfUserAsync(
162163
IEnumerable<string> scopes,
163164
string tenant = null)
165+
{
166+
return await GetAccessTokenForUserAsync(scopes, tenant);
167+
}
168+
169+
/// <summary>
170+
/// Typically used from a Web App or WebAPI controller, this method retrieves an access token
171+
/// for a downstream API using;
172+
/// 1) the token cache (for Web Apps and Web APis) if a token exists in the cache
173+
/// 2) or the <a href='https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow'>on-behalf-of flow</a>
174+
/// in Web APIs, for the user account that is ascertained from claims are provided in the <see cref="HttpContext.User"/>
175+
/// instance of the current HttpContext
176+
/// </summary>
177+
/// <param name="scopes">Scopes to request for the downstream API to call</param>
178+
/// <param name="tenant">Enables overriding of the tenant/account for the same identity. This is useful in the
179+
/// cases where a given account is guest in other tenants, and you want to acquire tokens for a specific tenant, like where the user is a guest in</param>
180+
/// <returns>An access token to call the downstream API and populated with this downstream Api's scopes</returns>
181+
/// <remarks>Calling this method from a Web API supposes that you have previously called,
182+
/// in a method called by JwtBearerOptions.Events.OnTokenValidated, the HttpContextExtensions.StoreTokenUsedToCallWebAPI method
183+
/// passing the validated token (as a JwtSecurityToken). Calling it from a Web App supposes that
184+
/// you have previously called AddAccountToCacheFromAuthorizationCodeAsync from a method called by
185+
/// OpenIdConnectOptions.Events.OnAuthorizationCodeReceived</remarks>
186+
public async Task<string> GetAccessTokenForUserAsync(
187+
IEnumerable<string> scopes,
188+
string tenant = null)
164189
{
165190
if (scopes == null)
166191
{
@@ -179,8 +204,9 @@ public async Task<string> GetAccessTokenOnBehalfOfUserAsync(
179204

180205
catch (MsalUiRequiredException ex)
181206
{
207+
// GetAccessTokenForUserAsync is an abstraction that can be called from a Web App or a Web API
182208
Debug.WriteLine(ex.Message);
183-
// GetAccessTokenOnBehalfOfUserAsync is an abstraction that can be called from a Web App or a Web API
209+
184210
// to get a token for a Web API on behalf of the user, but not necessarily with the on behalf of OAuth2.0
185211
// flow as this one only applies to Web APIs.
186212
JwtSecurityToken validatedToken = CurrentHttpContext.GetTokenUsedToCallWebAPI();

Microsoft.Identity.Web/TokenCacheProviders/MsalAbstractTokenCacheProvider.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ public async Task ClearAsync()
110110
{
111111
// This is a user token cache
112112
await RemoveKeyAsync(GetCacheKey(false)).ConfigureAwait(false);
113+
114+
// TODO: Clear the cookie session if any. Get inspiration from
115+
// https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/issues/240
113116
}
114117

115118
/// <summary>

0 commit comments

Comments
 (0)