55using Microsoft . Extensions . DependencyInjection ;
66using Microsoft . Identity . Web . Client ;
77using Microsoft . Identity . Web . Resource ;
8+ using Microsoft . IdentityModel . Tokens ;
89using System . Collections . Generic ;
910using System . IdentityModel . Tokens . Jwt ;
1011using System . Linq ;
1112using System . Security . Claims ;
13+ using System . Security . Cryptography . X509Certificates ;
1214using System . Threading . Tasks ;
1315
1416namespace Microsoft . Identity . Web
@@ -22,7 +24,7 @@ public static class WebApiStartupHelpers
2224 /// <param name="services">Service collection to which to add authentication</param>
2325 /// <param name="configuration">Configuration</param>
2426 /// <returns></returns>
25- public static IServiceCollection AddProtectWebApiWithMicrosoftIdentityPlatformV2 ( this IServiceCollection services , IConfiguration configuration )
27+ public static IServiceCollection AddProtectWebApiWithMicrosoftIdentityPlatformV2 ( this IServiceCollection services , IConfiguration configuration , X509Certificate2 tokenDecryptionCertificate = null )
2628 {
2729 services . AddAuthentication ( AzureADDefaults . JwtBearerAuthenticationScheme )
2830 . AddAzureADBearer ( options => configuration . Bind ( "AzureAd" , options ) ) ;
@@ -45,6 +47,12 @@ public static IServiceCollection AddProtectWebApiWithMicrosoftIdentityPlatformV2
4547 // we inject our own multitenant validation logic (which even accepts both V1 and V2 tokens)
4648 options . TokenValidationParameters . IssuerValidator = AadIssuerValidator . GetIssuerValidator ( options . Authority ) . ValidateAadIssuer ;
4749
50+ // If you provide a token decryption certificate, it will be used to decrypt the token
51+ if ( tokenDecryptionCertificate != null )
52+ {
53+ options . TokenValidationParameters . TokenDecryptionKey = new X509SecurityKey ( tokenDecryptionCertificate ) ;
54+ }
55+
4856 // When an access token for our own Web API is validated, we add it to MSAL.NET's cache so that it can
4957 // be used from the controllers.
5058 options . Events = new JwtBearerEvents ( ) ;
@@ -66,14 +74,13 @@ public static IServiceCollection AddProtectWebApiWithMicrosoftIdentityPlatformV2
6674 /// will be kept with the user's claims until the API calls a downstream API. Otherwise the account for the
6775 /// user is immediately added to the token cache</param>
6876 /// <returns></returns>
69- public static IServiceCollection AddProtectedApiCallsWebApis ( this IServiceCollection services , IConfiguration configuration , IEnumerable < string > scopes = null )
77+ public static IServiceCollection AddProtectedApiCallsWebApis ( this IServiceCollection services , IConfiguration configuration , IEnumerable < string > scopes = null )
7078 {
7179 services . AddTokenAcquisition ( ) ;
7280 services . Configure < JwtBearerOptions > ( AzureADDefaults . JwtBearerAuthenticationScheme , options =>
7381 {
7482 // If you don't pre-provide scopes when adding calling AddProtectedApiCallsWebApis, the On behalf of
7583 // flow will be delayed (lazy construction of MSAL's application
76-
7784 options . Events . OnTokenValidated = async context =>
7885 {
7986 if ( scopes != null && scopes . Any ( ) )
@@ -87,7 +94,12 @@ public static IServiceCollection AddProtectedApiCallsWebApis(this IServiceCollec
8794 context . Success ( ) ;
8895
8996 // Todo : rather use options.SaveToken?
90- ( context . Principal . Identity as ClaimsIdentity ) . AddClaim ( new Claim ( "jwt" , ( context . SecurityToken as JwtSecurityToken ) . RawData ) ) ;
97+ JwtSecurityToken jwtSecurityToken = context . SecurityToken as JwtSecurityToken ;
98+ if ( jwtSecurityToken != null )
99+ {
100+ string rawData = ( jwtSecurityToken . InnerToken != null ) ? jwtSecurityToken . InnerToken . RawData : jwtSecurityToken . RawData ;
101+ ( context . Principal . Identity as ClaimsIdentity ) . AddClaim ( new Claim ( "jwt" , rawData ) ) ;
102+ }
91103 }
92104 // Adds the token to the cache, and also handles the incremental consent and claim challenges
93105 await Task . FromResult ( 0 ) ;
0 commit comments