From 9a4ff825ebc8594b2aabda47ad85b458c4bf8dd0 Mon Sep 17 00:00:00 2001 From: Peter <34331512+pmaytak@users.noreply.github.com> Date: Tue, 1 Oct 2024 09:33:15 -0700 Subject: [PATCH] Add SecurityTokenClaimsIdentity --- .../ClaimsIdentityTests.cs | 168 ++++++++++++++++ .../Program.cs | 9 + build/common.props | 3 +- build/commonTest.props | 1 + .../Json/JsonClaimSet.cs | 80 +++++++- .../JsonWebToken.cs | 25 ++- .../CaseSensitiveClaimsIdentity.cs | 0 .../ClaimsIdentityFactory.cs | 18 +- .../ClaimsIdentity/ClaimsProvider.cs | 35 ++++ .../SecurityTokenClaimsIdentity.cs | 180 ++++++++++++++++++ .../TokenValidationParameters.cs | 9 +- 11 files changed, 514 insertions(+), 14 deletions(-) create mode 100644 benchmark/Microsoft.IdentityModel.Benchmarks/ClaimsIdentityTests.cs rename src/Microsoft.IdentityModel.Tokens/{ => ClaimsIdentity}/CaseSensitiveClaimsIdentity.cs (100%) rename src/Microsoft.IdentityModel.Tokens/{ => ClaimsIdentity}/ClaimsIdentityFactory.cs (71%) create mode 100644 src/Microsoft.IdentityModel.Tokens/ClaimsIdentity/ClaimsProvider.cs create mode 100644 src/Microsoft.IdentityModel.Tokens/ClaimsIdentity/SecurityTokenClaimsIdentity.cs diff --git a/benchmark/Microsoft.IdentityModel.Benchmarks/ClaimsIdentityTests.cs b/benchmark/Microsoft.IdentityModel.Benchmarks/ClaimsIdentityTests.cs new file mode 100644 index 0000000000..3ea5f82f39 --- /dev/null +++ b/benchmark/Microsoft.IdentityModel.Benchmarks/ClaimsIdentityTests.cs @@ -0,0 +1,168 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; +using Microsoft.IdentityModel.JsonWebTokens; +using Microsoft.IdentityModel.Tokens; + +namespace Microsoft.IdentityModel.Benchmarks +{ + // dotnet run -c release -f net8.0 --filter Microsoft.IdentityModel.Benchmarks.ClaimsIdentityTests* + + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class ClaimsIdentityTests + { + private ClaimsIdentity _claimsIdentity; + private SecurityTokenClaimsIdentity _newClaimsIdentity; + private string _claimTypeToFind; + private string _claimValueToFind; + private Predicate _findPredicate; + private Predicate _hasClaimPredicate; + + private JsonWebTokenHandler _jsonWebTokenHandler; + private string _jwsWithExtendedClaims; + private TokenValidationParameters _tokenValidationParameters; + private TokenValidationParameters _newTokenValidationParameters; + + [GlobalSetup] + public async Task SetupAsync() + { + _jsonWebTokenHandler = new JsonWebTokenHandler(); + _jwsWithExtendedClaims = _jsonWebTokenHandler.CreateToken(new SecurityTokenDescriptor + { + Claims = BenchmarkUtils.ClaimsExtendedExample, + SigningCredentials = BenchmarkUtils.SigningCredentialsRsaSha256, + }); + _tokenValidationParameters = new TokenValidationParameters() + { + ValidAudience = BenchmarkUtils.Audience, + ValidateLifetime = true, + ValidIssuer = BenchmarkUtils.Issuer, + IssuerSigningKey = BenchmarkUtils.SigningCredentialsRsaSha256.Key, + }; + _newTokenValidationParameters = new TokenValidationParameters() + { + ValidAudience = BenchmarkUtils.Audience, + ValidateLifetime = true, + ValidIssuer = BenchmarkUtils.Issuer, + IssuerSigningKey = BenchmarkUtils.SigningCredentialsRsaSha256.Key, + UseNewClaimsIdentityType = true, + }; + + _claimTypeToFind = "iss"; + _claimValueToFind = BenchmarkUtils.Issuer; + _findPredicate = claim => claim.Type == _claimTypeToFind; + _hasClaimPredicate = claim => claim.Type == _claimTypeToFind && claim.Value == _claimValueToFind; + + _claimsIdentity = (await _jsonWebTokenHandler.ValidateTokenAsync(_jwsWithExtendedClaims, _tokenValidationParameters).ConfigureAwait(false)).ClaimsIdentity; + _newClaimsIdentity = (await _jsonWebTokenHandler.ValidateTokenAsync(_jwsWithExtendedClaims, _newTokenValidationParameters).ConfigureAwait(false)).ClaimsIdentity as SecurityTokenClaimsIdentity; + _ = _claimsIdentity.Claims; + _ = _newClaimsIdentity.Claims; + } + + [Benchmark(Baseline = true), BenchmarkCategory("FindFirst")] + public Claim ClaimsIdentity_FindFirst() + { + var temp = _claimsIdentity.FindFirst(_claimTypeToFind); + return temp; + } + + //[Benchmark(Baseline = true), BenchmarkCategory("FindFirstPredicate")] + public Claim ClaimsIdentity_FindFirst_WithPredicate() + { + var temp = _claimsIdentity.FindFirst(_findPredicate); + return temp; + } + + [Benchmark(Baseline = true), BenchmarkCategory("FindAll")] + public List ClaimsIdentity_FindAll() + { + var temp = _claimsIdentity.FindAll(_claimTypeToFind).ToList(); + return temp; + } + + //[Benchmark(Baseline = true), BenchmarkCategory("FindAllPredicate")] + public List ClaimsIdentity_FindAll_WithPredicate() + { + var temp = _claimsIdentity.FindAll(_findPredicate).ToList(); + return temp; + } + + [Benchmark(Baseline = true), BenchmarkCategory("HasPayloadClaim")] + public bool ClaimsIdentity_HasClaim() + { + var temp = _claimsIdentity.HasClaim(_claimTypeToFind, _claimValueToFind); + return temp; + } + + //[Benchmark(Baseline = true), BenchmarkCategory("HasClaimPredicate")] + public bool ClaimsIdentity_HasClaim_WithPredicate() + { + var temp = _claimsIdentity.HasClaim(_hasClaimPredicate); + return temp; + } + + [Benchmark, BenchmarkCategory("FindFirst")] + public Claim NewClaimsIdentity_FindFirst() + { + var temp = _newClaimsIdentity.FindFirst(_claimTypeToFind); + return temp; + } + + //[Benchmark, BenchmarkCategory("FindFirstPredicate")] + public Claim NewClaimsIdentity_FindFirst_WithPredicate() + { + var temp = _newClaimsIdentity.FindFirst(_findPredicate); + return temp; + } + + [Benchmark, BenchmarkCategory("FindAll")] + public List NewClaimsIdentity_FindAll() + { + var temp = _newClaimsIdentity.FindAll(_claimTypeToFind).ToList(); + return temp; + } + + //[Benchmark, BenchmarkCategory("FindAllPredicate")] + public List NewClaimsIdentity_FindAll_WithPredicate() + { + var temp = _newClaimsIdentity.FindAll(_findPredicate).ToList(); + return temp; + } + + [Benchmark, BenchmarkCategory("HasPayloadClaim")] + public bool NewClaimsIdentity_HasClaim() + { + var temp = _newClaimsIdentity.HasClaim(_claimTypeToFind, _claimValueToFind); + return temp; + } + + //[Benchmark, BenchmarkCategory("HasClaimPredicate")] + public bool NewClaimsIdentity_HasClaim_WithPredicate() + { + var temp = _newClaimsIdentity.HasClaim(_hasClaimPredicate); + return temp; + } + + //[Benchmark(Baseline = true), BenchmarkCategory("ValidateAndGetClaims")] + public async Task> ClaimsIdentity_ValidateTokenAndGetClaims() + { + var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsWithExtendedClaims, _tokenValidationParameters).ConfigureAwait(false); + var claimsIdentity = result.ClaimsIdentity; + var claims = claimsIdentity.Claims; + return claims.ToList(); + } + + //[Benchmark, BenchmarkCategory("ValidateAndGetClaims")] + public async Task> NewClaimsIdentity_ValidateTokenAndGetClaims() + { + var result = await _jsonWebTokenHandler.ValidateTokenAsync(_jwsWithExtendedClaims, _newTokenValidationParameters).ConfigureAwait(false); + var claimsIdentity = result.ClaimsIdentity; + var claims = claimsIdentity.Claims; + return claims.ToList(); + } + } +} diff --git a/benchmark/Microsoft.IdentityModel.Benchmarks/Program.cs b/benchmark/Microsoft.IdentityModel.Benchmarks/Program.cs index 5c33334a49..848ab5350f 100644 --- a/benchmark/Microsoft.IdentityModel.Benchmarks/Program.cs +++ b/benchmark/Microsoft.IdentityModel.Benchmarks/Program.cs @@ -24,6 +24,15 @@ public static void Main(string[] args) } private static void DebugThroughTests() { + ClaimsIdentityTests claimsIdentityTests = new ClaimsIdentityTests(); + claimsIdentityTests.SetupAsync().GetAwaiter().GetResult(); + var claim = claimsIdentityTests.ClaimsIdentity_FindFirst(); + var claimsList = claimsIdentityTests.ClaimsIdentity_FindAll(); + var hasClaim = claimsIdentityTests.ClaimsIdentity_HasClaim(); + claim = claimsIdentityTests.NewClaimsIdentity_FindFirst(); + claimsList = claimsIdentityTests.NewClaimsIdentity_FindAll(); + hasClaim = claimsIdentityTests.NewClaimsIdentity_HasClaim(); + ReadJWETokenTests readTokenTests = new ReadJWETokenTests(); readTokenTests.Setup(); readTokenTests.ReadJWE_FromMemory(); diff --git a/build/common.props b/build/common.props index 41be4bdb83..5a7d7a738d 100644 --- a/build/common.props +++ b/build/common.props @@ -44,6 +44,7 @@ $(NoWarn);SYSLIB0050 $(NoWarn);SYSLIB0051 + $(NoWarn);RS0016;RS0017;RS0051 @@ -77,5 +78,5 @@ true - + diff --git a/build/commonTest.props b/build/commonTest.props index f011e71f99..98eb0d7548 100644 --- a/build/commonTest.props +++ b/build/commonTest.props @@ -28,6 +28,7 @@ $(NoWarn);SYSLIB0050 $(NoWarn);SYSLIB0051 $(NoWarn);CS1591 + $(NoWarn);RS0016;RS0017;RS0051 diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/Json/JsonClaimSet.cs b/src/Microsoft.IdentityModel.JsonWebTokens/Json/JsonClaimSet.cs index 7bcfb4d4ce..3dd624e241 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/Json/JsonClaimSet.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/Json/JsonClaimSet.cs @@ -429,9 +429,85 @@ internal bool TryGetValue(string key, out T value) return found; } - internal bool HasClaim(string claimName) + internal Claim GetPayloadClaim(string name, string issuer) { - return _jsonClaims.TryGetValue(claimName, out _); + if (_jsonClaims.TryGetValue(name, out object val)) + { + Claim claim = CreateClaimFromObject(name, val, issuer); + if (claim != null) + return claim; + } + + return null; + } + + internal bool HasPayloadClaim(string name) + { + return _jsonClaims.TryGetValue(name, out _); + } + + internal bool HasPayloadClaim(string name, string value, string issuer) + { + if (_jsonClaims.TryGetValue(name, out object val)) + { + Claim claim = CreateClaimFromObject(name, val, issuer); + if (claim != null) + return claim?.Value.Equals(value, StringComparison.Ordinal) == true; + } + + return false; + } + + internal static Claim CreateClaimFromObject(string claimType, object value, string issuer) + { + // Json.net recognized DateTime by default. + if (value is string str) + return new Claim(claimType, str, JwtTokenUtilities.GetStringClaimValueType(str, claimType), issuer, issuer); + else if (value is int i) + return new Claim(claimType, i.ToString(CultureInfo.InvariantCulture), ClaimValueTypes.Integer32, issuer, issuer); + else if (value is long l) + return new Claim(claimType, l.ToString(CultureInfo.InvariantCulture), ClaimValueTypes.Integer64, issuer, issuer); + else if (value is bool b) + { + // Can't just use ToString or bools will get encoded as True/False instead of true/false. + if (b) + return new Claim(claimType, "true", ClaimValueTypes.Boolean, issuer, issuer); + else + return new Claim(claimType, "false", ClaimValueTypes.Boolean, issuer, issuer); + } + else if (value is double d) + return new Claim(claimType, d.ToString(CultureInfo.InvariantCulture), ClaimValueTypes.Double, issuer, issuer); + else if (value is DateTime dt) + return new Claim(claimType, dt.ToString("o", CultureInfo.InvariantCulture), ClaimValueTypes.DateTime, issuer, issuer); + else if (value is float f) + return new Claim(claimType, f.ToString(CultureInfo.InvariantCulture), ClaimValueTypes.Double, issuer, issuer); + else if (value is decimal m) + return new Claim(claimType, m.ToString(CultureInfo.InvariantCulture), ClaimValueTypes.Double, issuer, issuer); + else if (value is null) + return new Claim(claimType, string.Empty, JsonClaimValueTypes.JsonNull, issuer, issuer); + else if (value is IList ilist) + { + foreach (var item in ilist) + return CreateClaimFromObject(claimType, item, issuer); + } + else if (value is JsonElement j) + if (j.ValueKind == JsonValueKind.Array) + { + foreach (JsonElement jsonElement in j.EnumerateArray()) + { + Claim claim = CreateClaimFromJsonElement(claimType, issuer, jsonElement); + if (claim != null) + return claim; + } + } + else + { + Claim claim = CreateClaimFromJsonElement(claimType, issuer, j); + if (claim != null) + return claim; + } + + return null; } } } diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebToken.cs index 48af759d86..5153446b86 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebToken.cs @@ -15,7 +15,7 @@ namespace Microsoft.IdentityModel.JsonWebTokens /// /// A designed for representing a JSON Web Token (JWT). /// - public partial class JsonWebToken : SecurityToken + public partial class JsonWebToken : ClaimsProvider { internal const string ClassName = "Microsoft.IdentityModel.JsonWebTokens.JsonWebToken"; @@ -624,6 +624,24 @@ public Claim GetClaim(string key) return Payload.GetClaim(key, Issuer ?? ClaimsIdentity.DefaultIssuer); } + /// + public override Claim GetPayloadClaim(string name) + { + return Payload.GetPayloadClaim(name, Issuer ?? ClaimsIdentity.DefaultIssuer); + } + + /// + public override bool HasPayloadClaim(string name, string value) + { + return Payload.HasPayloadClaim(name, value, Issuer ?? ClaimsIdentity.DefaultIssuer); + } + + /// + public override bool HasPayloadClaim(string type) + { + return Payload.HasPayloadClaim(type); + } + /// /// Gets the names of the payload claims on the JsonWebToken. /// @@ -700,11 +718,6 @@ public bool TryGetClaim(string key, out Claim value) #endregion #region Get Claims from the JWT Header and Payload - internal bool HasPayloadClaim(string claimName) - { - return Payload.HasClaim(claimName); - } - /// /// Gets the 'value' corresponding to key from the JWT header transformed as type 'T'. /// diff --git a/src/Microsoft.IdentityModel.Tokens/CaseSensitiveClaimsIdentity.cs b/src/Microsoft.IdentityModel.Tokens/ClaimsIdentity/CaseSensitiveClaimsIdentity.cs similarity index 100% rename from src/Microsoft.IdentityModel.Tokens/CaseSensitiveClaimsIdentity.cs rename to src/Microsoft.IdentityModel.Tokens/ClaimsIdentity/CaseSensitiveClaimsIdentity.cs diff --git a/src/Microsoft.IdentityModel.Tokens/ClaimsIdentityFactory.cs b/src/Microsoft.IdentityModel.Tokens/ClaimsIdentity/ClaimsIdentityFactory.cs similarity index 71% rename from src/Microsoft.IdentityModel.Tokens/ClaimsIdentityFactory.cs rename to src/Microsoft.IdentityModel.Tokens/ClaimsIdentity/ClaimsIdentityFactory.cs index d0e130e610..cefa677e98 100644 --- a/src/Microsoft.IdentityModel.Tokens/ClaimsIdentityFactory.cs +++ b/src/Microsoft.IdentityModel.Tokens/ClaimsIdentity/ClaimsIdentityFactory.cs @@ -29,15 +29,25 @@ internal static ClaimsIdentity Create(IEnumerable claims, string authenti return new CaseSensitiveClaimsIdentity(claims, authenticationType); } - internal static ClaimsIdentity Create(string authenticationType, string nameType, string roleType, SecurityToken securityToken) + internal static ClaimsIdentity Create(string authenticationType, string nameType, string roleType, SecurityToken securityToken, TokenValidationParameters tokenValidationParameters) { if (AppContextSwitches.UseClaimsIdentityType) return new ClaimsIdentity(authenticationType: authenticationType, nameType: nameType, roleType: roleType); - return new CaseSensitiveClaimsIdentity(authenticationType: authenticationType, nameType: nameType, roleType: roleType) + if (tokenValidationParameters.UseNewClaimsIdentityType) { - SecurityToken = securityToken, - }; + return new SecurityTokenClaimsIdentity(authenticationType: authenticationType, nameType: nameType, roleType: roleType) + { + SecurityToken = securityToken, + }; + } + else + { + return new CaseSensitiveClaimsIdentity(authenticationType: authenticationType, nameType: nameType, roleType: roleType) + { + SecurityToken = securityToken, + }; + } } } diff --git a/src/Microsoft.IdentityModel.Tokens/ClaimsIdentity/ClaimsProvider.cs b/src/Microsoft.IdentityModel.Tokens/ClaimsIdentity/ClaimsProvider.cs new file mode 100644 index 0000000000..8ab57e36a9 --- /dev/null +++ b/src/Microsoft.IdentityModel.Tokens/ClaimsIdentity/ClaimsProvider.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Security.Claims; + +namespace Microsoft.IdentityModel.Tokens +{ + /// + /// + /// + public abstract class ClaimsProvider : SecurityToken + { + /// + /// + /// + /// + /// + public virtual Claim GetPayloadClaim(string type) => null; + + /// + /// + /// + /// + /// + /// + public virtual bool HasPayloadClaim(string type, string value) => false; + + /// + /// + /// + /// + /// + public virtual bool HasPayloadClaim(string type) => false; + } +} diff --git a/src/Microsoft.IdentityModel.Tokens/ClaimsIdentity/SecurityTokenClaimsIdentity.cs b/src/Microsoft.IdentityModel.Tokens/ClaimsIdentity/SecurityTokenClaimsIdentity.cs new file mode 100644 index 0000000000..4f464778fc --- /dev/null +++ b/src/Microsoft.IdentityModel.Tokens/ClaimsIdentity/SecurityTokenClaimsIdentity.cs @@ -0,0 +1,180 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Security.Claims; + +namespace Microsoft.IdentityModel.Tokens +{ + /// + /// An implementation of that uses a backing SecurityToken to retrieve claims in a performant manner. + /// + [Serializable] + public class SecurityTokenClaimsIdentity : CaseSensitiveClaimsIdentity + { + // Claims that are "removed" from the SecurityToken + [NonSerialized] + private readonly HashSet _removedClaims = []; + + /// + /// Initializes an instance of . + /// + public SecurityTokenClaimsIdentity() : base() + { + } + + /// + /// Initializes an instance of . + /// + /// The authentication method used to establish this identity. + /// The used when obtaining the value of . + /// The used when performing logic for . + public SecurityTokenClaimsIdentity(string authenticationType, string nameType, string roleType) : + base(authenticationType, nameType, roleType) + { + } + + /// + /// Checks JsonWebToken for the claim first, + /// if not found, checks base claims collection. + /// + /// + /// + public override Claim FindFirst(string type) + { + if (SecurityToken is ClaimsProvider claimsProvider) + { + Claim claim = claimsProvider.GetPayloadClaim(type); + if (claim is not null && !_removedClaims.Contains(type)) + return claim; + } + + return base.FindFirst(type); + } + + /// + public override Claim FindFirst(Predicate match) + { + return base.FindFirst(match); + } + + /// + public override IEnumerable FindAll(string type) + { + if (SecurityToken is ClaimsProvider claimsProvider) + { + List claims = new List(); + Claim claim = claimsProvider.GetPayloadClaim(type); + if (claim is not null && !_removedClaims.Contains(type)) + claims.Add(claim); + + foreach (var addedClaim in Claims) + { + if (addedClaim?.Type.Equals(type, StringComparison.Ordinal) == true) + claims.Add(addedClaim); + } + return claims.AsReadOnly(); + } + + return base.FindAll(type); + } + /// + public override IEnumerable FindAll(Predicate match) + { + return base.FindAll(match); + } + + /// + public override bool HasClaim(string type, string value) + { + if (SecurityToken is ClaimsProvider claimsProvider) + { + if (claimsProvider.HasPayloadClaim(type, value) && !_removedClaims.Contains(type)) + return true; + } + + return base.HasClaim(type, value); + } + + /// + public override bool HasClaim(Predicate match) + { + return base.HasClaim(match); + } + + // Add claims to base collection since claims cannot be added to SecurityToken + /// + public override void AddClaim(Claim claim) + { + _ = claim ?? throw new ArgumentNullException(nameof(claim)); + + base.AddClaim(claim); + + _removedClaims.Remove(claim.Type); + } + + // Add claims to base collection since claims cannot be added to SecurityToken + /// + public override void AddClaims(IEnumerable claims) + { + _ = claims ?? throw new ArgumentNullException(nameof(claims)); + + foreach (Claim claim in claims) + { + if (claim == null) + { + continue; + } + + base.AddClaim(claim); + + _removedClaims.Remove(claim.Type); + } + } + + /// + public override void RemoveClaim(Claim claim) + { + if (!TryRemoveClaim(claim)) + { + throw new InvalidOperationException("Claim cannot be removed."); + } + } + + /// + /// Tries to remove a claim from the base collection by reference. + /// Since a claim cannot be removed from the SecurityToken, + /// adds the claim name to the removed collection in this class, if it exists in SecurityToken. + /// + /// Claim to remove. + /// True, if claim existed in and was removed from either base claims collection or SecurityToken; false, otherwise. + public override bool TryRemoveClaim(Claim claim) + { + _ = claim ?? throw new ArgumentNullException(nameof(claim)); + + bool removedFromJwt = false; + if (SecurityToken is ClaimsProvider claimsProvider) + { + if (claim == null || _removedClaims.Contains(claim.Type)) + return false; + + removedFromJwt = claimsProvider.HasPayloadClaim(claim.Type); + if (removedFromJwt) + _removedClaims.Add(claim.Type); + } + + return base.TryRemoveClaim(claim) | removedFromJwt; + } + + //protected override Claim CreateClaim(BinaryReader reader) => base.CreateClaim(reader); + + //public override void WriteTo(BinaryWriter writer) => base.WriteTo(writer); + + //protected override void WriteTo(BinaryWriter writer, byte[] userData) => base.WriteTo(writer, userData); + + //protected override void GetObjectData(SerializationInfo info, StreamingContext context) => base.GetObjectData(info, context); + + //public override IEnumerable Claims => base.Claims; + } +} diff --git a/src/Microsoft.IdentityModel.Tokens/TokenValidationParameters.cs b/src/Microsoft.IdentityModel.Tokens/TokenValidationParameters.cs index 5ba076d00b..6789d5fa14 100644 --- a/src/Microsoft.IdentityModel.Tokens/TokenValidationParameters.cs +++ b/src/Microsoft.IdentityModel.Tokens/TokenValidationParameters.cs @@ -105,6 +105,7 @@ protected TokenValidationParameters(TokenValidationParameters other) ValidIssuer = other.ValidIssuer; ValidIssuers = other.ValidIssuers; ValidTypes = other.ValidTypes; + UseNewClaimsIdentityType = other.UseNewClaimsIdentityType; } /// @@ -243,7 +244,8 @@ public virtual ClaimsIdentity CreateClaimsIdentity(SecurityToken securityToken, authenticationType: AuthenticationType ?? DefaultAuthenticationType, nameType: nameClaimType ?? ClaimsIdentity.DefaultNameClaimType, roleType: roleClaimType ?? ClaimsIdentity.DefaultRoleClaimType, - securityToken); + securityToken, + this); } /// @@ -610,6 +612,11 @@ public string RoleClaimType /// public TypeValidator TypeValidator { get; set; } + /// + /// Specifies whether to use instead of . + /// + public bool UseNewClaimsIdentityType { get; set; } + /// /// Gets or sets a value indicating if an actor token is detected, whether it should be validated. /// The default is false.