From 54f8c74baaaae57bd12b09c8186629e100e0bb52 Mon Sep 17 00:00:00 2001 From: satma0745 Date: Thu, 14 Dec 2023 18:17:07 +0300 Subject: [PATCH 1/8] Populate the ValidIssuer and the ValidAudience properties of the TokenValidationParameters. --- .../Authentication/JwtBearer/src/JwtBearerConfigureOptions.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Security/Authentication/JwtBearer/src/JwtBearerConfigureOptions.cs b/src/Security/Authentication/JwtBearer/src/JwtBearerConfigureOptions.cs index 812eb9287aa3..0f977b4ea609 100644 --- a/src/Security/Authentication/JwtBearer/src/JwtBearerConfigureOptions.cs +++ b/src/Security/Authentication/JwtBearer/src/JwtBearerConfigureOptions.cs @@ -73,8 +73,10 @@ public void Configure(string? name, JwtBearerOptions options) { ValidateIssuer = issuers.Count > 0, ValidIssuers = issuers, + ValidIssuer = issuer, ValidateAudience = audiences.Count > 0, ValidAudiences = audiences, + ValidAudience = audience, ValidateIssuerSigningKey = true, IssuerSigningKeys = GetIssuerSigningKeys(configSection, issuers), }; From f9eb63e08e650c161c170e78f703e08509aa5d41 Mon Sep 17 00:00:00 2001 From: satma0745 Date: Thu, 14 Dec 2023 20:05:45 +0300 Subject: [PATCH 2/8] Update tests to showcase the proposed behavior. --- .../Authentication/test/JwtBearerTests.cs | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/Security/Authentication/test/JwtBearerTests.cs b/src/Security/Authentication/test/JwtBearerTests.cs index bf63ccc7cbd1..57d930b66278 100755 --- a/src/Security/Authentication/test/JwtBearerTests.cs +++ b/src/Security/Authentication/test/JwtBearerTests.cs @@ -1017,8 +1017,7 @@ public void CanReadJwtBearerOptionsFromConfig() var config = new ConfigurationBuilder().AddInMemoryCollection(new[] { new KeyValuePair("Authentication:Schemes:Bearer:ValidIssuer", "dotnet-user-jwts"), - new KeyValuePair("Authentication:Schemes:Bearer:ValidAudiences:0", "http://localhost:5000"), - new KeyValuePair("Authentication:Schemes:Bearer:ValidAudiences:1", "https://localhost:5001"), + new KeyValuePair("Authentication:Schemes:Bearer:ValidAudience", "http://localhost:5000"), new KeyValuePair("Authentication:Schemes:Bearer:BackchannelTimeout", "00:01:00"), new KeyValuePair("Authentication:Schemes:Bearer:RequireHttpsMetadata", "false"), new KeyValuePair("Authentication:Schemes:Bearer:SaveToken", "True"), @@ -1036,14 +1035,40 @@ public void CanReadJwtBearerOptionsFromConfig() // Assert var jwtBearerOptions = sp.GetRequiredService>().Get(JwtBearerDefaults.AuthenticationScheme); + Assert.Equal(jwtBearerOptions.TokenValidationParameters.ValidIssuer, "dotnet-user-jwts"); Assert.Equal(jwtBearerOptions.TokenValidationParameters.ValidIssuers, new[] { "dotnet-user-jwts" }); - Assert.Equal(jwtBearerOptions.TokenValidationParameters.ValidAudiences, new[] { "http://localhost:5000", "https://localhost:5001" }); + Assert.Equal(jwtBearerOptions.TokenValidationParameters.ValidAudience, "http://localhost:5000"); + Assert.Equal(jwtBearerOptions.TokenValidationParameters.ValidAudiences, new[] { "http://localhost:5000" }); Assert.Equal(jwtBearerOptions.BackchannelTimeout, TimeSpan.FromSeconds(60)); Assert.False(jwtBearerOptions.RequireHttpsMetadata); Assert.True(jwtBearerOptions.SaveToken); Assert.True(jwtBearerOptions.MapInboundClaims); // Assert default values are respected } + [Fact] + public void CanReadMultipleAudiencesFromConfig() + { + var services = new ServiceCollection().AddLogging(); + var config = new ConfigurationBuilder().AddInMemoryCollection(new[] + { + new KeyValuePair("Authentication:Schemes:Bearer:ValidAudiences:0", "http://localhost:5000"), + new KeyValuePair("Authentication:Schemes:Bearer:ValidAudiences:0", "https://localhost:5001") + }).Build(); + services.AddSingleton(config); + + // Act + var builder = services.AddAuthentication(o => + { + o.AddScheme("Bearer", "Bearer"); + }); + builder.AddJwtBearer("Bearer", o => o.UseSecurityTokenValidators = true); + RegisterAuth(builder, _ => { }); + var sp = services.BuildServiceProvider(); + + var jwtBearerOptions = sp.GetRequiredService>().Get(JwtBearerDefaults.AuthenticationScheme); + Assert.Equal(jwtBearerOptions.TokenValidationParameters.ValidAudiences, new[] { "http://localhost:5000", "https://localhost:5001" }); + } + [Fact] public void CanReadMultipleIssuersFromConfig() { From 4207d1c5114129da63984eff90c2597474ea9b76 Mon Sep 17 00:00:00 2001 From: satma0745 Date: Thu, 14 Dec 2023 20:11:01 +0300 Subject: [PATCH 3/8] Explicitly specify the Assert section of a test. --- src/Security/Authentication/test/JwtBearerTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Security/Authentication/test/JwtBearerTests.cs b/src/Security/Authentication/test/JwtBearerTests.cs index 57d930b66278..665bd2863db1 100755 --- a/src/Security/Authentication/test/JwtBearerTests.cs +++ b/src/Security/Authentication/test/JwtBearerTests.cs @@ -1065,6 +1065,7 @@ public void CanReadMultipleAudiencesFromConfig() RegisterAuth(builder, _ => { }); var sp = services.BuildServiceProvider(); + // Assert var jwtBearerOptions = sp.GetRequiredService>().Get(JwtBearerDefaults.AuthenticationScheme); Assert.Equal(jwtBearerOptions.TokenValidationParameters.ValidAudiences, new[] { "http://localhost:5000", "https://localhost:5001" }); } From f0c46ce96e20e708c1148126e26256e3818a4165 Mon Sep 17 00:00:00 2001 From: satma0745 Date: Thu, 14 Dec 2023 20:47:10 +0300 Subject: [PATCH 4/8] Fix tests: swap expected and actual sides. --- src/Security/Authentication/test/JwtBearerTests.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Security/Authentication/test/JwtBearerTests.cs b/src/Security/Authentication/test/JwtBearerTests.cs index 665bd2863db1..e10d1e87bac7 100755 --- a/src/Security/Authentication/test/JwtBearerTests.cs +++ b/src/Security/Authentication/test/JwtBearerTests.cs @@ -1035,11 +1035,11 @@ public void CanReadJwtBearerOptionsFromConfig() // Assert var jwtBearerOptions = sp.GetRequiredService>().Get(JwtBearerDefaults.AuthenticationScheme); - Assert.Equal(jwtBearerOptions.TokenValidationParameters.ValidIssuer, "dotnet-user-jwts"); - Assert.Equal(jwtBearerOptions.TokenValidationParameters.ValidIssuers, new[] { "dotnet-user-jwts" }); - Assert.Equal(jwtBearerOptions.TokenValidationParameters.ValidAudience, "http://localhost:5000"); - Assert.Equal(jwtBearerOptions.TokenValidationParameters.ValidAudiences, new[] { "http://localhost:5000" }); - Assert.Equal(jwtBearerOptions.BackchannelTimeout, TimeSpan.FromSeconds(60)); + Assert.Equal("dotnet-user-jwts", jwtBearerOptions.TokenValidationParameters.ValidIssuer); + Assert.Equal(new[] { "dotnet-user-jwts" }, jwtBearerOptions.TokenValidationParameters.ValidIssuers); + Assert.Equal("http://localhost:5000", jwtBearerOptions.TokenValidationParameters.ValidAudience); + Assert.Equal(new[] { "http://localhost:5000" }, jwtBearerOptions.TokenValidationParameters.ValidAudiences); + Assert.Equal(TimeSpan.FromSeconds(60), jwtBearerOptions.BackchannelTimeout); Assert.False(jwtBearerOptions.RequireHttpsMetadata); Assert.True(jwtBearerOptions.SaveToken); Assert.True(jwtBearerOptions.MapInboundClaims); // Assert default values are respected @@ -1067,7 +1067,7 @@ public void CanReadMultipleAudiencesFromConfig() // Assert var jwtBearerOptions = sp.GetRequiredService>().Get(JwtBearerDefaults.AuthenticationScheme); - Assert.Equal(jwtBearerOptions.TokenValidationParameters.ValidAudiences, new[] { "http://localhost:5000", "https://localhost:5001" }); + Assert.Equal(new[] { "http://localhost:5000", "https://localhost:5001" }, jwtBearerOptions.TokenValidationParameters.ValidAudiences); } [Fact] From 96101d4853dfb9230ac7d7de911207a6bb1924bd Mon Sep 17 00:00:00 2001 From: satma0745 Date: Thu, 14 Dec 2023 22:35:10 +0300 Subject: [PATCH 5/8] Fix tests: use proper configuration parameter names. --- src/Security/Authentication/test/JwtBearerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Security/Authentication/test/JwtBearerTests.cs b/src/Security/Authentication/test/JwtBearerTests.cs index e10d1e87bac7..3e7e8461f018 100755 --- a/src/Security/Authentication/test/JwtBearerTests.cs +++ b/src/Security/Authentication/test/JwtBearerTests.cs @@ -1052,7 +1052,7 @@ public void CanReadMultipleAudiencesFromConfig() var config = new ConfigurationBuilder().AddInMemoryCollection(new[] { new KeyValuePair("Authentication:Schemes:Bearer:ValidAudiences:0", "http://localhost:5000"), - new KeyValuePair("Authentication:Schemes:Bearer:ValidAudiences:0", "https://localhost:5001") + new KeyValuePair("Authentication:Schemes:Bearer:ValidAudiences:1", "https://localhost:5001") }).Build(); services.AddSingleton(config); From 25fd66be5cdad915febab976890203edd38453cb Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Fri, 2 Feb 2024 14:19:24 -0800 Subject: [PATCH 6/8] Remove singular issuer and audience from plural properties --- .../JwtBearer/src/JwtBearerConfigureOptions.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Security/Authentication/JwtBearer/src/JwtBearerConfigureOptions.cs b/src/Security/Authentication/JwtBearer/src/JwtBearerConfigureOptions.cs index 0f977b4ea609..4a4fe81b5d0b 100644 --- a/src/Security/Authentication/JwtBearer/src/JwtBearerConfigureOptions.cs +++ b/src/Security/Authentication/JwtBearer/src/JwtBearerConfigureOptions.cs @@ -42,16 +42,8 @@ public void Configure(string? name, JwtBearerOptions options) var issuer = configSection[nameof(TokenValidationParameters.ValidIssuer)]; var issuers = configSection.GetSection(nameof(TokenValidationParameters.ValidIssuers)).GetChildren().Select(iss => iss.Value).ToList(); - if (issuer is not null) - { - issuers.Add(issuer); - } var audience = configSection[nameof(TokenValidationParameters.ValidAudience)]; var audiences = configSection.GetSection(nameof(TokenValidationParameters.ValidAudiences)).GetChildren().Select(aud => aud.Value).ToList(); - if (audience is not null) - { - audiences.Add(audience); - } options.Authority = configSection[nameof(options.Authority)] ?? options.Authority; options.BackchannelTimeout = StringHelpers.ParseValueOrDefault(configSection[nameof(options.BackchannelTimeout)], _invariantTimeSpanParse, options.BackchannelTimeout); From b34ea4e708196861a274b11288251229b89bcbd2 Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Fri, 2 Feb 2024 14:24:33 -0800 Subject: [PATCH 7/8] Fix tests --- src/Security/Authentication/test/JwtBearerTests.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Security/Authentication/test/JwtBearerTests.cs b/src/Security/Authentication/test/JwtBearerTests.cs index 3e7e8461f018..aaf0122ae3fd 100755 --- a/src/Security/Authentication/test/JwtBearerTests.cs +++ b/src/Security/Authentication/test/JwtBearerTests.cs @@ -1016,6 +1016,7 @@ public void CanReadJwtBearerOptionsFromConfig() var services = new ServiceCollection().AddLogging(); var config = new ConfigurationBuilder().AddInMemoryCollection(new[] { + new KeyValuePair("Authentication:Schemes:Bearer:ValidIssuer", "dotnet-user-jwts"), new KeyValuePair("Authentication:Schemes:Bearer:ValidIssuer", "dotnet-user-jwts"), new KeyValuePair("Authentication:Schemes:Bearer:ValidAudience", "http://localhost:5000"), new KeyValuePair("Authentication:Schemes:Bearer:BackchannelTimeout", "00:01:00"), @@ -1036,9 +1037,9 @@ public void CanReadJwtBearerOptionsFromConfig() // Assert var jwtBearerOptions = sp.GetRequiredService>().Get(JwtBearerDefaults.AuthenticationScheme); Assert.Equal("dotnet-user-jwts", jwtBearerOptions.TokenValidationParameters.ValidIssuer); - Assert.Equal(new[] { "dotnet-user-jwts" }, jwtBearerOptions.TokenValidationParameters.ValidIssuers); + Assert.Empty(jwtBearerOptions.TokenValidationParameters.ValidIssuers); Assert.Equal("http://localhost:5000", jwtBearerOptions.TokenValidationParameters.ValidAudience); - Assert.Equal(new[] { "http://localhost:5000" }, jwtBearerOptions.TokenValidationParameters.ValidAudiences); + Assert.Empty(jwtBearerOptions.TokenValidationParameters.ValidAudiences); Assert.Equal(TimeSpan.FromSeconds(60), jwtBearerOptions.BackchannelTimeout); Assert.False(jwtBearerOptions.RequireHttpsMetadata); Assert.True(jwtBearerOptions.SaveToken); From 2701366ddf83091fa89ebd776185605e25ccbd5d Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Wed, 21 Feb 2024 14:28:46 -0800 Subject: [PATCH 8/8] Try again to fix tests --- .../test/AuthenticationMiddlewareTests.cs | 2 +- .../Authentication/test/JwtBearerTests.cs | 96 ------------------- .../test/JwtBearerTests_Handler.cs | 38 +++++++- 3 files changed, 34 insertions(+), 102 deletions(-) diff --git a/src/Security/Authentication/test/AuthenticationMiddlewareTests.cs b/src/Security/Authentication/test/AuthenticationMiddlewareTests.cs index 03d9f14b7222..7eb0a6187a1c 100644 --- a/src/Security/Authentication/test/AuthenticationMiddlewareTests.cs +++ b/src/Security/Authentication/test/AuthenticationMiddlewareTests.cs @@ -177,7 +177,7 @@ public async Task WebApplicationBuilder_RegistersAuthenticationAndAuthorizationM Assert.True(app.Properties.ContainsKey("__AuthorizationMiddlewareSet")); var options = app.Services.GetService>().Get(JwtBearerDefaults.AuthenticationScheme); - Assert.Equal(new[] { "SomeIssuer" }, options.TokenValidationParameters.ValidIssuers); + Assert.Equal("SomeIssuer", options.TokenValidationParameters.ValidIssuer); Assert.Equal(new[] { "https://localhost:5001" }, options.TokenValidationParameters.ValidAudiences); } diff --git a/src/Security/Authentication/test/JwtBearerTests.cs b/src/Security/Authentication/test/JwtBearerTests.cs index aaf0122ae3fd..639324deff29 100755 --- a/src/Security/Authentication/test/JwtBearerTests.cs +++ b/src/Security/Authentication/test/JwtBearerTests.cs @@ -1010,102 +1010,6 @@ public async Task ExpirationAndIssuedWhenMinOrMaxValue() Assert.Equal(max, elementValueUtc); } - [Fact] - public void CanReadJwtBearerOptionsFromConfig() - { - var services = new ServiceCollection().AddLogging(); - var config = new ConfigurationBuilder().AddInMemoryCollection(new[] - { - new KeyValuePair("Authentication:Schemes:Bearer:ValidIssuer", "dotnet-user-jwts"), - new KeyValuePair("Authentication:Schemes:Bearer:ValidIssuer", "dotnet-user-jwts"), - new KeyValuePair("Authentication:Schemes:Bearer:ValidAudience", "http://localhost:5000"), - new KeyValuePair("Authentication:Schemes:Bearer:BackchannelTimeout", "00:01:00"), - new KeyValuePair("Authentication:Schemes:Bearer:RequireHttpsMetadata", "false"), - new KeyValuePair("Authentication:Schemes:Bearer:SaveToken", "True"), - }).Build(); - services.AddSingleton(config); - - // Act - var builder = services.AddAuthentication(o => - { - o.AddScheme("Bearer", "Bearer"); - }); - builder.AddJwtBearer("Bearer", o => o.UseSecurityTokenValidators = true); - RegisterAuth(builder, _ => { }); - var sp = services.BuildServiceProvider(); - - // Assert - var jwtBearerOptions = sp.GetRequiredService>().Get(JwtBearerDefaults.AuthenticationScheme); - Assert.Equal("dotnet-user-jwts", jwtBearerOptions.TokenValidationParameters.ValidIssuer); - Assert.Empty(jwtBearerOptions.TokenValidationParameters.ValidIssuers); - Assert.Equal("http://localhost:5000", jwtBearerOptions.TokenValidationParameters.ValidAudience); - Assert.Empty(jwtBearerOptions.TokenValidationParameters.ValidAudiences); - Assert.Equal(TimeSpan.FromSeconds(60), jwtBearerOptions.BackchannelTimeout); - Assert.False(jwtBearerOptions.RequireHttpsMetadata); - Assert.True(jwtBearerOptions.SaveToken); - Assert.True(jwtBearerOptions.MapInboundClaims); // Assert default values are respected - } - - [Fact] - public void CanReadMultipleAudiencesFromConfig() - { - var services = new ServiceCollection().AddLogging(); - var config = new ConfigurationBuilder().AddInMemoryCollection(new[] - { - new KeyValuePair("Authentication:Schemes:Bearer:ValidAudiences:0", "http://localhost:5000"), - new KeyValuePair("Authentication:Schemes:Bearer:ValidAudiences:1", "https://localhost:5001") - }).Build(); - services.AddSingleton(config); - - // Act - var builder = services.AddAuthentication(o => - { - o.AddScheme("Bearer", "Bearer"); - }); - builder.AddJwtBearer("Bearer", o => o.UseSecurityTokenValidators = true); - RegisterAuth(builder, _ => { }); - var sp = services.BuildServiceProvider(); - - // Assert - var jwtBearerOptions = sp.GetRequiredService>().Get(JwtBearerDefaults.AuthenticationScheme); - Assert.Equal(new[] { "http://localhost:5000", "https://localhost:5001" }, jwtBearerOptions.TokenValidationParameters.ValidAudiences); - } - - [Fact] - public void CanReadMultipleIssuersFromConfig() - { - var services = new ServiceCollection().AddLogging(); - var firstKey = "qPG6tDtfxFYZifHW3sEueQ=="; - var secondKey = "6JPzXj6aOPdojlZdeLshaA=="; - var config = new ConfigurationBuilder().AddInMemoryCollection(new[] - { - new KeyValuePair("Authentication:Schemes:Bearer:ValidIssuers:0", "dotnet-user-jwts"), - new KeyValuePair("Authentication:Schemes:Bearer:ValidIssuers:1", "dotnet-user-jwts-2"), - new KeyValuePair("Authentication:Schemes:Bearer:SigningKeys:0:Issuer", "dotnet-user-jwts"), - new KeyValuePair("Authentication:Schemes:Bearer:SigningKeys:0:Value", firstKey), - new KeyValuePair("Authentication:Schemes:Bearer:SigningKeys:0:Length", "32"), - new KeyValuePair("Authentication:Schemes:Bearer:SigningKeys:1:Issuer", "dotnet-user-jwts-2"), - new KeyValuePair("Authentication:Schemes:Bearer:SigningKeys:1:Value", secondKey), - new KeyValuePair("Authentication:Schemes:Bearer:SigningKeys:1:Length", "32"), - }).Build(); - services.AddSingleton(config); - - // Act - var builder = services.AddAuthentication(o => - { - o.AddScheme("Bearer", "Bearer"); - }); - builder.AddJwtBearer("Bearer", o => o.UseSecurityTokenValidators = true); - RegisterAuth(builder, _ => { }); - var sp = services.BuildServiceProvider(); - - // Assert - var jwtBearerOptions = sp.GetRequiredService>().Get(JwtBearerDefaults.AuthenticationScheme); - Assert.Equal(2, jwtBearerOptions.TokenValidationParameters.IssuerSigningKeys.Count()); - Assert.Equal(firstKey, Convert.ToBase64String(jwtBearerOptions.TokenValidationParameters.IssuerSigningKeys.OfType().FirstOrDefault()?.Key)); - Assert.Equal(secondKey, Convert.ToBase64String(jwtBearerOptions.TokenValidationParameters.IssuerSigningKeys.OfType().LastOrDefault()?.Key)); - } - class InvalidTokenValidator : ISecurityTokenValidator { public InvalidTokenValidator() diff --git a/src/Security/Authentication/test/JwtBearerTests_Handler.cs b/src/Security/Authentication/test/JwtBearerTests_Handler.cs index 6d8260c2a39f..844904b4da09 100644 --- a/src/Security/Authentication/test/JwtBearerTests_Handler.cs +++ b/src/Security/Authentication/test/JwtBearerTests_Handler.cs @@ -968,8 +968,9 @@ public void CanReadJwtBearerOptionsFromConfig() var config = new ConfigurationBuilder().AddInMemoryCollection(new[] { new KeyValuePair("Authentication:Schemes:Bearer:ValidIssuer", "dotnet-user-jwts"), - new KeyValuePair("Authentication:Schemes:Bearer:ValidAudiences:0", "http://localhost:5000"), - new KeyValuePair("Authentication:Schemes:Bearer:ValidAudiences:1", "https://localhost:5001"), + new KeyValuePair("Authentication:Schemes:Bearer:ValidIssuers:0", "dotnet-user-jwts-2"), + new KeyValuePair("Authentication:Schemes:Bearer:ValidAudience", "http://localhost:5000"), + new KeyValuePair("Authentication:Schemes:Bearer:ValidAudiences:0", "http://localhost:5001"), new KeyValuePair("Authentication:Schemes:Bearer:BackchannelTimeout", "00:01:00"), new KeyValuePair("Authentication:Schemes:Bearer:RequireHttpsMetadata", "false"), new KeyValuePair("Authentication:Schemes:Bearer:SaveToken", "True"), @@ -987,14 +988,41 @@ public void CanReadJwtBearerOptionsFromConfig() // Assert var jwtBearerOptions = sp.GetRequiredService>().Get(JwtBearerDefaults.AuthenticationScheme); - Assert.Equal(jwtBearerOptions.TokenValidationParameters.ValidIssuers, new[] { "dotnet-user-jwts" }); - Assert.Equal(jwtBearerOptions.TokenValidationParameters.ValidAudiences, new[] { "http://localhost:5000", "https://localhost:5001" }); - Assert.Equal(jwtBearerOptions.BackchannelTimeout, TimeSpan.FromSeconds(60)); + Assert.Equal("dotnet-user-jwts", jwtBearerOptions.TokenValidationParameters.ValidIssuer); + Assert.Equal(["dotnet-user-jwts-2"], jwtBearerOptions.TokenValidationParameters.ValidIssuers); + Assert.Equal("http://localhost:5000", jwtBearerOptions.TokenValidationParameters.ValidAudience); + Assert.Equal(["http://localhost:5001"], jwtBearerOptions.TokenValidationParameters.ValidAudiences); + Assert.Equal(TimeSpan.FromSeconds(60), jwtBearerOptions.BackchannelTimeout); Assert.False(jwtBearerOptions.RequireHttpsMetadata); Assert.True(jwtBearerOptions.SaveToken); Assert.True(jwtBearerOptions.MapInboundClaims); // Assert default values are respected } + [Fact] + public void CanReadMultipleAudiencesFromConfig() + { + var services = new ServiceCollection().AddLogging(); + var config = new ConfigurationBuilder().AddInMemoryCollection(new[] + { + new KeyValuePair("Authentication:Schemes:Bearer:ValidAudiences:0", "http://localhost:5000"), + new KeyValuePair("Authentication:Schemes:Bearer:ValidAudiences:1", "https://localhost:5001") + }).Build(); + services.AddSingleton(config); + + // Act + var builder = services.AddAuthentication(o => + { + o.AddScheme("Bearer", "Bearer"); + }); + builder.AddJwtBearer("Bearer"); + RegisterAuth(builder, _ => { }); + var sp = services.BuildServiceProvider(); + + // Assert + var jwtBearerOptions = sp.GetRequiredService>().Get(JwtBearerDefaults.AuthenticationScheme); + Assert.Equal(["http://localhost:5000", "https://localhost:5001"], jwtBearerOptions.TokenValidationParameters.ValidAudiences); + } + [Fact] public void CanReadMultipleIssuersFromConfig() {