Skip to content

Commit f3db10e

Browse files
Port fix for #53423 to main (#56702)
1 parent 6aab04c commit f3db10e

File tree

2 files changed

+77
-48
lines changed

2 files changed

+77
-48
lines changed

src/Security/Authentication/JwtBearer/src/JwtBearerConfigureOptions.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ public void Configure(string? name, JwtBearerOptions options)
4040
return;
4141
}
4242

43+
var validateIssuer = StringHelpers.ParseValueOrDefault(configSection[nameof(TokenValidationParameters.ValidateIssuer)], bool.Parse, options.TokenValidationParameters.ValidateIssuer);
4344
var issuer = configSection[nameof(TokenValidationParameters.ValidIssuer)];
4445
var issuers = configSection.GetSection(nameof(TokenValidationParameters.ValidIssuers)).GetChildren().Select(iss => iss.Value).ToList();
46+
var validateAudience = StringHelpers.ParseValueOrDefault(configSection[nameof(TokenValidationParameters.ValidateAudience)], bool.Parse, options.TokenValidationParameters.ValidateAudience);
4547
var audience = configSection[nameof(TokenValidationParameters.ValidAudience)];
4648
var audiences = configSection.GetSection(nameof(TokenValidationParameters.ValidAudiences)).GetChildren().Select(aud => aud.Value).ToList();
4749

