Skip to content

Commit fae4a56

Browse files
authored
Add MapInboundClaims top level sugar for JwtBearerOptions (#24636)
* Add MapInboundClaims option * Update JwtBearerOptions.cs * Update JwtBearerTests.cs * Update JwtBearerOptions.cs * Update JwtBearerOptions.cs * Update JwtBearerTests.cs * Add MapImboundClaims to OIDC * Update OpenIdConnectTests.cs * Update OpenIdConnectOptions.cs * Update OpenIdConnectOptions.cs * Use MapInboundClaims * Update OpenIdConnectTests.cs
1 parent 60cb3bb commit fae4a56

File tree

5 files changed

+79
-4
lines changed

5 files changed

+79
-4
lines changed

src/Security/Authentication/JwtBearer/src/JwtBearerOptions.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ namespace Microsoft.AspNetCore.Authentication.JwtBearer
1616
/// </summary>
1717
public class JwtBearerOptions : AuthenticationSchemeOptions
1818
{
19+
private JwtSecurityTokenHandler _defaultHandler = new JwtSecurityTokenHandler();
20+
21+
public JwtBearerOptions()
22+
{
23+
SecurityTokenValidators = new List<ISecurityTokenValidator> { _defaultHandler };
24+
}
25+
1926
/// <summary>
2027
/// Gets or sets if HTTPS is required for the metadata address or authority.
2128
/// The default is true. This should be disabled only in development environments.
@@ -90,7 +97,7 @@ public class JwtBearerOptions : AuthenticationSchemeOptions
9097
/// <summary>
9198
/// Gets the ordered list of <see cref="ISecurityTokenValidator"/> used to validate access tokens.
9299
/// </summary>
93-
public IList<ISecurityTokenValidator> SecurityTokenValidators { get; } = new List<ISecurityTokenValidator> { new JwtSecurityTokenHandler() };
100+
public IList<ISecurityTokenValidator> SecurityTokenValidators { get; private set; }
94101

95102
/// <summary>
96103
/// Gets or sets the parameters used to validate identity tokens.
@@ -111,6 +118,18 @@ public class JwtBearerOptions : AuthenticationSchemeOptions
111118
/// from returning an error and an error_description in the WWW-Authenticate header.
112119
/// </summary>
113120
public bool IncludeErrorDetails { get; set; } = true;
121+
122+
/// <summary>
123+
/// Gets or sets the <see cref="MapInboundClaims"/> property on the default instance of <see cref="JwtSecurityTokenHandler"/> in SecurityTokenValidators, which is used when determining
124+
/// whether or not to map claim types that are extracted when validating a <see cref="JwtSecurityToken"/>.
125+
/// <para>If this is set to true, the Claim Type is set to the JSON claim 'name' after translating using this mapping. Otherwise, no mapping occurs.</para>
126+
/// <para>The default value is true.</para>
127+
/// </summary>
128+
public bool MapInboundClaims
129+
{
130+
get => _defaultHandler.MapInboundClaims;
131+
set => _defaultHandler.MapInboundClaims = value;
132+
}
114133

115134
/// <summary>
116135
/// 1 day is the default time interval that afterwards, <see cref="ConfigurationManager" /> will obtain new configuration.

src/Security/Authentication/OpenIdConnect/samples/OpenIdConnectSample/Startup.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,6 @@ public static bool DisallowsSameSiteNone(string userAgent)
8989

9090
public void ConfigureServices(IServiceCollection services)
9191
{
92-
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
93-
9492
services.Configure<CookiePolicyOptions>(options =>
9593
{
9694
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
@@ -120,6 +118,7 @@ public void ConfigureServices(IServiceCollection services)
120118
o.SaveTokens = true;
121119
o.GetClaimsFromUserInfoEndpoint = true;
122120
o.AccessDeniedPath = "/access-denied-from-remote";
121+
o.MapInboundClaims = false;
123122

124123
// o.ClaimActions.MapAllExcept("aud", "iss", "iat", "nbf", "exp", "aio", "c_hash", "uti", "nonce");
125124

src/Security/Authentication/OpenIdConnect/src/OpenIdConnectOptions.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
1818
public class OpenIdConnectOptions : RemoteAuthenticationOptions
1919
{
2020
private CookieBuilder _nonceCookieBuilder;
21+
private JwtSecurityTokenHandler _defaultHandler = new JwtSecurityTokenHandler();
2122

2223
/// <summary>
2324
/// Initializes a new <see cref="OpenIdConnectOptions"/>
@@ -38,6 +39,7 @@ public OpenIdConnectOptions()
3839
CallbackPath = new PathString("/signin-oidc");
3940
SignedOutCallbackPath = new PathString("/signout-callback-oidc");
4041
RemoteSignOutPath = new PathString("/signout-oidc");
42+
SecurityTokenValidator = _defaultHandler;
4143

4244
Events = new OpenIdConnectEvents();
4345
Scope.Add("openid");
@@ -253,7 +255,7 @@ public override void Validate()
253255
/// <summary>
254256
/// Gets or sets the <see cref="ISecurityTokenValidator"/> used to validate identity tokens.
255257
/// </summary>
256-
public ISecurityTokenValidator SecurityTokenValidator { get; set; } = new JwtSecurityTokenHandler();
258+
public ISecurityTokenValidator SecurityTokenValidator { get; set; }
257259

258260
/// <summary>
259261
/// Gets or sets the parameters used to validate identity tokens.
@@ -337,5 +339,17 @@ public override CookieOptions Build(HttpContext context, DateTimeOffset expiresF
337339
/// The minimum time between <see cref="ConfigurationManager" /> retrievals, in the event that a retrieval failed, or that a refresh was explicitly requested. 30 seconds is the default.
338340
/// </summary>
339341
public TimeSpan RefreshInterval { get; set; } = ConfigurationManager<OpenIdConnectConfiguration>.DefaultRefreshInterval;
342+
343+
/// <summary>
344+
/// Gets or sets the <see cref="MapInboundClaims"/> property on the default instance of <see cref="JwtSecurityTokenHandler"/> in SecurityTokenValidator, which is used when determining
345+
/// whether or not to map claim types that are extracted when validating a <see cref="JwtSecurityToken"/>.
346+
/// <para>If this is set to true, the Claim Type is set to the JSON claim 'name' after translating using this mapping. Otherwise, no mapping occurs.</para>
347+
/// <para>The default value is true.</para>
348+
/// </summary>
349+
public bool MapInboundClaims
350+
{
351+
get => _defaultHandler.MapInboundClaims;
352+
set => _defaultHandler.MapInboundClaims = value;
353+
}
340354
}
341355
}

src/Security/Authentication/test/JwtBearerTests.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,27 @@ public async Task SaveBearerToken()
116116
Assert.Equal(tokenText, await response.Response.Content.ReadAsStringAsync());
117117
}
118118

119+
[Fact]
120+
public void MapInboundClaimsDefaultsToTrue()
121+
{
122+
var options = new JwtBearerOptions();
123+
Assert.True(options.MapInboundClaims);
124+
var jwtHandler = options.SecurityTokenValidators.First() as JwtSecurityTokenHandler;
125+
Assert.NotNull(jwtHandler);
126+
Assert.True(jwtHandler.MapInboundClaims);
127+
}
128+
129+
[Fact]
130+
public void MapInboundClaimsCanBeSetToFalse()
131+
{
132+
var options = new JwtBearerOptions();
133+
options.MapInboundClaims = false;
134+
Assert.False(options.MapInboundClaims);
135+
var jwtHandler = options.SecurityTokenValidators.First() as JwtSecurityTokenHandler;
136+
Assert.NotNull(jwtHandler);
137+
Assert.False(jwtHandler.MapInboundClaims);
138+
}
139+
119140
[Fact]
120141
public async Task SignInThrows()
121142
{

src/Security/Authentication/test/OpenIdConnect/OpenIdConnectTests.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Globalization;
6+
using System.IdentityModel.Tokens.Jwt;
67
using System.Linq;
78
using System.Net;
89
using System.Security.Claims;
@@ -366,6 +367,27 @@ public async Task RemoteSignOut_Get_Successful()
366367
Assert.Contains(remoteSignOutTransaction.Response.Headers, h => h.Key == "Set-Cookie");
367368
}
368369

370+
[Fact]
371+
public void MapInboundClaimsDefaultsToTrue()
372+
{
373+
var options = new OpenIdConnectOptions();
374+
Assert.True(options.MapInboundClaims);
375+
var jwtHandler = options.SecurityTokenValidator as JwtSecurityTokenHandler;
376+
Assert.NotNull(jwtHandler);
377+
Assert.True(jwtHandler.MapInboundClaims);
378+
}
379+
380+
[Fact]
381+
public void MapInboundClaimsCanBeSetToFalse()
382+
{
383+
var options = new OpenIdConnectOptions();
384+
options.MapInboundClaims = false;
385+
Assert.False(options.MapInboundClaims);
386+
var jwtHandler = options.SecurityTokenValidator as JwtSecurityTokenHandler;
387+
Assert.NotNull(jwtHandler);
388+
Assert.False(jwtHandler.MapInboundClaims);
389+
}
390+
369391
// Test Cases for calculating the expiration time of cookie from cookie name
370392
[Fact]
371393
public void NonceCookieExpirationTime()

0 commit comments

Comments
 (0)