diff --git a/src/EntityFramework.Storage/src/Mappers/ClientMapperProfile.cs b/src/EntityFramework.Storage/src/Mappers/ClientMapperProfile.cs index 30d537383d..5b2539cbbf 100644 --- a/src/EntityFramework.Storage/src/Mappers/ClientMapperProfile.cs +++ b/src/EntityFramework.Storage/src/Mappers/ClientMapperProfile.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Security.Claims; using AutoMapper; +using IdentityServer4.Models; namespace IdentityServer4.EntityFramework.Mappers { @@ -38,8 +39,8 @@ public ClientMapperProfile() .ReverseMap() .ForMember(dest => dest.Provider, opt => opt.MapFrom(src => src)); - CreateMap(MemberList.None) - .ConstructUsing(src => new Claim(src.Type, src.Value)) + CreateMap(MemberList.None) + .ConstructUsing(src => new ClientClaim(src.Type, src.Value, ClaimValueTypes.String)) .ReverseMap(); CreateMap() diff --git a/src/EntityFramework.Storage/test/IntegrationTests/Stores/ClientStoreTests.cs b/src/EntityFramework.Storage/test/IntegrationTests/Stores/ClientStoreTests.cs index bc7c548b38..2a60eb168b 100644 --- a/src/EntityFramework.Storage/test/IntegrationTests/Stores/ClientStoreTests.cs +++ b/src/EntityFramework.Storage/test/IntegrationTests/Stores/ClientStoreTests.cs @@ -77,7 +77,7 @@ public async Task FindClientByIdAsync_WhenClientExistsWithCollections_ExpectClie AllowedCorsOrigins = {"https://localhost"}, AllowedGrantTypes = GrantTypes.HybridAndClientCredentials, AllowedScopes = {"openid", "profile", "api1"}, - Claims = {new Claim("test", "value")}, + Claims = {new ClientClaim("test", "value")}, ClientSecrets = {new Secret("secret".Sha256())}, IdentityProviderRestrictions = {"AD"}, PostLogoutRedirectUris = {"https://locahost/signout-callback"}, diff --git a/src/IdentityServer4/host/appsettings.json b/src/IdentityServer4/host/appsettings.json index 40c9e84d48..b9419d469c 100644 --- a/src/IdentityServer4/host/appsettings.json +++ b/src/IdentityServer4/host/appsettings.json @@ -5,7 +5,17 @@ "ClientSecrets": [ { "Value": "K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=" } ], "AllowedGrantTypes": [ "client_credentials" ], "AllowedScopes": [ "api1", "api2.read_only" ], - "Properties": {"foo": "bar" } + "Properties": { "foo": "bar" }, + "Claims": [ + { + "type": "c1", + "value": "c1value" + }, + { + "type": "c2", + "value": "c2value" + } + ] }, { "ClientId": "hybrid", diff --git a/src/IdentityServer4/src/Validation/Models/ValidatedRequest.cs b/src/IdentityServer4/src/Validation/Models/ValidatedRequest.cs index 760462bf35..dfc1532574 100644 --- a/src/IdentityServer4/src/Validation/Models/ValidatedRequest.cs +++ b/src/IdentityServer4/src/Validation/Models/ValidatedRequest.cs @@ -124,7 +124,7 @@ public void SetClient(Client client, ParsedSecret secret = null, string confirma AccessTokenLifetime = client.AccessTokenLifetime; AccessTokenType = client.AccessTokenType; - ClientClaims = client.Claims.Select(c => new Claim(c.Type, c.Value, c.ValueType, c.Issuer)).ToList(); + ClientClaims = client.Claims.Select(c => new Claim(c.Type, c.Value, c.ValueType)).ToList(); } } } \ No newline at end of file diff --git a/src/IdentityServer4/test/IdentityServer.UnitTests/Services/Default/DefaultClaimsServiceTests.cs b/src/IdentityServer4/test/IdentityServer.UnitTests/Services/Default/DefaultClaimsServiceTests.cs index bcea8f8b2d..ee3cfc850f 100644 --- a/src/IdentityServer4/test/IdentityServer.UnitTests/Services/Default/DefaultClaimsServiceTests.cs +++ b/src/IdentityServer4/test/IdentityServer.UnitTests/Services/Default/DefaultClaimsServiceTests.cs @@ -31,7 +31,7 @@ public DefaultClaimsServiceTests() _client = new Client { ClientId = "client", - Claims = { new Claim("some_claim", "some_claim_value") } + Claims = { new ClientClaim("some_claim", "some_claim_value") } }; _user = new IdentityServerUser("bob") diff --git a/src/Storage/src/Models/Client.cs b/src/Storage/src/Models/Client.cs index a9bd3c5465..f73d5956fc 100644 --- a/src/Storage/src/Models/Client.cs +++ b/src/Storage/src/Models/Client.cs @@ -242,7 +242,7 @@ public ICollection AllowedGrantTypes /// /// The claims. /// - public ICollection Claims { get; set; } = new HashSet(new ClaimComparer()); + public ICollection Claims { get; set; } = new HashSet(); /// /// Gets or sets a value indicating whether client claims should be always included in the access tokens - or only for client credentials flow. diff --git a/src/Storage/src/Models/ClientClaim.cs b/src/Storage/src/Models/ClientClaim.cs new file mode 100644 index 0000000000..b71d5b99df --- /dev/null +++ b/src/Storage/src/Models/ClientClaim.cs @@ -0,0 +1,89 @@ +// 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; +using System.Security.Claims; + +namespace IdentityServer4.Models +{ + /// + /// A client claim + /// + public class ClientClaim + { + /// + /// The claim type + /// + public string Type { get; set; } + + /// + /// The claim value + /// + public string Value { get; set; } + + /// + /// The claim value type + /// + public string ValueType { get; set; } = ClaimValueTypes.String; + + /// + /// ctor + /// + public ClientClaim() + { + } + + /// + /// ctor + /// + /// + /// + public ClientClaim(string type, string value) + { + Type = type; + Value = value; + } + + /// + /// ctor + /// + /// + /// + /// + public ClientClaim(string type, string value, string valueType) + { + Type = type; + Value = value; + ValueType = valueType; + } + + /// + public override int GetHashCode() + { + unchecked + { + int hash = 17; + + hash = hash * 23 + Value.GetHashCode(); + hash = hash * 23 + Type.GetHashCode(); + hash = hash * 23 + ValueType.GetHashCode(); + return hash; + } + } + + /// + public override bool Equals(object obj) + { + if (obj is null) return false; + if (obj is ClientClaim c) + { + return (string.Equals(Type, c.Type, StringComparison.Ordinal) && + string.Equals(Value, c.Value, StringComparison.Ordinal) && + string.Equals(ValueType, c.ValueType, StringComparison.Ordinal)); + } + + return false; + } + } +} \ No newline at end of file