@@ -63,10 +65,10 @@ public void Configure(string? name, JwtBearerOptions options)
6365
options.SaveToken = StringHelpers.ParseValueOrDefault(configSection[nameof(options.SaveToken)], bool.Parse, options.SaveToken);
6466
options.TokenValidationParameters = new()
6567
{
66-
ValidateIssuer = issuers.Count > 0,
68+
ValidateIssuer = validateIssuer,
6769
ValidIssuers = issuers,
6870
ValidIssuer = issuer,
69-
ValidateAudience = audiences.Count > 0,
71+
ValidateAudience = validateAudience,
7072
ValidAudiences = audiences,
7173
ValidAudience = audience,
7274
ValidateIssuerSigningKey = true,

src/Security/Authentication/test/JwtBearerTests_Handler.cs

Lines changed: 73 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,9 @@ public class JwtBearerTests_Handler : SharedAuthenticationTests<JwtBearerOptions
3131
protected override bool SupportsSignIn { get => false; }
3232
protected override bool SupportsSignOut { get => false; }
3333

34-
protected override void RegisterAuth(AuthenticationBuilder services, Action<JwtBearerOptions> configure)
35-
{
36-
services.AddJwtBearer(o =>
37-
{
38-
ConfigureDefaults(o);
39-
configure.Invoke(o);
40-
});
41-
}
42-
43-
private void ConfigureDefaults(JwtBearerOptions o)
34+
protected override void RegisterAuth(AuthenticationBuilder services, Action<JwtBearerOptions> configure = null)
4435
{
36+
services.AddJwtBearer(configure);
4537
}
4638

4739
[Fact]
@@ -964,26 +956,20 @@ public async Task ExpirationAndIssuedWhenMinOrMaxValue()
964956
[Fact]
965957
public void CanReadJwtBearerOptionsFromConfig()
966958
{
967-
var services = new ServiceCollection().AddLogging();
968-
var config = new ConfigurationBuilder().AddInMemoryCollection(new[]
969-
{
970-
new KeyValuePair<string, string>("Authentication:Schemes:Bearer:ValidIssuer", "dotnet-user-jwts"),
971-
new KeyValuePair<string, string>("Authentication:Schemes:Bearer:ValidIssuers:0", "dotnet-user-jwts-2"),
972-
new KeyValuePair<string, string>("Authentication:Schemes:Bearer:ValidAudience", "http://localhost:5000"),
973-
new KeyValuePair<string, string>("Authentication:Schemes:Bearer:ValidAudiences:0", "http://localhost:5001"),
974-
new KeyValuePair<string, string>("Authentication:Schemes:Bearer:BackchannelTimeout", "00:01:00"),
975-
new KeyValuePair<string, string>("Authentication:Schemes:Bearer:RequireHttpsMetadata", "false"),
976-
new KeyValuePair<string, string>("Authentication:Schemes:Bearer:SaveToken", "True"),
977-
}).Build();
959+
var services = new ServiceCollection();
960+
var config = new ConfigurationBuilder().AddInMemoryCollection([
961+
new("Authentication:Schemes:Bearer:ValidIssuer", "dotnet-user-jwts"),
962+
new("Authentication:Schemes:Bearer:ValidIssuers:0", "dotnet-user-jwts-2"),
963+
new("Authentication:Schemes:Bearer:ValidAudience", "http://localhost:5000"),
964+
new("Authentication:Schemes:Bearer:ValidAudiences:0", "http://localhost:5001"),
965+
new("Authentication:Schemes:Bearer:BackchannelTimeout", "00:01:00"),
966+
new("Authentication:Schemes:Bearer:RequireHttpsMetadata", "false"),
967+
new("Authentication:Schemes:Bearer:SaveToken", "True"),
968+
]).Build();
978969
services.AddSingleton<IConfiguration>(config);
979970

980971
// Act
981-
var builder = services.AddAuthentication(o =>
982-
{
983-
o.AddScheme<TestHandler>("Bearer", "Bearer");
984-
});
985-
builder.AddJwtBearer("Bearer");
986-
RegisterAuth(builder, _ => { });
972+
RegisterAuth(services.AddAuthentication());
987973
var sp = services.BuildServiceProvider();
988974

989975
// Assert
@@ -995,7 +981,12 @@ public void CanReadJwtBearerOptionsFromConfig()
995981
Assert.Equal(TimeSpan.FromSeconds(60), jwtBearerOptions.BackchannelTimeout);
996982
Assert.False(jwtBearerOptions.RequireHttpsMetadata);
997983
Assert.True(jwtBearerOptions.SaveToken);
998-
Assert.True(jwtBearerOptions.MapInboundClaims); // Assert default values are respected
984+
// ValidateIssuerSigningKey should always be set to its non-default value of true if options are read from config.
985+
Assert.True(jwtBearerOptions.TokenValidationParameters.ValidateIssuerSigningKey);
986+
// Assert default values for other options are respected.
987+
Assert.True(jwtBearerOptions.MapInboundClaims);
988+
Assert.True(jwtBearerOptions.TokenValidationParameters.ValidateIssuer);
989+
Assert.True(jwtBearerOptions.TokenValidationParameters.ValidateAudience);
999990
}
1000991

1001992
[Fact]
@@ -1026,29 +1017,23 @@ public void CanReadMultipleAudiencesFromConfig()
10261017
[Fact]
10271018
public void CanReadMultipleIssuersFromConfig()
10281019
{
1029-
var services = new ServiceCollection().AddLogging();
1020+
var services = new ServiceCollection();
10301021
var firstKey = "qPG6tDtfxFYZifHW3sEueQ==";
10311022
var secondKey = "6JPzXj6aOPdojlZdeLshaA==";
1032-
var config = new ConfigurationBuilder().AddInMemoryCollection(new[]
1033-
{
1034-
new KeyValuePair<string, string>("Authentication:Schemes:Bearer:ValidIssuers:0", "dotnet-user-jwts"),
1035-
new KeyValuePair<string, string>("Authentication:Schemes:Bearer:ValidIssuers:1", "dotnet-user-jwts-2"),
1036-
new KeyValuePair<string, string>("Authentication:Schemes:Bearer:SigningKeys:0:Issuer", "dotnet-user-jwts"),
1037-
new KeyValuePair<string, string>("Authentication:Schemes:Bearer:SigningKeys:0:Value", firstKey),
1038-
new KeyValuePair<string, string>("Authentication:Schemes:Bearer:SigningKeys:0:Length", "32"),
1039-
new KeyValuePair<string, string>("Authentication:Schemes:Bearer:SigningKeys:1:Issuer", "dotnet-user-jwts-2"),
1040-
new KeyValuePair<string, string>("Authentication:Schemes:Bearer:SigningKeys:1:Value", secondKey),
1041-
new KeyValuePair<string, string>("Authentication:Schemes:Bearer:SigningKeys:1:Length", "32"),
1042-
}).Build();
1023+
var config = new ConfigurationBuilder().AddInMemoryCollection([
1024+
new("Authentication:Schemes:Bearer:ValidIssuers:0", "dotnet-user-jwts"),
1025+
new("Authentication:Schemes:Bearer:ValidIssuers:1", "dotnet-user-jwts-2"),
1026+
new("Authentication:Schemes:Bearer:SigningKeys:0:Issuer", "dotnet-user-jwts"),
1027+
new("Authentication:Schemes:Bearer:SigningKeys:0:Value", firstKey),
1028+
new("Authentication:Schemes:Bearer:SigningKeys:0:Length", "32"),
1029+
new("Authentication:Schemes:Bearer:SigningKeys:1:Issuer", "dotnet-user-jwts-2"),
1030+
new("Authentication:Schemes:Bearer:SigningKeys:1:Value", secondKey),
1031+
new("Authentication:Schemes:Bearer:SigningKeys:1:Length", "32"),
1032+
]).Build();
10431033
services.AddSingleton<IConfiguration>(config);
10441034

10451035
// Act
1046-
var builder = services.AddAuthentication(o =>
1047-
{
1048-
o.AddScheme<TestHandler>("Bearer", "Bearer");
1049-
});
1050-
builder.AddJwtBearer("Bearer");
1051-
RegisterAuth(builder, _ => { });
1036+
RegisterAuth(services.AddAuthentication());
10521037
var sp = services.BuildServiceProvider();
10531038

10541039
// Assert
@@ -1058,6 +1043,48 @@ public void CanReadMultipleIssuersFromConfig()
10581043
Assert.Equal(secondKey, Convert.ToBase64String(jwtBearerOptions.TokenValidationParameters.IssuerSigningKeys.OfType<SymmetricSecurityKey>().LastOrDefault()?.Key));
10591044
}
10601045

1046+
[Fact]
1047+
public void IssuerAndAudienceValidationEnabledByDefaultWhenOptionsAreReadFromConfig()
1048+
{
1049+
var services = new ServiceCollection();
1050+
var config = new ConfigurationBuilder().AddInMemoryCollection([
1051+
new("Authentication:Schemes:Bearer:Authority", "https://localhost:5001"),
1052+
]).Build();
1053+
services.AddSingleton<IConfiguration>(config);
1054+
1055+
// Act
1056+
RegisterAuth(services.AddAuthentication());
1057+
var sp = services.BuildServiceProvider();
1058+
1059+
// Assert
1060+
var jwtBearerOptions = sp.GetRequiredService<IOptionsMonitor<JwtBearerOptions>>().Get(JwtBearerDefaults.AuthenticationScheme);
1061+
Assert.Equal("https://localhost:5001", jwtBearerOptions.Authority);
1062+
Assert.True(jwtBearerOptions.TokenValidationParameters.ValidateIssuer);
1063+
Assert.True(jwtBearerOptions.TokenValidationParameters.ValidateAudience);
1064+
}
1065+
1066+
[Fact]
1067+
public void IssuerAndAudienceValidationCanBeDisabledFromConfig()
1068+
{
1069+
var services = new ServiceCollection();
1070+
var config = new ConfigurationBuilder().AddInMemoryCollection([
1071+
new("Authentication:Schemes:Bearer:Authority", "https://localhost:5001"),
1072+
new("Authentication:Schemes:Bearer:ValidateIssuer", "false"),
1073+
new("Authentication:Schemes:Bearer:ValidateAudience", "false"),
1074+
]).Build();
1075+
services.AddSingleton<IConfiguration>(config);
1076+
1077+
// Act
1078+
RegisterAuth(services.AddAuthentication());
1079+
var sp = services.BuildServiceProvider();
1080+
1081+
// Assert
1082+
var jwtBearerOptions = sp.GetRequiredService<IOptionsMonitor<JwtBearerOptions>>().Get(JwtBearerDefaults.AuthenticationScheme);
1083+
Assert.Equal("https://localhost:5001", jwtBearerOptions.Authority);
1084+
Assert.False(jwtBearerOptions.TokenValidationParameters.ValidateIssuer);
1085+
Assert.False(jwtBearerOptions.TokenValidationParameters.ValidateAudience);
1086+
}
1087+
10611088
class InvalidTokenValidator : TokenHandler
10621089
{
10631090
public InvalidTokenValidator()

0 commit comments

Comments
 (0)