Skip to content

Commit 958bafe

Browse files
authored
Synching Microsoft.Identity.Web with Web api tuto (#109)
1 parent 8ecf6d5 commit 958bafe

File tree

2 files changed

+37
-5
lines changed

2 files changed

+37
-5
lines changed

Microsoft.Identity.Web/Client/TokenAcquisition.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,20 @@ public async Task<string> GetAccessTokenOnBehalfOfUser(HttpContext context, IEnu
165165

166166
// Use MSAL to get the right token to call the API
167167
var application = BuildConfidentialClientApplication(context, context.User);
168-
return await GetAccessTokenOnBehalfOfUser(application, context.User, scopes, tenant);
168+
169+
// Case of a lazy OBO
170+
Claim jwtClaim = context.User.FindFirst("jwt");
171+
if (jwtClaim != null)
172+
{
173+
(context.User.Identity as ClaimsIdentity).RemoveClaim(jwtClaim);
174+
var result = await application.AcquireTokenOnBehalfOf(scopes.Except(scopesRequestedByMsalNet), new UserAssertion(jwtClaim.Value))
175+
.ExecuteAsync();
176+
return result.AccessToken;
177+
}
178+
else
179+
{
180+
return await GetAccessTokenOnBehalfOfUser(application, context.User, scopes, tenant);
181+
}
169182
}
170183

171184
/// <summary>

Microsoft.Identity.Web/WebApiStartupHelpers.cs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
using Microsoft.Identity.Web.Client;
77
using Microsoft.Identity.Web.Resource;
88
using System.Collections.Generic;
9+
using System.IdentityModel.Tokens.Jwt;
10+
using System.Linq;
11+
using System.Security.Claims;
912
using System.Threading.Tasks;
1013

1114
namespace Microsoft.Identity.Web
@@ -59,22 +62,38 @@ public static IServiceCollection AddProtectWebApiWithMicrosoftIdentityPlatformV2
5962
/// </summary>
6063
/// <param name="services">Service collection to which to add authentication</param>
6164
/// <param name="configuration">Configuration</param>
65+
/// <param name="scopes">Optional parameters. If not specified, the token used to call the protected API
66+
/// will be kept with the user's claims until the API calls a downstream API. Otherwise the account for the
67+
/// user is immediately added to the token cache</param>
6268
/// <returns></returns>
63-
public static IServiceCollection AddProtectedApiCallsWebApis(this IServiceCollection services, IConfiguration configuration, IEnumerable<string> scopes)
69+
public static IServiceCollection AddProtectedApiCallsWebApis(this IServiceCollection services, IConfiguration configuration, IEnumerable<string> scopes=null)
6470
{
6571
services.AddTokenAcquisition();
6672
services.Configure<JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, options =>
6773
{
74+
// If you don't pre-provide scopes when adding calling AddProtectedApiCallsWebApis, the On behalf of
75+
// flow will be delayed (lazy construction of MSAL's application
76+
6877
options.Events.OnTokenValidated = async context =>
6978
{
70-
var tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService<ITokenAcquisition>();
71-
context.Success();
79+
if (scopes != null && scopes.Any())
80+
{
81+
var tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService<ITokenAcquisition>();
82+
context.Success();
83+
tokenAcquisition.AddAccountToCacheFromJwt(context, scopes);
84+
}
85+
else
86+
{
87+
context.Success();
7288

89+
// Todo : rather use options.SaveToken?
90+
(context.Principal.Identity as ClaimsIdentity).AddClaim(new Claim("jwt", (context.SecurityToken as JwtSecurityToken).RawData));
91+
}
7392
// Adds the token to the cache, and also handles the incremental consent and claim challenges
74-
tokenAcquisition.AddAccountToCacheFromJwt(context, scopes);
7593
await Task.FromResult(0);
7694
};
7795
});
96+
7897
return services;
7998
}
8099
}

0 commit comments

Comments
 (0)