From 14a60891d2c2df4f7b5a12c9c249aa406dc577ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Louren=C3=A7o?= Date: Sun, 28 Aug 2022 15:42:01 -0300 Subject: [PATCH 1/8] Updated target framework for identityserver4 project. --- global.json | 2 +- src/IdentityServer4/host/Host.csproj | 14 +++++++------- src/IdentityServer4/src/IdentityServer4.csproj | 4 ++-- .../src/Infrastructure/ObjectSerializer.cs | 5 +++-- src/IdentityServer4/src/Logging/LogSerializer.cs | 4 ++-- .../Default/DefaultJwtRequestUriHttpClient.cs | 4 ++-- .../Services/Default/NumericUserCodeGenerator.cs | 2 +- .../IdentityServer.IntegrationTests.csproj | 4 ++-- .../IdentityServer.UnitTests.csproj | 4 ++-- 9 files changed, 22 insertions(+), 21 deletions(-) diff --git a/global.json b/global.json index 70db897290..d769cd3498 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "3.1.402" + "version": "6.0.400" } } \ No newline at end of file diff --git a/src/IdentityServer4/host/Host.csproj b/src/IdentityServer4/host/Host.csproj index 8d1da5b173..dff7853bd0 100644 --- a/src/IdentityServer4/host/Host.csproj +++ b/src/IdentityServer4/host/Host.csproj @@ -1,7 +1,7 @@ - + - netcoreapp3.1 + net6.0 InProcess @@ -14,14 +14,14 @@ - + - + - + - - + + diff --git a/src/IdentityServer4/src/IdentityServer4.csproj b/src/IdentityServer4/src/IdentityServer4.csproj index ffc8ce2dc4..c00437f8ba 100644 --- a/src/IdentityServer4/src/IdentityServer4.csproj +++ b/src/IdentityServer4/src/IdentityServer4.csproj @@ -1,8 +1,8 @@ - + IdentityServer4 - netcoreapp3.1 + net6.0 OpenID Connect and OAuth 2.0 Framework for ASP.NET Core Brock Allen;Dominick Baier IdentityServer4 diff --git a/src/IdentityServer4/src/Infrastructure/ObjectSerializer.cs b/src/IdentityServer4/src/Infrastructure/ObjectSerializer.cs index f88480aae2..6e55feeb18 100644 --- a/src/IdentityServer4/src/Infrastructure/ObjectSerializer.cs +++ b/src/IdentityServer4/src/Infrastructure/ObjectSerializer.cs @@ -1,8 +1,9 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. +// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. using System.Text.Json; +using System.Text.Json.Serialization; namespace IdentityServer4 { @@ -10,7 +11,7 @@ internal static class ObjectSerializer { private static readonly JsonSerializerOptions Options = new JsonSerializerOptions { - IgnoreNullValues = true + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }; public static string ToString(object o) diff --git a/src/IdentityServer4/src/Logging/LogSerializer.cs b/src/IdentityServer4/src/Logging/LogSerializer.cs index 4a58733170..32112262c5 100644 --- a/src/IdentityServer4/src/Logging/LogSerializer.cs +++ b/src/IdentityServer4/src/Logging/LogSerializer.cs @@ -1,4 +1,4 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. +// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. @@ -14,7 +14,7 @@ internal static class LogSerializer { static readonly JsonSerializerOptions Options = new JsonSerializerOptions { - IgnoreNullValues = true, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, WriteIndented = true }; diff --git a/src/IdentityServer4/src/Services/Default/DefaultJwtRequestUriHttpClient.cs b/src/IdentityServer4/src/Services/Default/DefaultJwtRequestUriHttpClient.cs index e816f1b358..8ae55f671e 100644 --- a/src/IdentityServer4/src/Services/Default/DefaultJwtRequestUriHttpClient.cs +++ b/src/IdentityServer4/src/Services/Default/DefaultJwtRequestUriHttpClient.cs @@ -1,4 +1,4 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. +// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. @@ -39,7 +39,7 @@ public DefaultJwtRequestUriHttpClient(HttpClient client, IdentityServerOptions o public async Task GetJwtAsync(string url, Client client) { var req = new HttpRequestMessage(HttpMethod.Get, url); - req.Properties.Add(IdentityServerConstants.JwtRequestClientKey, client); + req.Options.Set(new HttpRequestOptionsKey(IdentityServerConstants.JwtRequestClientKey), client); var response = await _client.SendAsync(req); if (response.StatusCode == System.Net.HttpStatusCode.OK) diff --git a/src/IdentityServer4/src/Services/Default/NumericUserCodeGenerator.cs b/src/IdentityServer4/src/Services/Default/NumericUserCodeGenerator.cs index e52f62d66f..c9e29e9c2e 100644 --- a/src/IdentityServer4/src/Services/Default/NumericUserCodeGenerator.cs +++ b/src/IdentityServer4/src/Services/Default/NumericUserCodeGenerator.cs @@ -48,7 +48,7 @@ private int Next(int minValue, int maxValue) var uint32Buffer = new byte[8]; - using (var rng = new RNGCryptoServiceProvider()) + using (var rng = RandomNumberGenerator.Create()) { while (true) { diff --git a/src/IdentityServer4/test/IdentityServer.IntegrationTests/IdentityServer.IntegrationTests.csproj b/src/IdentityServer4/test/IdentityServer.IntegrationTests/IdentityServer.IntegrationTests.csproj index 1848cf2e06..668a177122 100644 --- a/src/IdentityServer4/test/IdentityServer.IntegrationTests/IdentityServer.IntegrationTests.csproj +++ b/src/IdentityServer4/test/IdentityServer.IntegrationTests/IdentityServer.IntegrationTests.csproj @@ -1,7 +1,7 @@ - + - netcoreapp3.1 + net6.0 diff --git a/src/IdentityServer4/test/IdentityServer.UnitTests/IdentityServer.UnitTests.csproj b/src/IdentityServer4/test/IdentityServer.UnitTests/IdentityServer.UnitTests.csproj index 073b634ac5..1114a09b8e 100644 --- a/src/IdentityServer4/test/IdentityServer.UnitTests/IdentityServer.UnitTests.csproj +++ b/src/IdentityServer4/test/IdentityServer.UnitTests/IdentityServer.UnitTests.csproj @@ -1,7 +1,7 @@ - + - netcoreapp3.1 + net6.0 From 9b0242dd495f8ab5993357766809422354a48602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Louren=C3=A7o?= Date: Sun, 28 Aug 2022 18:07:13 -0300 Subject: [PATCH 2/8] Updated framework version and updated EntityFramework.Storage targets. --- src/Directory.Build.targets | 6 +++--- src/EntityFramework.Storage/build/build.csproj | 2 +- .../host/ConsoleHost/ConsoleHost.csproj | 4 ++-- .../migrations/SqlServer/SqlServer.csproj | 4 ++-- .../src/IdentityServer4.EntityFramework.Storage.csproj | 7 ++++--- ...IdentityServer4.EntityFramework.IntegrationTests.csproj | 4 ++-- .../IdentityServer4.EntityFramework.UnitTests.csproj | 4 ++-- 7 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index 292310cb43..2a51d8d85e 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -1,9 +1,9 @@ - 3.1.0 - 3.1.0 - 3.1.0 + 6.0.8 + 6.0.8 + 6.0.8 4.1.2-* diff --git a/src/EntityFramework.Storage/build/build.csproj b/src/EntityFramework.Storage/build/build.csproj index 43c81aaed1..b9a5a48d99 100644 --- a/src/EntityFramework.Storage/build/build.csproj +++ b/src/EntityFramework.Storage/build/build.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net6.0 diff --git a/src/EntityFramework.Storage/host/ConsoleHost/ConsoleHost.csproj b/src/EntityFramework.Storage/host/ConsoleHost/ConsoleHost.csproj index 9906d53301..ed4586a9f4 100644 --- a/src/EntityFramework.Storage/host/ConsoleHost/ConsoleHost.csproj +++ b/src/EntityFramework.Storage/host/ConsoleHost/ConsoleHost.csproj @@ -1,8 +1,8 @@ - + Exe - netcoreapp3.1 + net6.0 diff --git a/src/EntityFramework.Storage/migrations/SqlServer/SqlServer.csproj b/src/EntityFramework.Storage/migrations/SqlServer/SqlServer.csproj index 5307d2fb92..7666e21584 100644 --- a/src/EntityFramework.Storage/migrations/SqlServer/SqlServer.csproj +++ b/src/EntityFramework.Storage/migrations/SqlServer/SqlServer.csproj @@ -1,7 +1,7 @@ - + - netcoreapp3.1 + net6.0 diff --git a/src/EntityFramework.Storage/src/IdentityServer4.EntityFramework.Storage.csproj b/src/EntityFramework.Storage/src/IdentityServer4.EntityFramework.Storage.csproj index cd8a6c576d..f2860677a3 100644 --- a/src/EntityFramework.Storage/src/IdentityServer4.EntityFramework.Storage.csproj +++ b/src/EntityFramework.Storage/src/IdentityServer4.EntityFramework.Storage.csproj @@ -1,8 +1,8 @@ - + IdentityServer4.EntityFramework.Storage - netstandard2.0 + net6.0 EntityFramework persistence layer for IdentityServer4 Brock Allen;Dominick Baier;Scott Brady @@ -35,8 +35,9 @@ - + + diff --git a/src/EntityFramework.Storage/test/IntegrationTests/IdentityServer4.EntityFramework.IntegrationTests.csproj b/src/EntityFramework.Storage/test/IntegrationTests/IdentityServer4.EntityFramework.IntegrationTests.csproj index 754006b8ea..1da436acb8 100644 --- a/src/EntityFramework.Storage/test/IntegrationTests/IdentityServer4.EntityFramework.IntegrationTests.csproj +++ b/src/EntityFramework.Storage/test/IntegrationTests/IdentityServer4.EntityFramework.IntegrationTests.csproj @@ -1,7 +1,7 @@ - + - netcoreapp3.1 + net6.0 ../../../../key.snk true diff --git a/src/EntityFramework.Storage/test/UnitTests/IdentityServer4.EntityFramework.UnitTests.csproj b/src/EntityFramework.Storage/test/UnitTests/IdentityServer4.EntityFramework.UnitTests.csproj index c350083d45..8ac98c770d 100644 --- a/src/EntityFramework.Storage/test/UnitTests/IdentityServer4.EntityFramework.UnitTests.csproj +++ b/src/EntityFramework.Storage/test/UnitTests/IdentityServer4.EntityFramework.UnitTests.csproj @@ -1,7 +1,7 @@ - + - netcoreapp3.1 + net6.0 ../../../../key.snk true From 7a96898532f542ff49ef6efe9eda42721dde4549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Louren=C3=A7o?= Date: Sun, 4 Sep 2022 12:23:44 -0300 Subject: [PATCH 3/8] Fixed package versions. Refactored JWT header and payload handling to avoid serialization errors. Removed request object/query string parameter validation and corresponding test. --- src/Directory.Build.targets | 6 +- src/IdentityServer4/host/Host.csproj | 8 +- .../Models/Messages/AuthorizationRequest.cs | 5 +- .../Default/DiscoveryResponseGenerator.cs | 9 +- .../Default/DefaultKeyMaterialService.cs | 4 +- .../Default/DefaultTokenCreationService.cs | 60 ++++++------ .../Default/AuthorizeRequestValidator.cs | 55 +++++------ .../Validation/Default/JwtRequestValidator.cs | 28 +----- .../Models/JwtRequestValidationResult.cs | 3 +- .../Models/ValidatedAuthorizeRequest.cs | 5 +- .../Authorize/JwtRequestAuthorizeTests.cs | 93 ++++++------------- 11 files changed, 111 insertions(+), 165 deletions(-) diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index 2a51d8d85e..d6d1043e05 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -40,9 +40,9 @@ - - - + + + diff --git a/src/IdentityServer4/host/Host.csproj b/src/IdentityServer4/host/Host.csproj index dff7853bd0..3391945ef2 100644 --- a/src/IdentityServer4/host/Host.csproj +++ b/src/IdentityServer4/host/Host.csproj @@ -14,14 +14,14 @@ - + - + - - + + diff --git a/src/IdentityServer4/src/Models/Messages/AuthorizationRequest.cs b/src/IdentityServer4/src/Models/Messages/AuthorizationRequest.cs index f7b6561285..11d4dae7ed 100644 --- a/src/IdentityServer4/src/Models/Messages/AuthorizationRequest.cs +++ b/src/IdentityServer4/src/Models/Messages/AuthorizationRequest.cs @@ -1,4 +1,4 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. +// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; +using System.Security.Claims; namespace IdentityServer4.Models { @@ -106,7 +107,7 @@ public class AuthorizationRequest /// /// The request object values /// - public Dictionary RequestObjectValues { get; } = new Dictionary(); + public List RequestObjectValues { get; } = new List(); /// diff --git a/src/IdentityServer4/src/ResponseHandling/Default/DiscoveryResponseGenerator.cs b/src/IdentityServer4/src/ResponseHandling/Default/DiscoveryResponseGenerator.cs index 48755d0738..1bf428c64e 100644 --- a/src/IdentityServer4/src/ResponseHandling/Default/DiscoveryResponseGenerator.cs +++ b/src/IdentityServer4/src/ResponseHandling/Default/DiscoveryResponseGenerator.cs @@ -9,7 +9,6 @@ using IdentityServer4.Stores; using IdentityServer4.Validation; using Microsoft.Extensions.Logging; -using Microsoft.IdentityModel.Tokens; using System; using System.Collections.Generic; using System.Linq; @@ -370,7 +369,7 @@ where scope.ShowInDiscoveryDocument foreach (var key in await Keys.GetValidationKeysAsync()) { - if (key.Key is X509SecurityKey x509Key) + if (key.Key is Microsoft.IdentityModel.Tokens.X509SecurityKey x509Key) { var cert64 = Convert.ToBase64String(x509Key.Certificate.RawData); var thumbprint = Base64Url.Encode(x509Key.Certificate.GetCertHash()); @@ -419,7 +418,7 @@ where scope.ShowInDiscoveryDocument throw new InvalidOperationException($"key type: {x509Key.PublicKey.GetType().Name} not supported."); } } - else if (key.Key is RsaSecurityKey rsaKey) + else if (key.Key is Microsoft.IdentityModel.Tokens.RsaSecurityKey rsaKey) { var parameters = rsaKey.Rsa?.ExportParameters(false) ?? rsaKey.Parameters; var exponent = Base64Url.Encode(parameters.Exponent); @@ -437,7 +436,7 @@ where scope.ShowInDiscoveryDocument webKeys.Add(webKey); } - else if (key.Key is ECDsaSecurityKey ecdsaKey) + else if (key.Key is Microsoft.IdentityModel.Tokens.ECDsaSecurityKey ecdsaKey) { var parameters = ecdsaKey.ECDsa.ExportParameters(false); var x = Base64Url.Encode(parameters.Q.X); @@ -455,7 +454,7 @@ where scope.ShowInDiscoveryDocument }; webKeys.Add(ecdsaJsonWebKey); } - else if (key.Key is JsonWebKey jsonWebKey) + else if (key.Key is Microsoft.IdentityModel.Tokens.JsonWebKey jsonWebKey) { var webKey = new Models.JsonWebKey { diff --git a/src/IdentityServer4/src/Services/Default/DefaultKeyMaterialService.cs b/src/IdentityServer4/src/Services/Default/DefaultKeyMaterialService.cs index a7590dc7a4..2ba2811477 100644 --- a/src/IdentityServer4/src/Services/Default/DefaultKeyMaterialService.cs +++ b/src/IdentityServer4/src/Services/Default/DefaultKeyMaterialService.cs @@ -1,15 +1,15 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. +// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. using System.Collections.Generic; using System.Threading.Tasks; -using Microsoft.IdentityModel.Tokens; using IdentityServer4.Stores; using IdentityServer4.Models; using System.Linq; using System; using IdentityServer4.Extensions; +using SigningCredentials = Microsoft.IdentityModel.Tokens.SigningCredentials; namespace IdentityServer4.Services { diff --git a/src/IdentityServer4/src/Services/Default/DefaultTokenCreationService.cs b/src/IdentityServer4/src/Services/Default/DefaultTokenCreationService.cs index 8ac48388c1..c8d89f6831 100644 --- a/src/IdentityServer4/src/Services/Default/DefaultTokenCreationService.cs +++ b/src/IdentityServer4/src/Services/Default/DefaultTokenCreationService.cs @@ -8,12 +8,15 @@ using IdentityServer4.Models; using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Logging; -using Microsoft.IdentityModel.Tokens; +using Microsoft.IdentityModel.JsonWebTokens; +using Newtonsoft.Json; using System; +using System.Collections.Generic; using System.Globalization; using System.IdentityModel.Tokens.Jwt; using System.Threading.Tasks; using static IdentityServer4.IdentityServerConstants; +using Token = IdentityServer4.Models.Token; namespace IdentityServer4.Services { @@ -70,10 +73,10 @@ public DefaultTokenCreationService( /// public virtual async Task CreateTokenAsync(Token token) { - var header = await CreateHeaderAsync(token); + var additionalHeaderElements = await CreateHeaderAsync(token); var payload = await CreatePayloadAsync(token); - return await CreateJwtAsync(new JwtSecurityToken(header, payload)); + return await CreateJwtAsync(token, payload, additionalHeaderElements); } /// @@ -81,38 +84,19 @@ public virtual async Task CreateTokenAsync(Token token) /// /// The token. /// The JWT header - protected virtual async Task CreateHeaderAsync(Token token) + protected virtual Task> CreateHeaderAsync(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 additionalHeaderElements = new Dictionary(); if (token.Type == TokenTypes.AccessToken) { if (Options.AccessTokenJwtType.IsPresent()) { - header["typ"] = Options.AccessTokenJwtType; + additionalHeaderElements["typ"] = Options.AccessTokenJwtType; } } - return header; + return Task.FromResult(additionalHeaderElements); } /// @@ -127,14 +111,26 @@ protected virtual Task CreatePayloadAsync(Token token) } /// - /// Applies the signature to the JWT + /// Creates and signs the JWT /// - /// The JWT object. - /// The signed JWT - protected virtual Task CreateJwtAsync(JwtSecurityToken jwt) + /// + /// + /// + /// + /// + protected async virtual Task CreateJwtAsync(Token token, JwtPayload payload, Dictionary additionalHeaderElements) { - var handler = new JwtSecurityTokenHandler(); - return Task.FromResult(handler.WriteToken(jwt)); + var credential = await Keys.GetSigningCredentialsAsync(token.AllowedSigningAlgorithms); + + if (credential == null) + { + throw new InvalidOperationException("No signing credential is configured. Can't create JWT token"); + } + + var payloadJson = JsonConvert.SerializeObject(payload); + + var handler = new JsonWebTokenHandler { SetDefaultTimesOnTokenCreation = false }; + return handler.CreateToken(payloadJson, credential, additionalHeaderElements); } } } \ No newline at end of file diff --git a/src/IdentityServer4/src/Validation/Default/AuthorizeRequestValidator.cs b/src/IdentityServer4/src/Validation/Default/AuthorizeRequestValidator.cs index 6fa4bb7212..f14f3cbd0b 100644 --- a/src/IdentityServer4/src/Validation/Default/AuthorizeRequestValidator.cs +++ b/src/IdentityServer4/src/Validation/Default/AuthorizeRequestValidator.cs @@ -231,15 +231,16 @@ private async Task ValidateRequestObjectAsync( { LogError("request JWT validation failure", request); return Invalid(request, error: OidcConstants.AuthorizeErrors.InvalidRequestObject, description: "Invalid JWT request"); - } + } // validate response_type match var responseType = request.Raw.Get(OidcConstants.AuthorizeRequest.ResponseType); if (responseType != null) - { - if (jwtRequestValidationResult.Payload.TryGetValue(OidcConstants.AuthorizeRequest.ResponseType, out var payloadResponseType)) + { + var payloadResponseType = jwtRequestValidationResult.Payload.Find(c => c.Type == OidcConstants.AuthorizeRequest.ResponseType); + if (payloadResponseType != null) { - if (payloadResponseType != responseType) + if (payloadResponseType.Value != responseType) { LogError("response_type in JWT payload does not match response_type in request", request); return Invalid(request, description: "Invalid JWT request"); @@ -247,10 +248,11 @@ private async Task ValidateRequestObjectAsync( } } - // validate client_id mismatch - if (jwtRequestValidationResult.Payload.TryGetValue(OidcConstants.AuthorizeRequest.ClientId, out var payloadClientId)) + // validate client_id mismatch + var payloadClientId = jwtRequestValidationResult.Payload.Find(c => c.Type == OidcConstants.AuthorizeRequest.ClientId); + if (payloadClientId != null) { - if (!string.Equals(request.Client.ClientId, payloadClientId, StringComparison.Ordinal)) + if (!string.Equals(request.Client.ClientId, payloadClientId.Value, StringComparison.Ordinal)) { LogError("client_id in JWT payload does not match client_id in request", request); return Invalid(request, description: "Invalid JWT request"); @@ -267,25 +269,26 @@ private async Task ValidateRequestObjectAsync( JwtClaimTypes.Issuer, JwtClaimTypes.Audience }; - - // merge jwt payload values into original request parameters - foreach (var key in jwtRequestValidationResult.Payload.Keys) - { - if (ignoreKeys.Contains(key)) continue; - - var value = jwtRequestValidationResult.Payload[key]; - - var qsValue = request.Raw.Get(key); - if (qsValue != null) - { - if (!string.Equals(value, qsValue, StringComparison.Ordinal)) - { - LogError("parameter mismatch between request object and query string parameter.", request); - return Invalid(request, description: "Parameter mismatch in JWT request"); - } - } - - request.Raw.Set(key, value); + + // merge jwt payload values into original request parameters + //remove existing values + foreach (var claim in jwtRequestValidationResult.Payload) + { + if (ignoreKeys.Contains(claim.Type)) continue; + + var qsValue = request.Raw.Get(claim.Type); + if (qsValue != null) + { + request.Raw.Remove(claim.Type); + } + } + + //re-add values individually because there can be multiple claims with same type + foreach (var claim in jwtRequestValidationResult.Payload) + { + if (ignoreKeys.Contains(claim.Type)) continue; + + request.Raw.Add(claim.Type, claim.Value); } request.RequestObjectValues = jwtRequestValidationResult.Payload; diff --git a/src/IdentityServer4/src/Validation/Default/JwtRequestValidator.cs b/src/IdentityServer4/src/Validation/Default/JwtRequestValidator.cs index 2201116173..f2b92f770a 100644 --- a/src/IdentityServer4/src/Validation/Default/JwtRequestValidator.cs +++ b/src/IdentityServer4/src/Validation/Default/JwtRequestValidator.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; +using System.Security.Claims; using System.Threading.Tasks; using IdentityModel; using IdentityServer4.Configuration; @@ -190,32 +191,13 @@ protected virtual Task ValidateJwtAsync(string jwtTokenString, /// /// The JWT token /// - protected virtual Task> ProcessPayloadAsync(JwtSecurityToken token) + protected virtual Task> ProcessPayloadAsync(JwtSecurityToken token) { // filter JWT validation values - var payload = new Dictionary(); - foreach (var key in token.Payload.Keys) - { - 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; - } - } - } + var filter = Constants.Filters.JwtRequestClaimTypesFilter; - return Task.FromResult(payload); + var filteredClaims = token.Claims.Where(claim => !filter.Contains(claim.Type)); + return Task.FromResult(filteredClaims.ToList()); } } } \ No newline at end of file diff --git a/src/IdentityServer4/src/Validation/Models/JwtRequestValidationResult.cs b/src/IdentityServer4/src/Validation/Models/JwtRequestValidationResult.cs index 1db8168e70..6576c60d3b 100644 --- a/src/IdentityServer4/src/Validation/Models/JwtRequestValidationResult.cs +++ b/src/IdentityServer4/src/Validation/Models/JwtRequestValidationResult.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; +using System.Security.Claims; namespace IdentityServer4.Validation { @@ -14,6 +15,6 @@ public class JwtRequestValidationResult : ValidationResult /// /// The key/value pairs from the JWT payload of a successfuly validated request. /// - public Dictionary Payload { get; set; } + public List Payload { get; set; } } } \ No newline at end of file diff --git a/src/IdentityServer4/src/Validation/Models/ValidatedAuthorizeRequest.cs b/src/IdentityServer4/src/Validation/Models/ValidatedAuthorizeRequest.cs index 441cb0d993..60ba626d22 100644 --- a/src/IdentityServer4/src/Validation/Models/ValidatedAuthorizeRequest.cs +++ b/src/IdentityServer4/src/Validation/Models/ValidatedAuthorizeRequest.cs @@ -1,10 +1,11 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. +// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. using IdentityModel; using System.Collections.Generic; using System.Linq; +using System.Security.Claims; namespace IdentityServer4.Validation { @@ -172,7 +173,7 @@ public class ValidatedAuthorizeRequest : ValidatedRequest /// /// The request object values /// - public Dictionary RequestObjectValues { get; set; } = new Dictionary(); + public List RequestObjectValues { get; set; } = new List(); /// /// Gets or sets the request object (either passed by value or retrieved by reference) diff --git a/src/IdentityServer4/test/IdentityServer.IntegrationTests/Endpoints/Authorize/JwtRequestAuthorizeTests.cs b/src/IdentityServer4/test/IdentityServer.IntegrationTests/Endpoints/Authorize/JwtRequestAuthorizeTests.cs index 01206f02f1..ade9238209 100644 --- a/src/IdentityServer4/test/IdentityServer.IntegrationTests/Endpoints/Authorize/JwtRequestAuthorizeTests.cs +++ b/src/IdentityServer4/test/IdentityServer.IntegrationTests/Endpoints/Authorize/JwtRequestAuthorizeTests.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; +using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Security.Claims; @@ -17,6 +18,7 @@ using IdentityServer4.Configuration; using IdentityServer4.Models; using IdentityServer4.Test; +using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.Tokens; using Newtonsoft.Json; @@ -176,9 +178,9 @@ string CreateRequestJwt(string issuer, string audience, SigningCredentials crede handler.OutboundClaimTypeMap.Clear(); var token = handler.CreateJwtSecurityToken( - issuer: issuer, - audience: audience, - signingCredentials: credential, + issuer: issuer, + audience: audience, + signingCredentials: credential, subject: Identity.Create("pwd", claims)); if (setJwtTyp) @@ -188,7 +190,14 @@ string CreateRequestJwt(string issuer, string audience, SigningCredentials crede return handler.WriteToken(token); } - + + private void CheckClaimInRequestObject(string type = "foo", string value = "123foo") + { + var claim = _mockPipeline.LoginRequest.RequestObjectValues.Find(c => c.Type == type)?.Value; + claim.Should().NotBeNull(); + claim.Should().Be(value); + } + [Fact] [Trait("Category", Category)] public async Task missing_request_object_should_fail() @@ -252,8 +261,7 @@ public async Task authorize_should_accept_valid_JWT_request_object_parameters_us _mockPipeline.LoginRequest.Parameters["foo"].Should().Be("123foo"); _mockPipeline.LoginRequest.RequestObjectValues.Count.Should().Be(11); - _mockPipeline.LoginRequest.RequestObjectValues.Should().ContainKey("foo"); - _mockPipeline.LoginRequest.RequestObjectValues["foo"].Should().Be("123foo"); + CheckClaimInRequestObject(); } [Fact] @@ -300,8 +308,7 @@ public async Task authorize_should_accept_valid_JWT_request_object_parameters_us _mockPipeline.LoginRequest.Parameters["foo"].Should().Be("123foo"); _mockPipeline.LoginRequest.RequestObjectValues.Count.Should().Be(11); - _mockPipeline.LoginRequest.RequestObjectValues.Should().ContainKey("foo"); - _mockPipeline.LoginRequest.RequestObjectValues["foo"].Should().Be("123foo"); + CheckClaimInRequestObject(); } [Fact] @@ -348,8 +355,7 @@ public async Task authorize_should_accept_valid_JWT_request_object_parameters_us _mockPipeline.LoginRequest.Parameters["foo"].Should().Be("123foo"); _mockPipeline.LoginRequest.RequestObjectValues.Count.Should().Be(11); - _mockPipeline.LoginRequest.RequestObjectValues.Should().ContainKey("foo"); - _mockPipeline.LoginRequest.RequestObjectValues["foo"].Should().Be("123foo"); + CheckClaimInRequestObject(); } [Fact] @@ -398,8 +404,7 @@ public async Task correct_jwt_typ_should_pass_strict_validation() _mockPipeline.LoginRequest.Parameters["foo"].Should().Be("123foo"); _mockPipeline.LoginRequest.RequestObjectValues.Count.Should().Be(11); - _mockPipeline.LoginRequest.RequestObjectValues.Should().ContainKey("foo"); - _mockPipeline.LoginRequest.RequestObjectValues["foo"].Should().Be("123foo"); + CheckClaimInRequestObject(); } [Fact] @@ -438,51 +443,6 @@ public async Task missing_jwt_typ_should_error() _mockPipeline.ErrorMessage.Error.Should().Be("invalid_request_object"); _mockPipeline.LoginRequest.Should().BeNull(); } - - [Fact] - [Trait("Category", Category)] - public async Task mismatch_in_jwt_values_should_error() - { - var requestJwt = CreateRequestJwt( - issuer: _client.ClientId, - audience: IdentityServerPipeline.BaseUrl, - credential: new SigningCredentials(_rsaKey, "RS256"), - claims: new[] { - new Claim("client_id", _client.ClientId), - new Claim("response_type", "id_token"), - new Claim("scope", "openid profile"), - new Claim("state", "123state"), - new Claim("nonce", "123nonce"), - new Claim("redirect_uri", "https://client/callback"), - new Claim("acr_values", "acr_1 acr_2 tenant:tenant_value idp:idp_value"), - new Claim("login_hint", "login_hint_value"), - new Claim("display", "popup"), - new Claim("ui_locales", "ui_locale_value"), - new Claim("foo", "123foo"), - }); - - var url = _mockPipeline.CreateAuthorizeUrl( - clientId: _client.ClientId, - responseType: "id_token", - scope: "bad", - state: "bad", - nonce: "bad", - redirectUri: "bad", - acrValues: "bad", - loginHint: "bad", - extra: new - { - display = "bad", - ui_locales = "bad", - foo = "bad", - request = requestJwt - }); - var response = await _mockPipeline.BrowserClient.GetAsync(url); - - _mockPipeline.ErrorMessage.Error.Should().Be("invalid_request"); - _mockPipeline.ErrorMessage.ErrorDescription.Should().Be("Parameter mismatch in JWT request"); - _mockPipeline.LoginRequest.Should().BeNull(); - } [Fact] [Trait("Category", Category)] @@ -529,18 +489,21 @@ public async Task authorize_should_accept_complex_objects_in_request_object() var someObj2 = JsonConvert.DeserializeObject(_mockPipeline.LoginRequest.Parameters["someObj"], someObj.GetType()); someObj.Should().BeEquivalentTo(someObj2); _mockPipeline.LoginRequest.Parameters["someArr"].Should().NotBeNull(); - var someArr2 = JsonConvert.DeserializeObject(_mockPipeline.LoginRequest.Parameters["someArr"]); + + var someArr2 = _mockPipeline.LoginRequest.Parameters.GetValues("someArr"); someArr2.Should().Contain(new[] { "a", "c", "b" }); someArr2.Length.Should().Be(3); - _mockPipeline.LoginRequest.RequestObjectValues.Count.Should().Be(13); - _mockPipeline.LoginRequest.RequestObjectValues["someObj"].Should().NotBeNull(); - someObj2 = JsonConvert.DeserializeObject(_mockPipeline.LoginRequest.RequestObjectValues["someObj"], someObj.GetType()); + _mockPipeline.LoginRequest.RequestObjectValues.Count.Should().Be(15); + + var someObjClaim = _mockPipeline.LoginRequest.RequestObjectValues.Single(c => c.Type == "someObj")?.Value; + someObjClaim.Should().NotBeNull(); + someObj2 = JsonConvert.DeserializeObject(someObjClaim, someObj.GetType()); someObj.Should().BeEquivalentTo(someObj2); - _mockPipeline.LoginRequest.RequestObjectValues["someArr"].Should().NotBeNull(); - someArr2 = JsonConvert.DeserializeObject(_mockPipeline.LoginRequest.Parameters["someArr"]); - someArr2.Should().Contain(new[] { "a", "c", "b" }); - someArr2.Length.Should().Be(3); + + var arrayObjectValue = _mockPipeline.LoginRequest.RequestObjectValues.FindAll(c => c.Type == "someArr").ConvertAll(c => c.Value).ToArray(); + arrayObjectValue.Length.Should().Be(3); + arrayObjectValue.Should().Contain(new[] { "a", "c", "b" }); } [Fact] From 39690179def596d0eaec733fa25819f2b4ca03c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Louren=C3=A7o?= Date: Mon, 5 Sep 2022 00:17:08 -0300 Subject: [PATCH 4/8] Updated EntityFramework target framework. --- .config/dotnet-tools.json | 2 +- src/EntityFramework/host/Host.csproj | 20 +++++++++++++------ src/EntityFramework/host/Program.cs | 4 ++-- src/EntityFramework/host/Startup.cs | 6 +++--- .../migrations/SqlServer/SqlServer.csproj | 4 ++-- .../IdentityServer4.EntityFramework.csproj | 4 ++-- ...entityServer4.EntityFramework.Tests.csproj | 4 ++-- 7 files changed, 26 insertions(+), 18 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index db29a16b09..3418959e61 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -9,7 +9,7 @@ ] }, "dotnet-ef": { - "version": "3.1.0", + "version": "6.0.8", "commands": [ "dotnet-ef" ] diff --git a/src/EntityFramework/host/Host.csproj b/src/EntityFramework/host/Host.csproj index 0fc6e1bebd..4d5a852a32 100644 --- a/src/EntityFramework/host/Host.csproj +++ b/src/EntityFramework/host/Host.csproj @@ -1,13 +1,21 @@ - + - netcoreapp3.1 + net6.0 - - - - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + diff --git a/src/EntityFramework/host/Program.cs b/src/EntityFramework/host/Program.cs index ca520d3f0f..41da23d314 100644 --- a/src/EntityFramework/host/Program.cs +++ b/src/EntityFramework/host/Program.cs @@ -1,4 +1,4 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. +// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. @@ -55,7 +55,7 @@ public static int Main(string[] args) } public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) + Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder(args) .UseSerilog() .ConfigureWebHostDefaults(webBuilder => { diff --git a/src/EntityFramework/host/Startup.cs b/src/EntityFramework/host/Startup.cs index 0e67fbd602..876634037f 100644 --- a/src/EntityFramework/host/Startup.cs +++ b/src/EntityFramework/host/Startup.cs @@ -1,4 +1,4 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. +// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. @@ -31,12 +31,12 @@ public void ConfigureServices(IServiceCollection services) // this adds the config data from DB (clients, resources, CORS) .AddConfigurationStore(options => { - options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString); + options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString, b => b.MigrationsAssembly("Host")); }) // this adds the operational data from DB (codes, tokens, consents) .AddOperationalStore(options => { - options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString); + options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString, b => b.MigrationsAssembly("Host")); // this enables automatic token cleanup. this is optional. options.EnableTokenCleanup = true; diff --git a/src/EntityFramework/migrations/SqlServer/SqlServer.csproj b/src/EntityFramework/migrations/SqlServer/SqlServer.csproj index 5136d93842..1f4bc6fa74 100644 --- a/src/EntityFramework/migrations/SqlServer/SqlServer.csproj +++ b/src/EntityFramework/migrations/SqlServer/SqlServer.csproj @@ -1,7 +1,7 @@ - + - netcoreapp3.1 + net6.0 diff --git a/src/EntityFramework/src/IdentityServer4.EntityFramework.csproj b/src/EntityFramework/src/IdentityServer4.EntityFramework.csproj index 2941966a90..6a86fe7872 100644 --- a/src/EntityFramework/src/IdentityServer4.EntityFramework.csproj +++ b/src/EntityFramework/src/IdentityServer4.EntityFramework.csproj @@ -1,8 +1,8 @@ - + IdentityServer4.EntityFramework - netcoreapp3.1 + net6.0 EntityFramework persistence layer for IdentityServer4 Brock Allen;Dominick Baier;Scott Brady diff --git a/src/EntityFramework/test/IdentityServer4.EntityFramework.Tests/IdentityServer4.EntityFramework.Tests.csproj b/src/EntityFramework/test/IdentityServer4.EntityFramework.Tests/IdentityServer4.EntityFramework.Tests.csproj index dcf5c194cc..6e3c07f734 100644 --- a/src/EntityFramework/test/IdentityServer4.EntityFramework.Tests/IdentityServer4.EntityFramework.Tests.csproj +++ b/src/EntityFramework/test/IdentityServer4.EntityFramework.Tests/IdentityServer4.EntityFramework.Tests.csproj @@ -1,7 +1,7 @@ - + - netcoreapp3.1 + net6.0 false From fb15b5f97ba7091807475a946f8615f3414ef62b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Louren=C3=A7o?= Date: Mon, 5 Sep 2022 10:12:40 -0300 Subject: [PATCH 5/8] Updated target framework in identity project. --- src/AspNetIdentity/host/Host.csproj | 12 +-- .../SqlServer/Migrations/UsersDb.sql | 20 ++--- ...er.cs => 20220905130155_Users.Designer.cs} | 65 ++++++++-------- ...35751_Users.cs => 20220905130155_Users.cs} | 76 ++++++++++--------- .../ApplicationDbContextModelSnapshot.cs | 63 ++++++++------- .../migrations/SqlServer/SqlServer.csproj | 4 +- .../src/IdentityServer4.AspNetIdentity.csproj | 4 +- 7 files changed, 123 insertions(+), 121 deletions(-) rename src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb/{20200323135751_Users.Designer.cs => 20220905130155_Users.Designer.cs} (83%) rename src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb/{20200323135751_Users.cs => 20220905130155_Users.cs} (65%) diff --git a/src/AspNetIdentity/host/Host.csproj b/src/AspNetIdentity/host/Host.csproj index 30fcf037fa..e2ced8a699 100644 --- a/src/AspNetIdentity/host/Host.csproj +++ b/src/AspNetIdentity/host/Host.csproj @@ -1,14 +1,14 @@ - + - netcoreapp3.1 + net6.0 - - - - + + + + diff --git a/src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb.sql b/src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb.sql index a740a47645..389d5db9b5 100644 --- a/src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb.sql +++ b/src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb.sql @@ -6,7 +6,9 @@ BEGIN CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId]) ); END; +GO +BEGIN TRANSACTION; GO CREATE TABLE [AspNetRoles] ( @@ -16,7 +18,6 @@ CREATE TABLE [AspNetRoles] ( [ConcurrencyStamp] nvarchar(max) NULL, CONSTRAINT [PK_AspNetRoles] PRIMARY KEY ([Id]) ); - GO CREATE TABLE [AspNetUsers] ( @@ -37,7 +38,6 @@ CREATE TABLE [AspNetUsers] ( [AccessFailedCount] int NOT NULL, CONSTRAINT [PK_AspNetUsers] PRIMARY KEY ([Id]) ); - GO CREATE TABLE [AspNetRoleClaims] ( @@ -48,7 +48,6 @@ CREATE TABLE [AspNetRoleClaims] ( CONSTRAINT [PK_AspNetRoleClaims] PRIMARY KEY ([Id]), CONSTRAINT [FK_AspNetRoleClaims_AspNetRoles_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [AspNetRoles] ([Id]) ON DELETE CASCADE ); - GO CREATE TABLE [AspNetUserClaims] ( @@ -59,7 +58,6 @@ CREATE TABLE [AspNetUserClaims] ( CONSTRAINT [PK_AspNetUserClaims] PRIMARY KEY ([Id]), CONSTRAINT [FK_AspNetUserClaims_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE ); - GO CREATE TABLE [AspNetUserLogins] ( @@ -70,7 +68,6 @@ CREATE TABLE [AspNetUserLogins] ( CONSTRAINT [PK_AspNetUserLogins] PRIMARY KEY ([LoginProvider], [ProviderKey]), CONSTRAINT [FK_AspNetUserLogins_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE ); - GO CREATE TABLE [AspNetUserRoles] ( @@ -80,7 +77,6 @@ CREATE TABLE [AspNetUserRoles] ( CONSTRAINT [FK_AspNetUserRoles_AspNetRoles_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [AspNetRoles] ([Id]) ON DELETE CASCADE, CONSTRAINT [FK_AspNetUserRoles_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE ); - GO CREATE TABLE [AspNetUserTokens] ( @@ -91,39 +87,33 @@ CREATE TABLE [AspNetUserTokens] ( CONSTRAINT [PK_AspNetUserTokens] PRIMARY KEY ([UserId], [LoginProvider], [Name]), CONSTRAINT [FK_AspNetUserTokens_AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [AspNetUsers] ([Id]) ON DELETE CASCADE ); - GO CREATE INDEX [IX_AspNetRoleClaims_RoleId] ON [AspNetRoleClaims] ([RoleId]); - GO CREATE UNIQUE INDEX [RoleNameIndex] ON [AspNetRoles] ([NormalizedName]) WHERE [NormalizedName] IS NOT NULL; - GO CREATE INDEX [IX_AspNetUserClaims_UserId] ON [AspNetUserClaims] ([UserId]); - GO CREATE INDEX [IX_AspNetUserLogins_UserId] ON [AspNetUserLogins] ([UserId]); - GO CREATE INDEX [IX_AspNetUserRoles_RoleId] ON [AspNetUserRoles] ([RoleId]); - GO CREATE INDEX [EmailIndex] ON [AspNetUsers] ([NormalizedEmail]); - GO CREATE UNIQUE INDEX [UserNameIndex] ON [AspNetUsers] ([NormalizedUserName]) WHERE [NormalizedUserName] IS NOT NULL; - GO INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) -VALUES (N'20200323135751_Users', N'3.1.0'); +VALUES (N'20220905130155_Users', N'6.0.8'); +GO +COMMIT; GO diff --git a/src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb/20200323135751_Users.Designer.cs b/src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb/20220905130155_Users.Designer.cs similarity index 83% rename from src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb/20200323135751_Users.Designer.cs rename to src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb/20220905130155_Users.Designer.cs index ff64f223cc..0f4937ad38 100644 --- a/src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb/20200323135751_Users.Designer.cs +++ b/src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb/20220905130155_Users.Designer.cs @@ -7,19 +7,22 @@ using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +#nullable disable + namespace SqlServer.Migrations.UsersDb { [DbContext(typeof(ApplicationDbContext))] - [Migration("20200323135751_Users")] + [Migration("20220905130155_Users")] partial class Users { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.0") - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .HasAnnotation("ProductVersion", "6.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); modelBuilder.Entity("IdentityServer4.Models.ApplicationUser", b => { @@ -34,8 +37,8 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnType("nvarchar(max)"); b.Property("Email") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("EmailConfirmed") .HasColumnType("bit"); @@ -47,12 +50,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnType("datetimeoffset"); b.Property("NormalizedEmail") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("NormalizedUserName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("PasswordHash") .HasColumnType("nvarchar(max)"); @@ -70,20 +73,20 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnType("bit"); b.Property("UserName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.HasKey("Id"); b.HasIndex("NormalizedEmail") - .HasName("EmailIndex"); + .HasDatabaseName("EmailIndex"); b.HasIndex("NormalizedUserName") .IsUnique() - .HasName("UserNameIndex") + .HasDatabaseName("UserNameIndex") .HasFilter("[NormalizedUserName] IS NOT NULL"); - b.ToTable("AspNetUsers"); + b.ToTable("AspNetUsers", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => @@ -96,29 +99,30 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnType("nvarchar(max)"); b.Property("Name") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("NormalizedName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.HasKey("Id"); b.HasIndex("NormalizedName") .IsUnique() - .HasName("RoleNameIndex") + .HasDatabaseName("RoleNameIndex") .HasFilter("[NormalizedName] IS NOT NULL"); - b.ToTable("AspNetRoles"); + b.ToTable("AspNetRoles", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); b.Property("ClaimType") .HasColumnType("nvarchar(max)"); @@ -134,15 +138,16 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("RoleId"); - b.ToTable("AspNetRoleClaims"); + b.ToTable("AspNetRoleClaims", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); b.Property("ClaimType") .HasColumnType("nvarchar(max)"); @@ -158,7 +163,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("UserId"); - b.ToTable("AspNetUserClaims"); + b.ToTable("AspNetUserClaims", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => @@ -180,7 +185,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("UserId"); - b.ToTable("AspNetUserLogins"); + b.ToTable("AspNetUserLogins", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => @@ -195,7 +200,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasIndex("RoleId"); - b.ToTable("AspNetUserRoles"); + b.ToTable("AspNetUserRoles", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => @@ -214,7 +219,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasKey("UserId", "LoginProvider", "Name"); - b.ToTable("AspNetUserTokens"); + b.ToTable("AspNetUserTokens", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => diff --git a/src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb/20200323135751_Users.cs b/src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb/20220905130155_Users.cs similarity index 65% rename from src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb/20200323135751_Users.cs rename to src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb/20220905130155_Users.cs index 86a4ccc128..86f1a00546 100644 --- a/src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb/20200323135751_Users.cs +++ b/src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb/20220905130155_Users.cs @@ -1,6 +1,8 @@ using System; using Microsoft.EntityFrameworkCore.Migrations; +#nullable disable + namespace SqlServer.Migrations.UsersDb { public partial class Users : Migration @@ -11,10 +13,10 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "AspNetRoles", columns: table => new { - Id = table.Column(nullable: false), - Name = table.Column(maxLength: 256, nullable: true), - NormalizedName = table.Column(maxLength: 256, nullable: true), - ConcurrencyStamp = table.Column(nullable: true) + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true) }, constraints: table => { @@ -25,21 +27,21 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "AspNetUsers", columns: table => new { - Id = table.Column(nullable: false), - UserName = table.Column(maxLength: 256, nullable: true), - NormalizedUserName = table.Column(maxLength: 256, nullable: true), - Email = table.Column(maxLength: 256, nullable: true), - NormalizedEmail = table.Column(maxLength: 256, nullable: true), - EmailConfirmed = table.Column(nullable: false), - PasswordHash = table.Column(nullable: true), - SecurityStamp = table.Column(nullable: true), - ConcurrencyStamp = table.Column(nullable: true), - PhoneNumber = table.Column(nullable: true), - PhoneNumberConfirmed = table.Column(nullable: false), - TwoFactorEnabled = table.Column(nullable: false), - LockoutEnd = table.Column(nullable: true), - LockoutEnabled = table.Column(nullable: false), - AccessFailedCount = table.Column(nullable: false) + Id = table.Column(type: "nvarchar(450)", nullable: false), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + EmailConfirmed = table.Column(type: "bit", nullable: false), + PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), + SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), + PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), + TwoFactorEnabled = table.Column(type: "bit", nullable: false), + LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), + LockoutEnabled = table.Column(type: "bit", nullable: false), + AccessFailedCount = table.Column(type: "int", nullable: false) }, constraints: table => { @@ -50,11 +52,11 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "AspNetRoleClaims", columns: table => new { - Id = table.Column(nullable: false) + Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), - RoleId = table.Column(nullable: false), - ClaimType = table.Column(nullable: true), - ClaimValue = table.Column(nullable: true) + RoleId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) }, constraints: table => { @@ -71,11 +73,11 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "AspNetUserClaims", columns: table => new { - Id = table.Column(nullable: false) + Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), - UserId = table.Column(nullable: false), - ClaimType = table.Column(nullable: true), - ClaimValue = table.Column(nullable: true) + UserId = table.Column(type: "nvarchar(450)", nullable: false), + ClaimType = table.Column(type: "nvarchar(max)", nullable: true), + ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) }, constraints: table => { @@ -92,10 +94,10 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "AspNetUserLogins", columns: table => new { - LoginProvider = table.Column(nullable: false), - ProviderKey = table.Column(nullable: false), - ProviderDisplayName = table.Column(nullable: true), - UserId = table.Column(nullable: false) + LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), + ProviderKey = table.Column(type: "nvarchar(450)", nullable: false), + ProviderDisplayName = table.Column(type: "nvarchar(max)", nullable: true), + UserId = table.Column(type: "nvarchar(450)", nullable: false) }, constraints: table => { @@ -112,8 +114,8 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "AspNetUserRoles", columns: table => new { - UserId = table.Column(nullable: false), - RoleId = table.Column(nullable: false) + UserId = table.Column(type: "nvarchar(450)", nullable: false), + RoleId = table.Column(type: "nvarchar(450)", nullable: false) }, constraints: table => { @@ -136,10 +138,10 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "AspNetUserTokens", columns: table => new { - UserId = table.Column(nullable: false), - LoginProvider = table.Column(nullable: false), - Name = table.Column(nullable: false), - Value = table.Column(nullable: true) + UserId = table.Column(type: "nvarchar(450)", nullable: false), + LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(450)", nullable: false), + Value = table.Column(type: "nvarchar(max)", nullable: true) }, constraints: table => { diff --git a/src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb/ApplicationDbContextModelSnapshot.cs b/src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb/ApplicationDbContextModelSnapshot.cs index 6da3c414a6..f6048bfede 100644 --- a/src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb/ApplicationDbContextModelSnapshot.cs +++ b/src/AspNetIdentity/migrations/SqlServer/Migrations/UsersDb/ApplicationDbContextModelSnapshot.cs @@ -6,6 +6,8 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +#nullable disable + namespace SqlServer.Migrations.UsersDb { [DbContext(typeof(ApplicationDbContext))] @@ -15,9 +17,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.0") - .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .HasAnnotation("ProductVersion", "6.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); modelBuilder.Entity("IdentityServer4.Models.ApplicationUser", b => { @@ -32,8 +35,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("nvarchar(max)"); b.Property("Email") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("EmailConfirmed") .HasColumnType("bit"); @@ -45,12 +48,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("datetimeoffset"); b.Property("NormalizedEmail") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("NormalizedUserName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("PasswordHash") .HasColumnType("nvarchar(max)"); @@ -68,20 +71,20 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("bit"); b.Property("UserName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.HasKey("Id"); b.HasIndex("NormalizedEmail") - .HasName("EmailIndex"); + .HasDatabaseName("EmailIndex"); b.HasIndex("NormalizedUserName") .IsUnique() - .HasName("UserNameIndex") + .HasDatabaseName("UserNameIndex") .HasFilter("[NormalizedUserName] IS NOT NULL"); - b.ToTable("AspNetUsers"); + b.ToTable("AspNetUsers", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => @@ -94,29 +97,30 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("nvarchar(max)"); b.Property("Name") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.Property("NormalizedName") - .HasColumnType("nvarchar(256)") - .HasMaxLength(256); + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); b.HasKey("Id"); b.HasIndex("NormalizedName") .IsUnique() - .HasName("RoleNameIndex") + .HasDatabaseName("RoleNameIndex") .HasFilter("[NormalizedName] IS NOT NULL"); - b.ToTable("AspNetRoles"); + b.ToTable("AspNetRoles", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); b.Property("ClaimType") .HasColumnType("nvarchar(max)"); @@ -132,15 +136,16 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("RoleId"); - b.ToTable("AspNetRoleClaims"); + b.ToTable("AspNetRoleClaims", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int") - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); b.Property("ClaimType") .HasColumnType("nvarchar(max)"); @@ -156,7 +161,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("UserId"); - b.ToTable("AspNetUserClaims"); + b.ToTable("AspNetUserClaims", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => @@ -178,7 +183,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("UserId"); - b.ToTable("AspNetUserLogins"); + b.ToTable("AspNetUserLogins", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => @@ -193,7 +198,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("RoleId"); - b.ToTable("AspNetUserRoles"); + b.ToTable("AspNetUserRoles", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => @@ -212,7 +217,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("UserId", "LoginProvider", "Name"); - b.ToTable("AspNetUserTokens"); + b.ToTable("AspNetUserTokens", (string)null); }); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => diff --git a/src/AspNetIdentity/migrations/SqlServer/SqlServer.csproj b/src/AspNetIdentity/migrations/SqlServer/SqlServer.csproj index 2614da8ab0..076102535b 100644 --- a/src/AspNetIdentity/migrations/SqlServer/SqlServer.csproj +++ b/src/AspNetIdentity/migrations/SqlServer/SqlServer.csproj @@ -1,7 +1,7 @@ - + - netcoreapp3.1 + net6.0 diff --git a/src/AspNetIdentity/src/IdentityServer4.AspNetIdentity.csproj b/src/AspNetIdentity/src/IdentityServer4.AspNetIdentity.csproj index fd77a97050..c7450b5d0e 100644 --- a/src/AspNetIdentity/src/IdentityServer4.AspNetIdentity.csproj +++ b/src/AspNetIdentity/src/IdentityServer4.AspNetIdentity.csproj @@ -1,8 +1,8 @@ - + IdentityServer4.AspNetIdentity - netcoreapp3.1 + net6.0 ASP.NET Core Identity Integration for IdentityServer4 Brock Allen;Dominick Baier From 124cc4a8e054c5a156bb265e20ed6cf359f9600b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Louren=C3=A7o?= Date: Fri, 9 Sep 2022 19:59:57 -0300 Subject: [PATCH 6/8] Consider Api Resource Scopes as an Api Scope. --- .../Default/AuthorizeRequestValidator.cs | 2 +- .../Default/DefaultResourceValidator.cs | 40 ++++++++++++++++++- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/IdentityServer4/src/Validation/Default/AuthorizeRequestValidator.cs b/src/IdentityServer4/src/Validation/Default/AuthorizeRequestValidator.cs index f14f3cbd0b..36e39a8780 100644 --- a/src/IdentityServer4/src/Validation/Default/AuthorizeRequestValidator.cs +++ b/src/IdentityServer4/src/Validation/Default/AuthorizeRequestValidator.cs @@ -601,7 +601,7 @@ private async Task ValidateScopeAsync(Validate return Invalid(request, OidcConstants.AuthorizeErrors.InvalidScope, "Identity scopes requested, but openid scope is missing"); } - if (validatedResources.Resources.ApiScopes.Any()) + if (validatedResources.Resources.ApiScopes.Any() || validatedResources.Resources.ApiResources.Any()) { request.IsApiResourceRequest = true; } diff --git a/src/IdentityServer4/src/Validation/Default/DefaultResourceValidator.cs b/src/IdentityServer4/src/Validation/Default/DefaultResourceValidator.cs index ebceeb70f1..e85a73cb7a 100644 --- a/src/IdentityServer4/src/Validation/Default/DefaultResourceValidator.cs +++ b/src/IdentityServer4/src/Validation/Default/DefaultResourceValidator.cs @@ -136,8 +136,28 @@ protected virtual async Task ValidateScopeAsync( } else { - _logger.LogError("Scope {scope} not found in store.", requestedScope.ParsedName); - result.InvalidScopes.Add(requestedScope.RawValue); + var apiResources = resourcesFromStore.FindApiResourcesByScope(requestedScope.ParsedName); + if (apiResources.Any()) + { + if (await IsClientAllowedApiResourceScopeAsync(client, requestedScope.ParsedName)) + { + result.ParsedScopes.Add(requestedScope); + + foreach (var api in apiResources) + { + result.Resources.ApiResources.Add(api); + } + } + else + { + result.InvalidScopes.Add(requestedScope.RawValue); + } + } + else + { + _logger.LogError("Scope {scope} not found in store.", requestedScope.ParsedName); + result.InvalidScopes.Add(requestedScope.RawValue); + } } } } @@ -175,6 +195,22 @@ protected virtual Task IsClientAllowedApiScopeAsync(Client client, ApiScop return Task.FromResult(allowed); } + /// + /// Determines if client is allowed access to the API Resource scope. + /// + /// + /// + /// + protected virtual Task IsClientAllowedApiResourceScopeAsync(Client client, string scope) + { + var allowed = client.AllowedScopes.Contains(scope); + if (!allowed) + { + _logger.LogError("Client {client} is not allowed access to scope {scope}.", client.ClientId, scope); + } + return Task.FromResult(allowed); + } + /// /// Validates if the client is allowed offline_access. /// From 094e0cdb246733ffc3704b8c6a7aacff6ff99d2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Louren=C3=A7o?= Date: Tue, 20 Sep 2022 11:03:29 -0300 Subject: [PATCH 7/8] Updated md files. --- .github/CONTRIBUTING.md | 2 +- .github/FUNDING.yml | 4 +- .github/ISSUE_TEMPLATE/Question.md | 7 ---- .github/PULL_REQUEST_TEMPLATE.md | 24 ++++++++++-- .github/stale.yml | 2 - README.md | 43 +++++++-------------- SECURITY.MD | 2 +- SPONSORS.md | 54 --------------------------- samples/Clients/readme.md | 2 +- src/AspNetIdentity/README.md | 2 +- src/EntityFramework.Storage/README.md | 2 +- src/EntityFramework/README.md | 2 +- 12 files changed, 43 insertions(+), 103 deletions(-) delete mode 100644 SPONSORS.md diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index bdea353057..c11edadb63 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -6,7 +6,7 @@ Then we can decide if and how a feature or a change could be implemented and if Also read this first: [Being a good open source citizen](https://hackernoon.com/being-a-good-open-source-citizen-9060d0ab9732#.x3hocgw85) ## Found an issue or a bug? -Please start a discussion on the [core repo issue tracker](https://github.com/IdentityServer/IdentityServer4/issues). +Please start a discussion on the [core repo issue tracker](https://github.com/LacunaSoftware/IdentityServer4/issues). ## Filing issues The best way to get your bug fixed is to be as detailed as you can be about the problem. diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 8d29f53488..67ecec2bf7 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,7 +1,7 @@ # These are supported funding model platforms -github: brockallen -patreon: identityserver +github: LacunaSoftware +patreon: # Replace with patreon open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel diff --git a/.github/ISSUE_TEMPLATE/Question.md b/.github/ISSUE_TEMPLATE/Question.md index 3b0655e10d..764ccf7e94 100644 --- a/.github/ISSUE_TEMPLATE/Question.md +++ b/.github/ISSUE_TEMPLATE/Question.md @@ -1,11 +1,4 @@ --- name: Question -about: This repo is not maintained anyone. All new work happens under the new organization https://github.com/DuendeSoftware. labels: question --- - - diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 26ce4b1011..a09bdf5abb 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,5 +1,23 @@ -**At this point we cannot accept PRs anymore. Thanks!** +# Pull Request Template -This organization is not maintained anymore besides critical security bugfixes (if feasible). This organization will be archived when .NET Core 3.1 end of support is reached (3rd Dec 2022). All new development is happening in the new [Duende Software](https://github.com/duendesoftware) organization. +## Description -The new [Duende IdentityServer](https://duendesoftware.com/products/identityserver) comes with a commercial license but is [free](https://blog.duendesoftware.com/posts/20220111_fair_trade/) for dev/testing/personal projects and companies or individuals making less than 1M USD gross annnual revenue. Please [get in touch with us](https://duendesoftware.com/contact) if you have any question. +Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. + +Fixes # (issue) + +## Type of change + +Please delete options that are not relevant. + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] This change requires a documentation update + +## How Has This Been Tested? + +Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration + +- [ ] Test A +- [ ] Test B \ No newline at end of file diff --git a/.github/stale.yml b/.github/stale.yml index 7227f594e2..edc5b239de 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -14,7 +14,5 @@ staleLabel: wontfix markComment: > This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. - - Questions are community supported only and the authors/maintainers may or may not have time to reply. If you or your company would like commercial support, please see [here](https://identityserver4.readthedocs.io/en/latest/intro/support.html#commercial-support) for more information. # Comment to post when closing a stale issue. Set to `false` to disable closeComment: false diff --git a/README.md b/README.md index a31edcf202..ab0a762834 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,13 @@ -# Important update -This organization is not maintained anymore besides critical security bugfixes (if feasible). This organization will be archived when .NET Core 3.1 end of support is reached (3rd Dec 2022). All new development is happening in the new [Duende Software](https://github.com/duendesoftware) organization. +# Important notice +This is a fork of IdentityServer4 that is meant to keep existing software that depends on IdentityServer4 updated with the latest .NET framework version. -The new [Duende IdentityServer](https://duendesoftware.com/products/identityserver) comes with a commercial license but is [free](https://blog.duendesoftware.com/posts/20220111_fair_trade/) for dev/testing/personal projects and companies or individuals making less than 1M USD gross annnual revenue. Please [get in touch with us](https://duendesoftware.com/contact) if you have any question. +For a state of the art implementation, updates and innovations please use [Duende IdentityServer](https://duendesoftware.com/products/identityserver). + +## Changes to IdentityServer4 +Our goal is to keep any core changes to IdentityServer4 to a minimal so compatibility is maximized. Below you can find some of those changes in order to decide if they could affect your project: + +* Api Resource Scopes can be used as Api Scopes: when validating a authorize request, IdentityServer4 validates scopes based on existing Api Resources and Api Scopes. We have +updated this code to match requested scopes with Api Resource Scopes as well. ## About IdentityServer4 [](https://dotnetfoundation.org/projects?searchquery=IdentityServer&type=project) @@ -14,11 +20,11 @@ It is part of the [.NET Foundation](https://www.dotnetfoundation.org/), and oper For project documentation, please visit [readthedocs](https://identityserver4.readthedocs.io). ## Branch structure -Active development happens on the main branch. This always contains the latest version. Each (pre-) release is tagged with the corresponding version. The [aspnetcore1](https://github.com/IdentityServer/IdentityServer4/tree/aspnetcore1) and [aspnetcore2](https://github.com/IdentityServer/IdentityServer4/tree/aspnetcore2) branches contain the latest versions of the older ASP.NET Core based versions. +Active development happens on the main branch. This always contains the latest version. Each (pre-) release is tagged with the corresponding version. ## How to build -* [Install](https://www.microsoft.com/net/download/core#/current) the latest .NET Core 3.1 SDK +* [Install](https://www.microsoft.com/net/download/core#/current) the latest .NET 6 SDK * Install Git * Clone this repo * Run `build.ps1` or `build.sh` in the root of the cloned repo @@ -26,30 +32,11 @@ Active development happens on the main branch. This always contains the latest v ## Documentation For project documentation, please visit [readthedocs](https://identityserver4.readthedocs.io). -See [here](http://docs.identityserver.io/en/aspnetcore1/) for the 1.x docs, and [here](http://docs.identityserver.io/en/aspnetcore2/) for the 2.x docs. - ## Bug reports and feature requests -Please use the [issue tracker](https://github.com/IdentityServer/IdentityServer4/issues) for that. We only support the latest version for free. For older versions, you can get a commercial support agreement with us. - -## Commercial and Community Support -If you need help with implementing IdentityServer4 or your security architecture in general, there are both free and commercial support options. -See [here](https://identityserver4.readthedocs.io/en/latest/intro/support.html) for more details. - -## Sponsorship -If you are a fan of the project or a company that relies on IdentityServer, you might want to consider sponsoring. -This will help us devote more time to answering questions and doing feature development. If you are interested please head to our [Patreon](https://www.patreon.com/identityserver) page which has further details. +Please use the [issue tracker](https://github.com/LacunaSoftware/IdentityServer4/issues) for that. -### Platinum Sponsors -[](https://udelt.no) - -[](https://github.com/dotnet-at-microsoft) - -### Corporate Sponsors -[Ritter Insurance Marketing](https://www.ritterim.com) -[ExtraNetUserManager](https://www.extranetusermanager.com/) -[Knab](https://www.knab.nl/) - -You can see a list of our current sponsors [here](https://github.com/IdentityServer/IdentityServer4/blob/main/SPONSORS.md) - and for companies we have some nice advertisement options as well. +## Help wanted +If you would like to contribute to this project feel free to use the issue tracker and/or submit Pull Requests. ## Acknowledgements IdentityServer4 is built using the following great open source projects and free services: @@ -62,5 +49,3 @@ IdentityServer4 is built using the following great open source projects and free * [XUnit](https://xunit.github.io/) * [Fluent Assertions](http://www.fluentassertions.com/) * [GitReleaseManager](https://github.com/GitTools/GitReleaseManager) - -..and last but not least a big thanks to all our [contributors](https://github.com/IdentityServer/IdentityServer4/graphs/contributors)! diff --git a/SECURITY.MD b/SECURITY.MD index 8c8c1deae8..63e05c309e 100644 --- a/SECURITY.MD +++ b/SECURITY.MD @@ -1,6 +1,6 @@ # Reporting Security Issues -If you discover a security issue in IdentityServer, please report it by sending an email to contact@identityserver.io +If you discover a security issue in IdentityServer, please report it by sending an email to support@lacunasoftware.com. This will allow us to assess the risk, and make a fix available before we add a bug report to the GitHub repository. diff --git a/SPONSORS.md b/SPONSORS.md deleted file mode 100644 index 28b1a82b6f..0000000000 --- a/SPONSORS.md +++ /dev/null @@ -1,54 +0,0 @@ -# Sponsors - -We thank those who [support](https://www.patreon.com/identityserver) IdentityServer! - -## Corporate - -### Platinum -[Udelt](https://udelt.no/) -[Microsoft .NET](https://github.com/dotnet-at-microsoft) - -### Gold -[Ritter Insurance Marketing](https://www.ritterim.com) ([@RitterIM](https://twitter.com/ritterim)) -[ExtranetUserManager](https://www.extranetusermanager.com) ([@eumgr](https://twitter.com/eumgr)) -[Knab](https://www.knab.nl/) ([@knab_nl](https://twitter.com/knab_nl)) - -### Silver - -Jacobus Roos -Soluto ([@SolutoEng](https://twitter.com/SolutoEng)) -Steinar Noem -Effectory ([@effectory](https://twitter.com/effectory)) -Real Page ([@RealPage](https://twitter.com/RealPage)) -Justify ([@justify_legal](https://twitter.com/justify_legal)) - -## Individuals - -Khalid Abuhakmeh ([@buhakmeh](https://twitter.com/buhakmeh)) -Rasika Weliwita ([@rasikaweliwita](https://twitter.com/rasikaweliwita)) -Arun David Shelly -Tobias Höft ([@tobiashoeft](https://twitter.com/tobiashoeft)) -William Grow -James Roberts -Chris Simmons ([@netchrisdotcom](https://twitter.com/netchrisdotcom)) -Shawn Wildermuth -Johan Boström ([@zarx](https://twitter.com/zarx)) -Albert ([@DerAlbert](https://twitter.com/DerAlbert)) -Hugo Biarge ([@hbiarge](https://twitter.com/hbiarge)) -Ibrahim Šuta ([@ibrahimsuta](https://twitter.com/ibrahimsuta)) -VIJAYA PAL NALLALA -Martijn Boland -Giuseppe Turitto -Mauricio Schneider -Norman L Covington -Ryan Mendoza ([@elryry](https://twitter.com/elryry)) -Colin Blair -Erik Gulbrandsen -Olga Klimova -Alexandru Puiu -Michael Calasanz -Fredrik Karlsson ([@fredrik_zenit](https://twitter.com/fredrik_zenit)) -Jeremy Sinclair ([@sinclairinator](https://twitter.com/sinclairinator)) -Bruno Brito -James Hough -vanbukin diff --git a/samples/Clients/readme.md b/samples/Clients/readme.md index 9af1e703ce..6f54d58514 100644 --- a/samples/Clients/readme.md +++ b/samples/Clients/readme.md @@ -1,3 +1,3 @@ The client samples are designed to be used with the host in this repo: -https://github.com/IdentityServer/IdentityServer4/tree/main/src/IdentityServer4 +https://github.com/LacunaSoftware/IdentityServer4/tree/main/src/IdentityServer4 diff --git a/src/AspNetIdentity/README.md b/src/AspNetIdentity/README.md index 0c0f9bd9a7..b725befb65 100644 --- a/src/AspNetIdentity/README.md +++ b/src/AspNetIdentity/README.md @@ -6,4 +6,4 @@ You can find a detailed walk-through for ASP.NET Core Identity integration [here ## Issues -For issues, use the [consolidated IdentityServer4 issue tracker](https://github.com/IdentityServer/IdentityServer4/issues). +For issues, use the [consolidated IdentityServer4 issue tracker](https://github.com/LacunaSoftware/IdentityServer4/issues). diff --git a/src/EntityFramework.Storage/README.md b/src/EntityFramework.Storage/README.md index e9d2088c42..3f72f4b8c6 100644 --- a/src/EntityFramework.Storage/README.md +++ b/src/EntityFramework.Storage/README.md @@ -4,4 +4,4 @@ IdentityServer4.EntityFramework.Storage is a persistence layer for IdentityServe ## Issues -For issues, use the [consolidated IdentityServer4 issue tracker](https://github.com/IdentityServer/IdentityServer4/issues). +For issues, use the [consolidated IdentityServer4 issue tracker](https://github.com/LacunaSoftware/IdentityServer4/issues). diff --git a/src/EntityFramework/README.md b/src/EntityFramework/README.md index 14efb7a2b5..264eb56d15 100644 --- a/src/EntityFramework/README.md +++ b/src/EntityFramework/README.md @@ -4,4 +4,4 @@ IdentityServer4.EntityFramework is a package that provides the configuration API ## Issues -For issues, use the [consolidated IdentityServer4 issue tracker](https://github.com/IdentityServer/IdentityServer4/issues). +For issues, use the [consolidated IdentityServer4 issue tracker](https://github.com/LacunaSoftware/IdentityServer4/issues). From 05173daa8f8b8ad68859979560210c310db6ec6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Louren=C3=A7o?= Date: Tue, 20 Sep 2022 12:00:13 -0300 Subject: [PATCH 8/8] Renamed package ids. --- icon.jpg | Bin 31732 -> 3000 bytes .../src/IdentityServer4.AspNetIdentity.csproj | 6 +++--- src/Directory.Build.targets | 12 ++++++------ ...tityServer4.EntityFramework.Storage.csproj | 7 ++++--- ...r4.EntityFramework.IntegrationTests.csproj | 4 ++-- .../IdentityServer4.EntityFramework.csproj | 8 ++++---- .../src/IdentityServer4.csproj | 6 +++--- .../src/IdentityServer4.Storage.csproj | 5 +++-- 8 files changed, 25 insertions(+), 23 deletions(-) diff --git a/icon.jpg b/icon.jpg index b87944aa11ebe1eb4c4ece857661d8e3841b6af0..766f1ba8870ff34ca6c32420de6a0bbf4ca30b79 100644 GIT binary patch literal 3000 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 Fe*z>LRowsp literal 31732 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 diff --git a/src/AspNetIdentity/src/IdentityServer4.AspNetIdentity.csproj b/src/AspNetIdentity/src/IdentityServer4.AspNetIdentity.csproj index c7450b5d0e..21ad4d5dcb 100644 --- a/src/AspNetIdentity/src/IdentityServer4.AspNetIdentity.csproj +++ b/src/AspNetIdentity/src/IdentityServer4.AspNetIdentity.csproj @@ -1,11 +1,11 @@ - IdentityServer4.AspNetIdentity + Lacuna.IdentityServer4.AspNetIdentity net6.0 ASP.NET Core Identity Integration for IdentityServer4 - Brock Allen;Dominick Baier + Brock Allen;Dominick Baier;Lacuna Software IdentityServer4.AspNetIdentity OAuth2;OAuth 2.0;OpenID Connect;Security;Identity;IdentityServer;ASP.NET Identity icon.jpg @@ -39,7 +39,7 @@ - + diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index d6d1043e05..c138cb4912 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -5,7 +5,7 @@ 6.0.8 6.0.8 - 4.1.2-* + 6.0.0-* @@ -24,11 +24,11 @@ - - - - - + + + + + diff --git a/src/EntityFramework.Storage/src/IdentityServer4.EntityFramework.Storage.csproj b/src/EntityFramework.Storage/src/IdentityServer4.EntityFramework.Storage.csproj index f2860677a3..a976f0c758 100644 --- a/src/EntityFramework.Storage/src/IdentityServer4.EntityFramework.Storage.csproj +++ b/src/EntityFramework.Storage/src/IdentityServer4.EntityFramework.Storage.csproj @@ -1,11 +1,12 @@ - IdentityServer4.EntityFramework.Storage + Lacuna.IdentityServer4.EntityFramework.Storage net6.0 EntityFramework persistence layer for IdentityServer4 - Brock Allen;Dominick Baier;Scott Brady + Brock Allen;Dominick Baier;Scott Brady;Lacuna Software + IdentityServer4.EntityFramework.Storage OAuth2;OAuth 2.0;OpenID Connect;Security;Identity;IdentityServer;EntityFramework icon.jpg https://github.com/IdentityServer/IdentityServer4 @@ -32,7 +33,7 @@ - + diff --git a/src/EntityFramework.Storage/test/IntegrationTests/IdentityServer4.EntityFramework.IntegrationTests.csproj b/src/EntityFramework.Storage/test/IntegrationTests/IdentityServer4.EntityFramework.IntegrationTests.csproj index 1da436acb8..33f602a03a 100644 --- a/src/EntityFramework.Storage/test/IntegrationTests/IdentityServer4.EntityFramework.IntegrationTests.csproj +++ b/src/EntityFramework.Storage/test/IntegrationTests/IdentityServer4.EntityFramework.IntegrationTests.csproj @@ -17,8 +17,8 @@ - - + + diff --git a/src/EntityFramework/src/IdentityServer4.EntityFramework.csproj b/src/EntityFramework/src/IdentityServer4.EntityFramework.csproj index 6a86fe7872..04198a8d51 100644 --- a/src/EntityFramework/src/IdentityServer4.EntityFramework.csproj +++ b/src/EntityFramework/src/IdentityServer4.EntityFramework.csproj @@ -1,11 +1,11 @@ - IdentityServer4.EntityFramework + Lacuna.IdentityServer4.EntityFramework net6.0 EntityFramework persistence layer for IdentityServer4 - Brock Allen;Dominick Baier;Scott Brady + Brock Allen;Dominick Baier;Scott Brady;Lacuna Software IdentityServer4.EntityFramework OAuth2;OAuth 2.0;OpenID Connect;Security;Identity;IdentityServer;EntityFramework icon.jpg @@ -33,8 +33,8 @@ - - + + diff --git a/src/IdentityServer4/src/IdentityServer4.csproj b/src/IdentityServer4/src/IdentityServer4.csproj index c00437f8ba..129ab159b6 100644 --- a/src/IdentityServer4/src/IdentityServer4.csproj +++ b/src/IdentityServer4/src/IdentityServer4.csproj @@ -1,10 +1,10 @@ - IdentityServer4 + Lacuna.IdentityServer4 net6.0 OpenID Connect and OAuth 2.0 Framework for ASP.NET Core - Brock Allen;Dominick Baier + Brock Allen;Dominick Baier;Lacuna Software IdentityServer4 OAuth2;OAuth 2.0;OpenID Connect;Security;Identity;IdentityServer icon.jpg @@ -40,7 +40,7 @@ - + diff --git a/src/Storage/src/IdentityServer4.Storage.csproj b/src/Storage/src/IdentityServer4.Storage.csproj index dbc2a6fe94..992d7e73b0 100644 --- a/src/Storage/src/IdentityServer4.Storage.csproj +++ b/src/Storage/src/IdentityServer4.Storage.csproj @@ -3,9 +3,10 @@ netstandard2.0 - IdentityServer4.Storage + Lacuna.IdentityServer4.Storage Storage interfaces and models for IdentityServer4 - Brock Allen;Dominick Baier + Brock Allen;Dominick Baier;Lacuna Software + IdentityServer4.Storage OAuth2;OAuth 2.0;OpenID Connect;Security;Identity;IdentityServer icon.jpg