diff --git a/src/Security/Authentication/JwtBearer/src/JwtBearerConfigureOptions.cs b/src/Security/Authentication/JwtBearer/src/JwtBearerConfigureOptions.cs index 812eb9287aa3..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); @@ -73,8 +65,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), }; 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 bf63ccc7cbd1..639324deff29 100755 --- a/src/Security/Authentication/test/JwtBearerTests.cs +++ b/src/Security/Authentication/test/JwtBearerTests.cs @@ -1010,75 +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:ValidAudiences:0", "http://localhost:5000"), - new KeyValuePair("Authentication:Schemes:Bearer:ValidAudiences:1", "https://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"), - }).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(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.False(jwtBearerOptions.RequireHttpsMetadata); - Assert.True(jwtBearerOptions.SaveToken); - Assert.True(jwtBearerOptions.MapInboundClaims); // Assert default values are respected - } - - [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() {