diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ac0c0f53..d161bb39c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,6 +20,16 @@ jobs: runs-on: ${{ matrix.runs-on }} steps: - uses: actions/checkout@af513c7a016048ae468971c52ed77d9562c7c819 + + - name: Setup dotnet + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '5.0.100-rc.2.20479.15' + - name: Setup dotnet + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '3.1.x' + - run: dotnet --info - if: contains(matrix.runs-on, 'macOS') || contains(matrix.runs-on, 'ubuntu') diff --git a/global.json b/global.json index 70db89729..2a7b742c5 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "3.1.402" + "version": "5.0.100-rc.2.20479.15" } } \ No newline at end of file diff --git a/src/AspNetIdentity/host/Host.csproj b/src/AspNetIdentity/host/Host.csproj index e05fab5b8..2c0f98b38 100644 --- a/src/AspNetIdentity/host/Host.csproj +++ b/src/AspNetIdentity/host/Host.csproj @@ -1,20 +1,16 @@  - netcoreapp3.1 + netcoreapp3.1;net5.0 - - - - diff --git a/src/AspNetIdentity/src/Duende.IdentityServer.AspNetIdentity.csproj b/src/AspNetIdentity/src/Duende.IdentityServer.AspNetIdentity.csproj index bff809739..7cb4bc281 100644 --- a/src/AspNetIdentity/src/Duende.IdentityServer.AspNetIdentity.csproj +++ b/src/AspNetIdentity/src/Duende.IdentityServer.AspNetIdentity.csproj @@ -2,7 +2,7 @@ Duende.IdentityServer.AspNetIdentity - netcoreapp3.1 + netcoreapp3.1;net5.0 ASP.NET Core Identity Integration for Duende IdentityServer Duende.IdentityServer.AspNetIdentity diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index c56cb591c..5aeb16da6 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -1,11 +1,21 @@ + 5.0.0-* + + + 3.1.0 3.1.0 3.1.0 - - 5.0.0-* + 5.6.0 + + + + 5.0.0-rc.2.* + 5.0.0-rc.2.* + 5.0.0-rc.2.* + 6.8.0 @@ -40,9 +50,8 @@ - - - + + diff --git a/src/EntityFramework.Storage/src/Duende.IdentityServer.EntityFramework.Storage.csproj b/src/EntityFramework.Storage/src/Duende.IdentityServer.EntityFramework.Storage.csproj index ca94a0c16..1cd4abe65 100644 --- a/src/EntityFramework.Storage/src/Duende.IdentityServer.EntityFramework.Storage.csproj +++ b/src/EntityFramework.Storage/src/Duende.IdentityServer.EntityFramework.Storage.csproj @@ -1,7 +1,7 @@  Duende.IdentityServer.EntityFramework.Storage - netstandard2.0 + netstandard2.0;net5.0 EntityFramework persistence layer for Duende IdentityServer true diff --git a/src/EntityFramework.Storage/test/IntegrationTests/IntegrationTests.csproj b/src/EntityFramework.Storage/test/IntegrationTests/IntegrationTests.csproj index e0bf3ab76..e87f24a59 100644 --- a/src/EntityFramework.Storage/test/IntegrationTests/IntegrationTests.csproj +++ b/src/EntityFramework.Storage/test/IntegrationTests/IntegrationTests.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp3.1;net5.0 diff --git a/src/EntityFramework.Storage/test/UnitTests/UnitTests.csproj b/src/EntityFramework.Storage/test/UnitTests/UnitTests.csproj index 2282622fd..0ec514e29 100644 --- a/src/EntityFramework.Storage/test/UnitTests/UnitTests.csproj +++ b/src/EntityFramework.Storage/test/UnitTests/UnitTests.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp3.1;net5.0 diff --git a/src/EntityFramework/host/Host.csproj b/src/EntityFramework/host/Host.csproj index f0436ed01..01958e375 100644 --- a/src/EntityFramework/host/Host.csproj +++ b/src/EntityFramework/host/Host.csproj @@ -1,13 +1,10 @@  - netcoreapp3.1 + netcoreapp3.1;net5.0 - - - diff --git a/src/EntityFramework/src/Duende.IdentityServer.EntityFramework.csproj b/src/EntityFramework/src/Duende.IdentityServer.EntityFramework.csproj index 0f4829490..51c359ed5 100644 --- a/src/EntityFramework/src/Duende.IdentityServer.EntityFramework.csproj +++ b/src/EntityFramework/src/Duende.IdentityServer.EntityFramework.csproj @@ -2,7 +2,7 @@ Duende.IdentityServer.EntityFramework - netcoreapp3.1 + netcoreapp3.1;net5.0 EntityFramework persistence layer for Duende IdentityServer Duende.IdentityServer.EntityFramework diff --git a/src/IdentityServer/host/Host.csproj b/src/IdentityServer/host/Host.csproj index 4ed4eda49..95e5a62db 100644 --- a/src/IdentityServer/host/Host.csproj +++ b/src/IdentityServer/host/Host.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp3.1;net5.0 InProcess @@ -20,7 +20,6 @@ - diff --git a/src/IdentityServer/host/Properties/launchSettings.json b/src/IdentityServer/host/Properties/launchSettings.json index 641abdaa2..c7cddae79 100644 --- a/src/IdentityServer/host/Properties/launchSettings.json +++ b/src/IdentityServer/host/Properties/launchSettings.json @@ -7,15 +7,6 @@ "ASPNETCORE_ENVIRONMENT": "Development" }, "applicationUrl": "https://localhost:5001;http://localhost:5000" - }, - "Host (proxy)": { - "commandName": "Project", - "launchBrowser": true, - "launchUrl": "https://identityserver.local", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - }, - "applicationUrl": "https://localhost:5001;http://localhost:5000" } } } \ No newline at end of file diff --git a/src/IdentityServer/src/Configuration/DependencyInjection/BuilderExtensions/Crypto.cs b/src/IdentityServer/src/Configuration/DependencyInjection/BuilderExtensions/Crypto.cs index b8b74baf1..e0f292d1a 100644 --- a/src/IdentityServer/src/Configuration/DependencyInjection/BuilderExtensions/Crypto.cs +++ b/src/IdentityServer/src/Configuration/DependencyInjection/BuilderExtensions/Crypto.cs @@ -7,7 +7,6 @@ using Duende.IdentityServer.Models; using Duende.IdentityServer.Stores; using Microsoft.IdentityModel.Tokens; -using Newtonsoft.Json; using System; using System.IO; using System.Linq; @@ -185,7 +184,7 @@ public static IIdentityServerBuilder AddDeveloperSigningCredential( if (persistKey) { - File.WriteAllText(filename, JsonConvert.SerializeObject(jwk)); + File.WriteAllText(filename, System.Text.Json.JsonSerializer.Serialize(jwk)); } return builder.AddSigningCredential(key, signingAlgorithm); diff --git a/src/IdentityServer/src/Configuration/IdentityServerApplicationBuilderExtensions.cs b/src/IdentityServer/src/Configuration/IdentityServerApplicationBuilderExtensions.cs index 5a8a70f44..999c8ab9e 100644 --- a/src/IdentityServer/src/Configuration/IdentityServerApplicationBuilderExtensions.cs +++ b/src/IdentityServer/src/Configuration/IdentityServerApplicationBuilderExtensions.cs @@ -11,6 +11,7 @@ using Microsoft.Extensions.Logging; using System; using System.Reflection; +using System.Runtime.InteropServices; using System.Threading.Tasks; namespace Microsoft.AspNetCore.Builder @@ -54,7 +55,7 @@ internal static void Validate(this IApplicationBuilder app) if (loggerFactory == null) throw new ArgumentNullException(nameof(loggerFactory)); var logger = loggerFactory.CreateLogger("Duende.IdentityServer.Startup"); - logger.LogInformation("Starting Duende IdentityServer version {version}", typeof(Duende.IdentityServer.Hosting.IdentityServerMiddleware).Assembly.GetCustomAttribute().InformationalVersion); + logger.LogInformation("Starting Duende IdentityServer version {version} ({netversion})", typeof(Duende.IdentityServer.Hosting.IdentityServerMiddleware).Assembly.GetCustomAttribute().InformationalVersion, RuntimeInformation.FrameworkDescription); var scopeFactory = app.ApplicationServices.GetService(); diff --git a/src/IdentityServer/src/Duende.IdentityServer.csproj b/src/IdentityServer/src/Duende.IdentityServer.csproj index cddc68c71..d56fd160c 100644 --- a/src/IdentityServer/src/Duende.IdentityServer.csproj +++ b/src/IdentityServer/src/Duende.IdentityServer.csproj @@ -2,7 +2,7 @@ Duende.IdentityServer - netcoreapp3.1 + netcoreapp3.1;net5.0 OpenID Connect and OAuth 2.0 Framework for ASP.NET Core Duende.IdentityServer @@ -16,8 +16,7 @@ - - + diff --git a/src/IdentityServer/src/Extensions/TokenExtensions.cs b/src/IdentityServer/src/Extensions/TokenExtensions.cs index 2917cb17a..ec4a1b474 100644 --- a/src/IdentityServer/src/Extensions/TokenExtensions.cs +++ b/src/IdentityServer/src/Extensions/TokenExtensions.cs @@ -6,13 +6,14 @@ using Duende.IdentityServer.Models; using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Logging; -using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; +using System.Text.Json; using Duende.IdentityServer.Configuration; +using Microsoft.AspNetCore.Routing; namespace Duende.IdentityServer.Extensions { @@ -22,132 +23,135 @@ namespace Duende.IdentityServer.Extensions public static class TokenExtensions { /// - /// Creates the default JWT payload. + /// Creates the default JWT payload dictionary /// - /// The token. - /// The clock. - /// The options - /// The logger. + /// + /// + /// + /// /// - /// - /// - public static JwtPayload CreateJwtPayload(this Token token, ISystemClock clock, IdentityServerOptions options, ILogger logger) + public static Dictionary CreateJwtPayloadDictionary(this Token token, + IdentityServerOptions options, ISystemClock clock, ILogger logger) { - var payload = new JwtPayload( - token.Issuer, - null, - null, - clock.UtcNow.UtcDateTime, - clock.UtcNow.UtcDateTime.AddSeconds(token.Lifetime)); - - foreach (var aud in token.Audiences) + try { - payload.AddClaim(new Claim(JwtClaimTypes.Audience, aud)); - } + var payload = new Dictionary(); - var amrClaims = token.Claims.Where(x => x.Type == JwtClaimTypes.AuthenticationMethod).ToArray(); - var scopeClaims = token.Claims.Where(x => x.Type == JwtClaimTypes.Scope).ToArray(); - var jsonClaims = token.Claims.Where(x => x.ValueType == IdentityServerConstants.ClaimValueTypes.Json).ToList(); - - // add confirmation claim if present (it's JSON valued) - if (token.Confirmation.IsPresent()) - { - jsonClaims.Add(new Claim(JwtClaimTypes.Confirmation, token.Confirmation, IdentityServerConstants.ClaimValueTypes.Json)); - } + // set issuer + payload.Add(JwtClaimTypes.Issuer, token.Issuer); - var normalClaims = token.Claims - .Except(amrClaims) - .Except(jsonClaims) - .Except(scopeClaims); - - payload.AddClaims(normalClaims); - - // scope claims - if (!scopeClaims.IsNullOrEmpty()) - { - var scopeValues = scopeClaims.Select(x => x.Value).ToArray(); + // set times (nbf, exp, iat) + var now = clock.UtcNow.ToUnixTimeSeconds(); + var exp = now + token.Lifetime; + + payload.Add(JwtClaimTypes.NotBefore, now); + payload.Add(JwtClaimTypes.IssuedAt, now); + payload.Add(JwtClaimTypes.Expiration, exp); - if (options.EmitScopesAsSpaceDelimitedStringInJwt) + // add audience claim(s) + if (token.Audiences.Any()) { - payload.Add(JwtClaimTypes.Scope, string.Join(" ", scopeValues)); + if (token.Audiences.Count == 1) + { + payload.Add(JwtClaimTypes.Audience, token.Audiences.First()); + } + else + { + payload.Add(JwtClaimTypes.Audience, token.Audiences); + } } - else + + // add confirmation claim (if present) + if (token.Confirmation.IsPresent()) { - payload.Add(JwtClaimTypes.Scope, scopeValues); + payload.Add(JwtClaimTypes.Confirmation, + JsonSerializer.Deserialize(token.Confirmation)); } - } - - // amr claims - if (!amrClaims.IsNullOrEmpty()) - { - var amrValues = amrClaims.Select(x => x.Value).Distinct().ToArray(); - payload.Add(JwtClaimTypes.AuthenticationMethod, amrValues); - } - - // deal with json types - // calling ToArray() to trigger JSON parsing once and so later - // collection identity comparisons work for the anonymous type - try - { - var jsonTokens = jsonClaims.Select(x => new { x.Type, JsonValue = JRaw.Parse(x.Value) }).ToArray(); - var jsonObjects = jsonTokens.Where(x => x.JsonValue.Type == JTokenType.Object).ToArray(); - var jsonObjectGroups = jsonObjects.GroupBy(x => x.Type).ToArray(); - foreach (var group in jsonObjectGroups) + // scope claims + var scopeClaims = token.Claims.Where(x => x.Type == JwtClaimTypes.Scope).ToArray(); + if (!scopeClaims.IsNullOrEmpty()) { - if (payload.ContainsKey(group.Key)) - { - throw new Exception($"Can't add two claims where one is a JSON object and the other is not a JSON object ({group.Key})"); - } + var scopeValues = scopeClaims.Select(x => x.Value).ToArray(); - if (group.Skip(1).Any()) + if (options.EmitScopesAsSpaceDelimitedStringInJwt) { - // add as array - payload.Add(group.Key, group.Select(x => x.JsonValue).ToArray()); + payload.Add(JwtClaimTypes.Scope, string.Join(" ", scopeValues)); } else { - // add just one - payload.Add(group.Key, group.First().JsonValue); + payload.Add(JwtClaimTypes.Scope, scopeValues); } } - var jsonArrays = jsonTokens.Where(x => x.JsonValue.Type == JTokenType.Array).ToArray(); - var jsonArrayGroups = jsonArrays.GroupBy(x => x.Type).ToArray(); - foreach (var group in jsonArrayGroups) + // amr claims + var amrClaims = token.Claims.Where(x => x.Type == JwtClaimTypes.AuthenticationMethod).ToArray(); + if (!amrClaims.IsNullOrEmpty()) + { + var amrValues = amrClaims.Select(x => x.Value).Distinct().ToArray(); + payload.Add(JwtClaimTypes.AuthenticationMethod, amrValues); + } + + var simpleClaimTypes = token.Claims.Where(c => + c.Type != JwtClaimTypes.AuthenticationMethod && c.Type != JwtClaimTypes.Scope) + .Select(c => c.Type) + .Distinct(); + + // other claims + foreach (var claimType in simpleClaimTypes) { - if (payload.ContainsKey(group.Key)) + var claims = token.Claims.Where(c => c.Type == claimType).ToArray(); + + if (claims.Count() > 1) { - throw new Exception( - $"Can't add two claims where one is a JSON array and the other is not a JSON array ({group.Key})"); + payload.Add(claimType, AddObjects(claims)); } - - var newArr = new List(); - foreach (var arrays in group) + else { - var arr = (JArray)arrays.JsonValue; - newArr.AddRange(arr); + payload.Add(claimType, AddObject(claims.First())); } - - // add just one array for the group/key/claim type - payload.Add(group.Key, newArr.ToArray()); - } - - var unsupportedJsonTokens = jsonTokens.Except(jsonObjects).Except(jsonArrays).ToArray(); - var unsupportedJsonClaimTypes = unsupportedJsonTokens.Select(x => x.Type).Distinct().ToArray(); - if (unsupportedJsonClaimTypes.Any()) - { - throw new Exception( - $"Unsupported JSON type for claim types: {unsupportedJsonClaimTypes.Aggregate((x, y) => x + ", " + y)}"); } return payload; } catch (Exception ex) { - logger.LogCritical(ex, "Error creating a JSON valued claim"); + logger.LogCritical(ex, "Error creating the JWT payload"); throw; } } + + private static IEnumerable AddObjects(IEnumerable claims) + { + foreach (var claim in claims) + { + yield return AddObject(claim); + } + } + + private static object AddObject(Claim claim) + { + if (claim.Type == ClaimValueTypes.Boolean) + { + return Boolean.Parse(claim.Value); + } + + if (claim.Type == ClaimValueTypes.Integer || claim.Type == ClaimValueTypes.Integer32) + { + return Int32.Parse(claim.Value); + } + + if (claim.Type == ClaimValueTypes.Integer64) + { + return Int64.Parse(claim.Value); + } + + if (claim.Type == IdentityServerConstants.ClaimValueTypes.Json) + { + return JsonSerializer.Deserialize(claim.Value); + } + + return claim.Value; + } } } \ No newline at end of file diff --git a/src/IdentityServer/src/Services/Default/DefaultBackChannelLogoutService.cs b/src/IdentityServer/src/Services/Default/DefaultBackChannelLogoutService.cs index ca18add50..f009fa633 100644 --- a/src/IdentityServer/src/Services/Default/DefaultBackChannelLogoutService.cs +++ b/src/IdentityServer/src/Services/Default/DefaultBackChannelLogoutService.cs @@ -164,7 +164,6 @@ protected Task> CreateClaimsForTokenAsync(BackChannelLogoutRe { new Claim(JwtClaimTypes.Subject, request.SubjectId), new Claim(JwtClaimTypes.Audience, request.ClientId), - new Claim(JwtClaimTypes.IssuedAt, Clock.UtcNow.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64), new Claim(JwtClaimTypes.JwtId, CryptoRandom.CreateUniqueId(16, CryptoRandom.OutputFormat.Hex)), new Claim(JwtClaimTypes.Events, json, IdentityServerConstants.ClaimValueTypes.Json) }; diff --git a/src/IdentityServer/src/Services/Default/DefaultTokenCreationService.cs b/src/IdentityServer/src/Services/Default/DefaultTokenCreationService.cs index 7dd276f20..ac25bd625 100644 --- a/src/IdentityServer/src/Services/Default/DefaultTokenCreationService.cs +++ b/src/IdentityServer/src/Services/Default/DefaultTokenCreationService.cs @@ -9,11 +9,15 @@ using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Tokens; using System; +using System.Collections.Generic; using System.Globalization; using System.IdentityModel.Tokens.Jwt; +using System.Text.Json; using System.Threading.Tasks; using Duende.IdentityServer.Configuration; +using Microsoft.IdentityModel.JsonWebTokens; + namespace Duende.IdentityServer.Services { /// @@ -69,71 +73,63 @@ public DefaultTokenCreationService( /// public virtual async Task CreateTokenAsync(Token token) { - var header = await CreateHeaderAsync(token); var payload = await CreatePayloadAsync(token); + var headerElements = await CreateHeaderElementsAsync(token); - return await CreateJwtAsync(new JwtSecurityToken(header, payload)); + return await CreateJwtAsync(token, payload, headerElements); } /// - /// Creates the JWT header + /// Creates the JWT payload /// - /// The token. - /// The JWT header - protected virtual async Task CreateHeaderAsync(Token token) + /// + /// + protected virtual Task CreatePayloadAsync(Token token) { - var credential = await Keys.GetSigningCredentialsAsync(token.AllowedSigningAlgorithms); - - if (credential == null) - { - throw new InvalidOperationException("No signing credential is configured. Can't create JWT token"); - } - - var header = new JwtHeader(credential); - - // emit x5t claim for backwards compatibility with v4 of MS JWT library - if (credential.Key is X509SecurityKey x509Key) - { - var cert = x509Key.Certificate; - if (Clock.UtcNow.UtcDateTime > cert.NotAfter) - { - Logger.LogWarning("Certificate {subjectName} has expired on {expiration}", cert.Subject, cert.NotAfter.ToString(CultureInfo.InvariantCulture)); - } - - header["x5t"] = Base64Url.Encode(cert.GetCertHash()); - } + var payload = token.CreateJwtPayloadDictionary(Options, Clock, Logger); + return Task.FromResult(JsonSerializer.Serialize(payload)); + } + /// + /// Creates additional JWT header elements + /// + /// + /// + protected virtual Task> CreateHeaderElementsAsync(Token token) + { + var additionalHeaderElements = new Dictionary(); + if (token.Type == IdentityServerConstants.TokenTypes.AccessToken) { if (Options.AccessTokenJwtType.IsPresent()) { - header["typ"] = Options.AccessTokenJwtType; + additionalHeaderElements.Add("typ", Options.AccessTokenJwtType); } } - return header; + return Task.FromResult(additionalHeaderElements); } /// - /// Creates the JWT payload + /// Creates JWT token /// - /// The token. - /// The JWT payload - protected virtual Task CreatePayloadAsync(Token token) + /// + /// + /// + /// + /// + protected virtual async Task CreateJwtAsync(Token token, string payload, + Dictionary headerElements) { - var payload = token.CreateJwtPayload(Clock, Options, Logger); - return Task.FromResult(payload); - } + var credential = await Keys.GetSigningCredentialsAsync(token.AllowedSigningAlgorithms); - /// - /// Applies the signature to the JWT - /// - /// The JWT object. - /// The signed JWT - protected virtual Task CreateJwtAsync(JwtSecurityToken jwt) - { - var handler = new JwtSecurityTokenHandler(); - return Task.FromResult(handler.WriteToken(jwt)); + if (credential == null) + { + throw new InvalidOperationException("No signing credential is configured. Can't create JWT token"); + } + + var handler = new JsonWebTokenHandler { SetDefaultTimesOnTokenCreation = false }; + return handler.CreateToken(payload, credential, headerElements); } } } \ No newline at end of file diff --git a/src/IdentityServer/src/Services/Default/DefaultTokenService.cs b/src/IdentityServer/src/Services/Default/DefaultTokenService.cs index 70d95edef..52bec9cdc 100644 --- a/src/IdentityServer/src/Services/Default/DefaultTokenService.cs +++ b/src/IdentityServer/src/Services/Default/DefaultTokenService.cs @@ -124,8 +124,9 @@ public virtual async Task CreateIdentityTokenAsync(TokenCreationRequest r claims.Add(new Claim(JwtClaimTypes.Nonce, request.Nonce)); } + // todo: cleanup // add iat claim - claims.Add(new Claim(JwtClaimTypes.IssuedAt, Clock.UtcNow.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64)); + //claims.Add(new Claim(JwtClaimTypes.IssuedAt, Clock.UtcNow.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64)); // add at_hash claim if (request.AccessTokenToHash.IsPresent()) @@ -202,10 +203,6 @@ public virtual async Task CreateAccessTokenAsync(TokenCreationRequest req claims.Add(new Claim(JwtClaimTypes.SessionId, request.ValidatedRequest.SessionId)); } - // iat claim as required by JWT profile - claims.Add(new Claim(JwtClaimTypes.IssuedAt, Clock.UtcNow.ToUnixTimeSeconds().ToString(), - ClaimValueTypes.Integer64)); - var issuer = ContextAccessor.HttpContext.GetIdentityServerIssuerUri(); var token = new Token(OidcConstants.TokenTypes.AccessToken) { diff --git a/src/IdentityServer/src/Validation/Default/JwtRequestValidator.cs b/src/IdentityServer/src/Validation/Default/JwtRequestValidator.cs index 1fafdc6cf..5490b25c2 100644 --- a/src/IdentityServer/src/Validation/Default/JwtRequestValidator.cs +++ b/src/IdentityServer/src/Validation/Default/JwtRequestValidator.cs @@ -14,8 +14,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Tokens; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; namespace Duende.IdentityServer.Validation { @@ -199,19 +197,7 @@ protected virtual Task> ProcessPayloadAsync(JwtSecuri if (!Constants.Filters.JwtRequestClaimTypesFilter.Contains(key)) { var value = token.Payload[key]; - - switch (value) - { - case string s: - payload.Add(key, s); - break; - case JObject jobj: - payload.Add(key, jobj.ToString(Formatting.None)); - break; - case JArray jarr: - payload.Add(key, jarr.ToString(Formatting.None)); - break; - } + payload.Add(key, value.ToString()); } } diff --git a/src/IdentityServer/test/IntegrationTests/IntegrationTests.csproj b/src/IdentityServer/test/IntegrationTests/IntegrationTests.csproj index ec75caf41..9dc5ecf70 100644 --- a/src/IdentityServer/test/IntegrationTests/IntegrationTests.csproj +++ b/src/IdentityServer/test/IntegrationTests/IntegrationTests.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp3.1;net5.0 diff --git a/src/IdentityServer/test/UnitTests/Extensions/JwtPayloadCreationTests.cs b/src/IdentityServer/test/UnitTests/Extensions/JwtPayloadCreationTests.cs deleted file mode 100644 index 7606f7020..000000000 --- a/src/IdentityServer/test/UnitTests/Extensions/JwtPayloadCreationTests.cs +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) Duende Software. All rights reserved. -// See LICENSE in the project root for license information. - - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; -using Duende.IdentityServer.Configuration; -using Duende.IdentityServer.Extensions; -using Duende.IdentityServer.Models; -using FluentAssertions; -using IdentityModel; -using UnitTests.Common; -using Microsoft.AspNetCore.Authentication; -using Xunit; - -namespace UnitTests.Extensions -{ - public class JwtPayloadCreationTests - { - private Token _token; - - public JwtPayloadCreationTests() - { - var claims = new List - { - new Claim(JwtClaimTypes.Scope, "scope1"), - new Claim(JwtClaimTypes.Scope, "scope2"), - new Claim(JwtClaimTypes.Scope, "scope3"), - }; - - _token = new Token(OidcConstants.TokenTypes.AccessToken) - { - CreationTime = DateTime.UtcNow, - Issuer = "issuer", - Lifetime = 60, - Claims = claims.Distinct(new ClaimComparer()).ToList(), - ClientId = "client" - }; - } - - [Fact] - public void Should_create_scopes_as_array_by_default() - { - var options = new IdentityServerOptions(); - var payload = _token.CreateJwtPayload(new SystemClock(), options, TestLogger.Create()); - - payload.Should().NotBeNull(); - var scopes = payload.Claims.Where(c => c.Type == JwtClaimTypes.Scope).ToArray(); - scopes.Count().Should().Be(3); - scopes[0].Value.Should().Be("scope1"); - scopes[1].Value.Should().Be("scope2"); - scopes[2].Value.Should().Be("scope3"); - } - - [Fact] - public void Should_create_scopes_as_string() - { - var options = new IdentityServerOptions - { - EmitScopesAsSpaceDelimitedStringInJwt = true - }; - - var payload = _token.CreateJwtPayload(new SystemClock(), options, TestLogger.Create()); - - payload.Should().NotBeNull(); - var scopes = payload.Claims.Where(c => c.Type == JwtClaimTypes.Scope).ToList(); - scopes.Count().Should().Be(1); - scopes.First().Value.Should().Be("scope1 scope2 scope3"); - } - } -} diff --git a/src/IdentityServer/test/UnitTests/ResponseHandling/DeviceAuthorizationResponseGeneratorTests.cs b/src/IdentityServer/test/UnitTests/ResponseHandling/DeviceAuthorizationResponseGeneratorTests.cs index b2ec6bdf5..c57b48461 100644 --- a/src/IdentityServer/test/UnitTests/ResponseHandling/DeviceAuthorizationResponseGeneratorTests.cs +++ b/src/IdentityServer/test/UnitTests/ResponseHandling/DeviceAuthorizationResponseGeneratorTests.cs @@ -18,7 +18,7 @@ using Microsoft.Extensions.Logging.Abstractions; using Xunit; -namespace IdentityServer.UnitTests.ResponseHandling +namespace UnitTests.ResponseHandling { public class DeviceAuthorizationResponseGeneratorTests { diff --git a/src/IdentityServer/test/UnitTests/ResponseHandling/UserInfoResponseGeneratorTests.cs b/src/IdentityServer/test/UnitTests/ResponseHandling/UserInfoResponseGeneratorTests.cs index 37b79c68d..199c1a130 100644 --- a/src/IdentityServer/test/UnitTests/ResponseHandling/UserInfoResponseGeneratorTests.cs +++ b/src/IdentityServer/test/UnitTests/ResponseHandling/UserInfoResponseGeneratorTests.cs @@ -16,7 +16,7 @@ using UnitTests.Common; using Xunit; -namespace IdentityServer.UnitTests.ResponseHandling +namespace UnitTests.ResponseHandling { public class UserInfoResponseGeneratorTests { diff --git a/src/IdentityServer/test/UnitTests/Stores/InMemoryClientStoreTests.cs b/src/IdentityServer/test/UnitTests/Stores/InMemoryClientStoreTests.cs index a7a7b73e1..1dd444871 100644 --- a/src/IdentityServer/test/UnitTests/Stores/InMemoryClientStoreTests.cs +++ b/src/IdentityServer/test/UnitTests/Stores/InMemoryClientStoreTests.cs @@ -9,7 +9,7 @@ using Xunit; using FluentAssertions; -namespace IdentityServer.UnitTests.Stores +namespace UnitTests.Stores { public class InMemoryClientStoreTests { diff --git a/src/IdentityServer/test/UnitTests/Stores/InMemoryDeviceFlowStoreTests.cs b/src/IdentityServer/test/UnitTests/Stores/InMemoryDeviceFlowStoreTests.cs index f385312a2..e96991372 100644 --- a/src/IdentityServer/test/UnitTests/Stores/InMemoryDeviceFlowStoreTests.cs +++ b/src/IdentityServer/test/UnitTests/Stores/InMemoryDeviceFlowStoreTests.cs @@ -11,7 +11,7 @@ using FluentAssertions; using Xunit; -namespace IdentityServer.UnitTests.Stores +namespace UnitTests.Stores { public class InMemoryDeviceFlowStoreTests { diff --git a/src/IdentityServer/test/UnitTests/Stores/InMemoryPersistedGrantStoreTests.cs b/src/IdentityServer/test/UnitTests/Stores/InMemoryPersistedGrantStoreTests.cs index 2f8f8135c..50cb94142 100644 --- a/src/IdentityServer/test/UnitTests/Stores/InMemoryPersistedGrantStoreTests.cs +++ b/src/IdentityServer/test/UnitTests/Stores/InMemoryPersistedGrantStoreTests.cs @@ -9,7 +9,7 @@ using Duende.IdentityServer.Stores; using FluentAssertions; -namespace IdentityServer.UnitTests.Stores +namespace UnitTests.Stores { public class InMemoryPersistedGrantStoreTests { diff --git a/src/IdentityServer/test/UnitTests/Stores/InMemoryResourcesStoreTests.cs b/src/IdentityServer/test/UnitTests/Stores/InMemoryResourcesStoreTests.cs index ab194be47..fd87b7add 100644 --- a/src/IdentityServer/test/UnitTests/Stores/InMemoryResourcesStoreTests.cs +++ b/src/IdentityServer/test/UnitTests/Stores/InMemoryResourcesStoreTests.cs @@ -9,7 +9,7 @@ using Xunit; using FluentAssertions; -namespace IdentityServer.UnitTests.Stores +namespace UnitTests.Stores { public class InMemoryResourcesStoreTests { diff --git a/src/IdentityServer/test/UnitTests/UnitTests.csproj b/src/IdentityServer/test/UnitTests/UnitTests.csproj index 6aaba9a89..e080049fa 100644 --- a/src/IdentityServer/test/UnitTests/UnitTests.csproj +++ b/src/IdentityServer/test/UnitTests/UnitTests.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1 + netcoreapp3.1;net5.0 diff --git a/src/IdentityServer/test/UnitTests/Validation/AccessTokenValidation.cs b/src/IdentityServer/test/UnitTests/Validation/AccessTokenValidation.cs index b0ecb2fcc..bba897f0c 100644 --- a/src/IdentityServer/test/UnitTests/Validation/AccessTokenValidation.cs +++ b/src/IdentityServer/test/UnitTests/Validation/AccessTokenValidation.cs @@ -188,7 +188,7 @@ public async Task JWT_Token_with_scopes_have_expected_claims(bool flag) result.Jwt.Should().NotBeNullOrEmpty(); result.Client.ClientId.Should().Be("roclient"); - result.Claims.Count().Should().Be(8); + result.Claims.Count().Should().Be(9); var scopes = result.Claims.Where(c => c.Type == "scope").Select(c => c.Value).ToArray(); scopes.Count().Should().Be(2); scopes[0].Should().Be("read"); diff --git a/src/Storage/src/Duende.IdentityServer.Storage.csproj b/src/Storage/src/Duende.IdentityServer.Storage.csproj index 826ddf516..9237fe775 100644 --- a/src/Storage/src/Duende.IdentityServer.Storage.csproj +++ b/src/Storage/src/Duende.IdentityServer.Storage.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.0;net5.0 Duende.IdentityServer.Storage Storage interfaces and models for Duende IdentityServer