From 04d0d137f0b2099ee4aa7fdee8881ce6506f92e0 Mon Sep 17 00:00:00 2001 From: msbw2 Date: Tue, 12 Nov 2024 11:52:32 -0800 Subject: [PATCH] Use SecurityTokenDescriptor when creating tokens (#2991) --- .../InternalAPI.Unshipped.txt | 4 + .../JsonWebTokenHandler.CreateToken.cs | 247 +++++++----------- .../JwtSecurityTokenHandler.cs | 222 ++++++---------- 3 files changed, 185 insertions(+), 288 deletions(-) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt b/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt index 81abc18294..cb23d777b2 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt +++ b/src/Microsoft.IdentityModel.JsonWebTokens/InternalAPI.Unshipped.txt @@ -1,4 +1,8 @@ +static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.CreateToken(string payload, Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor tokenDescriptor) -> string static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.EncryptToken(byte[] innerTokenUtf8Bytes, Microsoft.IdentityModel.Tokens.EncryptingCredentials encryptingCredentials, string compressionAlgorithm, System.Collections.Generic.IDictionary additionalHeaderClaims, string tokenType, bool includeKeyIdInHeader) -> string +static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.EncryptToken(byte[] innerTokenUtf8Bytes, Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor tokenDescriptor) -> string static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.WriteJweHeader(Microsoft.IdentityModel.Tokens.EncryptingCredentials encryptingCredentials, string compressionAlgorithm, string tokenType, System.Collections.Generic.IDictionary jweHeaderClaims, bool includeKeyIdInHeader) -> byte[] +static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.WriteJweHeader(Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor tokenDescriptor) -> byte[] +static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.WriteJwsHeader(ref System.Text.Json.Utf8JsonWriter writer, Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor tokenDescriptor) -> void static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.WriteJwsHeader(ref System.Text.Json.Utf8JsonWriter writer, Microsoft.IdentityModel.Tokens.SigningCredentials signingCredentials, Microsoft.IdentityModel.Tokens.EncryptingCredentials encryptingCredentials, System.Collections.Generic.IDictionary jweHeaderClaims, System.Collections.Generic.IDictionary jwsHeaderClaims, string tokenType, bool includeKeyIdInHeader) -> void static Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.StackFrames.IssuerValidatorThrew -> System.Diagnostics.StackFrame diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.CreateToken.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.CreateToken.cs index efd18ff18d..c05ec8bce1 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.CreateToken.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.CreateToken.cs @@ -25,6 +25,8 @@ namespace Microsoft.IdentityModel.JsonWebTokens /// This partial class is focused on TokenCreation. public partial class JsonWebTokenHandler : TokenHandler { + private static readonly SecurityTokenDescriptor s_emptyTokenDescriptor = new(); + /// /// Creates an unsigned JSON Web Signature (JWS). /// @@ -35,14 +37,7 @@ public virtual string CreateToken(string payload) { _ = payload ?? throw LogHelper.LogArgumentNullException(nameof(payload)); - return CreateToken( - payload, - null, - null, - null, - null, - null, - null); + return CreateToken(payload, s_emptyTokenDescriptor); } /// @@ -60,13 +55,7 @@ public virtual string CreateToken( _ = payload ?? throw LogHelper.LogArgumentNullException(nameof(payload)); _ = additionalHeaderClaims ?? throw LogHelper.LogArgumentNullException(nameof(additionalHeaderClaims)); - return CreateToken(payload, - null, - null, - null, - additionalHeaderClaims, - null, - null); + return CreateToken(payload, new SecurityTokenDescriptor { AdditionalHeaderClaims = additionalHeaderClaims }); } /// @@ -84,14 +73,7 @@ public virtual string CreateToken( _ = payload ?? throw LogHelper.LogArgumentNullException(nameof(payload)); _ = signingCredentials ?? throw LogHelper.LogArgumentNullException(nameof(signingCredentials)); - return CreateToken( - payload, - signingCredentials, - null, - null, - null, - null, - null); + return CreateToken(payload, new SecurityTokenDescriptor { SigningCredentials = signingCredentials }); } /// @@ -116,14 +98,7 @@ public virtual string CreateToken( _ = signingCredentials ?? throw LogHelper.LogArgumentNullException(nameof(signingCredentials)); _ = additionalHeaderClaims ?? throw LogHelper.LogArgumentNullException(nameof(additionalHeaderClaims)); - return CreateToken( - payload, - signingCredentials, - null, - null, - additionalHeaderClaims, - null, - null); + return CreateToken(payload, new SecurityTokenDescriptor { SigningCredentials = signingCredentials, AdditionalHeaderClaims = additionalHeaderClaims }); } /// @@ -189,14 +164,7 @@ internal static string CreateToken( { writer = new(utf8ByteMemoryStream, new JsonWriterOptions { Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping }); - WriteJwsHeader( - ref writer, - tokenDescriptor.SigningCredentials, - tokenDescriptor.EncryptingCredentials, - tokenDescriptor.AdditionalHeaderClaims, - tokenDescriptor.AdditionalInnerHeaderClaims, - tokenDescriptor.TokenType, - tokenDescriptor.IncludeKeyIdInHeader); + WriteJwsHeader(ref writer, tokenDescriptor); // mark length of jwt header int headerLength = (int)utf8ByteMemoryStream.Length; @@ -253,11 +221,7 @@ int sizeOfEncodedHeaderAndPayloadAsciiBytes { return EncryptToken( Encoding.UTF8.GetBytes(encodedChars, 0, sizeOfEncodedHeader + sizeOfEncodedPayload + sizeOfEncodedSignature + 2), - tokenDescriptor.EncryptingCredentials, - tokenDescriptor.CompressionAlgorithm, - tokenDescriptor.AdditionalHeaderClaims, - tokenDescriptor.TokenType, - true); + tokenDescriptor); } else { @@ -293,14 +257,7 @@ public virtual string CreateToken( _ = payload ?? throw LogHelper.LogArgumentNullException(nameof(payload)); _ = encryptingCredentials ?? throw LogHelper.LogArgumentNullException(nameof(encryptingCredentials)); - return CreateToken( - payload, - null, - encryptingCredentials, - null, - null, - null, - null); + return CreateToken(payload, new SecurityTokenDescriptor { EncryptingCredentials = encryptingCredentials }); } /// @@ -325,14 +282,7 @@ public virtual string CreateToken( _ = encryptingCredentials ?? throw LogHelper.LogArgumentNullException(nameof(encryptingCredentials)); _ = additionalHeaderClaims ?? throw LogHelper.LogArgumentNullException(nameof(additionalHeaderClaims)); - return CreateToken( - payload, - null, - encryptingCredentials, - null, - additionalHeaderClaims, - null, - null); + return CreateToken(payload, new SecurityTokenDescriptor { EncryptingCredentials = encryptingCredentials, AdditionalHeaderClaims = additionalHeaderClaims }); } /// @@ -354,14 +304,7 @@ public virtual string CreateToken( _ = signingCredentials ?? throw LogHelper.LogArgumentNullException(nameof(signingCredentials)); _ = encryptingCredentials ?? throw LogHelper.LogArgumentNullException(nameof(encryptingCredentials)); - return CreateToken( - payload, - signingCredentials, - encryptingCredentials, - null, - null, - null, - null); + return CreateToken(payload, new SecurityTokenDescriptor { SigningCredentials = signingCredentials, EncryptingCredentials = encryptingCredentials }); } /// @@ -390,14 +333,7 @@ public virtual string CreateToken( _ = encryptingCredentials ?? throw LogHelper.LogArgumentNullException(nameof(encryptingCredentials)); _ = additionalHeaderClaims ?? throw LogHelper.LogArgumentNullException(nameof(additionalHeaderClaims)); - return CreateToken( - payload, - signingCredentials, - encryptingCredentials, - null, - additionalHeaderClaims, - null, - null); + return CreateToken(payload, new SecurityTokenDescriptor { SigningCredentials = signingCredentials, EncryptingCredentials = encryptingCredentials, AdditionalHeaderClaims = additionalHeaderClaims }); } /// @@ -422,14 +358,7 @@ public virtual string CreateToken( _ = encryptingCredentials ?? throw LogHelper.LogArgumentNullException(nameof(encryptingCredentials)); - return CreateToken( - payload, - null, - encryptingCredentials, - compressionAlgorithm, - null, - null, - null); + return CreateToken(payload, new SecurityTokenDescriptor { EncryptingCredentials = encryptingCredentials, CompressionAlgorithm = compressionAlgorithm }); } /// @@ -459,14 +388,7 @@ public virtual string CreateToken( _ = signingCredentials ?? throw LogHelper.LogArgumentNullException(nameof(signingCredentials)); _ = encryptingCredentials ?? throw LogHelper.LogArgumentNullException(nameof(encryptingCredentials)); - return CreateToken( - payload, - signingCredentials, - encryptingCredentials, - compressionAlgorithm, - null, - null, - null); + return CreateToken(payload, new SecurityTokenDescriptor { SigningCredentials = signingCredentials, EncryptingCredentials = encryptingCredentials, CompressionAlgorithm = compressionAlgorithm }); } /// @@ -506,14 +428,14 @@ public virtual string CreateToken( _ = additionalHeaderClaims ?? throw LogHelper.LogArgumentNullException(nameof(additionalHeaderClaims)); _ = additionalInnerHeaderClaims ?? throw LogHelper.LogArgumentNullException(nameof(additionalInnerHeaderClaims)); - return CreateToken( - payload, - signingCredentials, - encryptingCredentials, - compressionAlgorithm, - additionalHeaderClaims, - additionalInnerHeaderClaims, - null); + return CreateToken(payload, new SecurityTokenDescriptor + { + SigningCredentials = signingCredentials, + EncryptingCredentials = encryptingCredentials, + CompressionAlgorithm = compressionAlgorithm, + AdditionalHeaderClaims = additionalHeaderClaims, + AdditionalInnerHeaderClaims = additionalInnerHeaderClaims + }); } /// @@ -550,25 +472,33 @@ public virtual string CreateToken( _ = encryptingCredentials ?? throw LogHelper.LogArgumentNullException(nameof(encryptingCredentials)); _ = additionalHeaderClaims ?? throw LogHelper.LogArgumentNullException(nameof(additionalHeaderClaims)); - return CreateToken( - payload, - signingCredentials, - encryptingCredentials, - compressionAlgorithm, - additionalHeaderClaims, - null, - null); + return CreateToken(payload, new SecurityTokenDescriptor + { + SigningCredentials = signingCredentials, + EncryptingCredentials = encryptingCredentials, + CompressionAlgorithm = compressionAlgorithm, + AdditionalHeaderClaims = additionalHeaderClaims + }); } - internal static string CreateToken - ( + internal static string CreateToken( string payload, SigningCredentials signingCredentials, EncryptingCredentials encryptingCredentials, string compressionAlgorithm, IDictionary additionalHeaderClaims, IDictionary additionalInnerHeaderClaims, - string tokenType) + string tokenType) => CreateToken(payload, new SecurityTokenDescriptor + { + SigningCredentials = signingCredentials, + EncryptingCredentials = encryptingCredentials, + CompressionAlgorithm = compressionAlgorithm, + AdditionalHeaderClaims = additionalHeaderClaims, + AdditionalInnerHeaderClaims = additionalInnerHeaderClaims, + TokenType = tokenType + }); + + internal static string CreateToken(string payload, SecurityTokenDescriptor tokenDescriptor) { using (MemoryStream utf8ByteMemoryStream = new()) { @@ -582,18 +512,12 @@ internal static string CreateToken { writer = new Utf8JsonWriter(utf8ByteMemoryStream, new JsonWriterOptions { Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping }); - WriteJwsHeader( - ref writer, - signingCredentials, - encryptingCredentials, - additionalHeaderClaims, - additionalInnerHeaderClaims, - null, - true); + WriteJwsHeader(ref writer, tokenDescriptor); // mark length of jwt header int headerLength = (int)utf8ByteMemoryStream.Length; int signatureSize = 0; + SigningCredentials signingCredentials = tokenDescriptor.SigningCredentials; if (signingCredentials != null) signatureSize = SupportedAlgorithms.GetMaxByteCount(signingCredentials.Algorithm); @@ -634,15 +558,12 @@ int sizeOfEncodedHeaderAndPayloadAsciiBytes sizeOfEncodedSignature = Base64UrlEncoder.Encode(signatureBytes.AsSpan(0, signatureLength), encodedChars.AsSpan(sizeOfEncodedHeader + sizeOfEncodedPayload + 2)); } + EncryptingCredentials encryptingCredentials = tokenDescriptor.EncryptingCredentials; if (encryptingCredentials != null) { return EncryptToken( Encoding.UTF8.GetBytes(encodedChars, 0, sizeOfEncodedHeader + sizeOfEncodedPayload + sizeOfEncodedSignature + 2), - encryptingCredentials, - compressionAlgorithm, - additionalHeaderClaims, - tokenType, - true); + tokenDescriptor); } else { @@ -964,8 +885,19 @@ internal static void WriteJwsHeader( IDictionary jweHeaderClaims, IDictionary jwsHeaderClaims, string tokenType, - bool includeKeyIdInHeader) + bool includeKeyIdInHeader) => WriteJwsHeader(ref writer, new SecurityTokenDescriptor + { + SigningCredentials = signingCredentials, + EncryptingCredentials = encryptingCredentials, + AdditionalHeaderClaims = jweHeaderClaims, + AdditionalInnerHeaderClaims = jwsHeaderClaims, + TokenType = tokenType, + IncludeKeyIdInHeader = includeKeyIdInHeader + }); + + internal static void WriteJwsHeader(ref Utf8JsonWriter writer, SecurityTokenDescriptor tokenDescriptor) { + IDictionary jweHeaderClaims = tokenDescriptor.AdditionalHeaderClaims; if (jweHeaderClaims?.Count > 0 && jweHeaderClaims.Keys.Intersect(JwtTokenUtilities.DefaultHeaderParameters, StringComparer.OrdinalIgnoreCase).Any()) throw LogHelper.LogExceptionMessage( new SecurityTokenException( @@ -974,6 +906,7 @@ internal static void WriteJwsHeader( LogHelper.MarkAsNonPII(nameof(jweHeaderClaims)), LogHelper.MarkAsNonPII(string.Join(", ", JwtTokenUtilities.DefaultHeaderParameters))))); + IDictionary jwsHeaderClaims = tokenDescriptor.AdditionalInnerHeaderClaims; if (jwsHeaderClaims?.Count > 0 && jwsHeaderClaims.Keys.Intersect(JwtTokenUtilities.DefaultHeaderParameters, StringComparer.OrdinalIgnoreCase).Any()) throw LogHelper.LogExceptionMessage( new SecurityTokenException( @@ -984,11 +917,12 @@ internal static void WriteJwsHeader( // If token is a JWE, jweHeaderClaims go in outer header. - bool addJweHeaderClaims = encryptingCredentials is null && jweHeaderClaims?.Count > 0; + bool addJweHeaderClaims = tokenDescriptor.EncryptingCredentials is null && jweHeaderClaims?.Count > 0; bool addJwsHeaderClaims = jwsHeaderClaims?.Count > 0; bool typeWritten = false; writer.WriteStartObject(); + SigningCredentials signingCredentials = tokenDescriptor.SigningCredentials; if (signingCredentials == null) { writer.WriteString(JwtHeaderUtf8Bytes.Alg, SecurityAlgorithms.None); @@ -996,7 +930,7 @@ internal static void WriteJwsHeader( else { writer.WriteString(JwtHeaderUtf8Bytes.Alg, signingCredentials.Algorithm); - if (includeKeyIdInHeader) + if (tokenDescriptor.IncludeKeyIdInHeader) { if (signingCredentials.Key.KeyId != null) writer.WriteString(JwtHeaderUtf8Bytes.Kid, signingCredentials.Key.KeyId); @@ -1031,7 +965,10 @@ internal static void WriteJwsHeader( } if (!typeWritten) + { + string tokenType = tokenDescriptor.TokenType; writer.WriteString(JwtHeaderUtf8Bytes.Typ, string.IsNullOrEmpty(tokenType) ? JwtConstants.HeaderType : tokenType); + } writer.WriteEndObject(); writer.Flush(); @@ -1042,7 +979,16 @@ internal static byte[] WriteJweHeader( string compressionAlgorithm, string tokenType, IDictionary jweHeaderClaims, - bool includeKeyIdInHeader) + bool includeKeyIdInHeader) => WriteJweHeader(new SecurityTokenDescriptor + { + EncryptingCredentials = encryptingCredentials, + CompressionAlgorithm = compressionAlgorithm, + TokenType = tokenType, + AdditionalHeaderClaims = jweHeaderClaims, + IncludeKeyIdInHeader = includeKeyIdInHeader + }); + + internal static byte[] WriteJweHeader(SecurityTokenDescriptor tokenDescriptor) { using (MemoryStream memoryStream = new()) { @@ -1052,6 +998,7 @@ internal static byte[] WriteJweHeader( writer = new Utf8JsonWriter(memoryStream, new JsonWriterOptions { Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping }); writer.WriteStartObject(); + EncryptingCredentials encryptingCredentials = tokenDescriptor.EncryptingCredentials; writer.WriteString(JwtHeaderUtf8Bytes.Alg, encryptingCredentials.Alg); writer.WriteString(JwtHeaderUtf8Bytes.Enc, encryptingCredentials.Enc); @@ -1060,6 +1007,7 @@ internal static byte[] WriteJweHeader( // is treated as opt-in. When the library is at the point where it is able to make breaking changes // (such as the next major version update) we should consider whether or not this app-compat switch // needs to be maintained. + bool includeKeyIdInHeader = tokenDescriptor.IncludeKeyIdInHeader; if (AppContextSwitches.UseRfcDefinitionOfEpkAndKid) { if (includeKeyIdInHeader && encryptingCredentials.KeyExchangePublicKey.KeyId != null) @@ -1082,6 +1030,7 @@ internal static byte[] WriteJweHeader( writer.WriteString(JwtHeaderUtf8Bytes.Kid, encryptingCredentials.Key.KeyId); } + string compressionAlgorithm = tokenDescriptor.CompressionAlgorithm; if (!string.IsNullOrEmpty(compressionAlgorithm)) writer.WriteString(JwtHeaderUtf8Bytes.Zip, compressionAlgorithm); @@ -1089,6 +1038,7 @@ internal static byte[] WriteJweHeader( bool ctyWritten = !encryptingCredentials.SetDefaultCtyClaim; // Current 6x Priority is jweHeaderClaims, type, cty + IDictionary jweHeaderClaims = tokenDescriptor.AdditionalHeaderClaims; if (jweHeaderClaims != null && jweHeaderClaims.Count > 0) { foreach (KeyValuePair kvp in jweHeaderClaims) @@ -1102,7 +1052,10 @@ internal static byte[] WriteJweHeader( } if (!typeWritten) + { + string tokenType = tokenDescriptor.TokenType; writer.WriteString(JwtHeaderUtf8Bytes.Typ, string.IsNullOrEmpty(tokenType) ? JwtConstants.HeaderType : tokenType); + } if (!ctyWritten) writer.WriteString(JwtHeaderUtf8Bytes.Cty, JwtConstants.HeaderType); @@ -1152,7 +1105,7 @@ public string EncryptToken(string innerJwt, EncryptingCredentials encryptingCred if (encryptingCredentials == null) throw LogHelper.LogArgumentNullException(nameof(encryptingCredentials)); - return EncryptTokenPrivate(innerJwt, encryptingCredentials, null, null, null); + return EncryptTokenPrivate(innerJwt, new SecurityTokenDescriptor { EncryptingCredentials = encryptingCredentials }); } /// @@ -1183,7 +1136,7 @@ public string EncryptToken( if (additionalHeaderClaims == null) throw LogHelper.LogArgumentNullException(nameof(additionalHeaderClaims)); - return EncryptTokenPrivate(innerJwt, encryptingCredentials, null, additionalHeaderClaims, null); + return EncryptTokenPrivate(innerJwt, new SecurityTokenDescriptor { EncryptingCredentials = encryptingCredentials, AdditionalHeaderClaims = additionalHeaderClaims }); } /// @@ -1215,7 +1168,7 @@ public string EncryptToken( if (string.IsNullOrEmpty(algorithm)) throw LogHelper.LogArgumentNullException(nameof(algorithm)); - return EncryptTokenPrivate(innerJwt, encryptingCredentials, algorithm, null, null); + return EncryptTokenPrivate(innerJwt, new SecurityTokenDescriptor { EncryptingCredentials = encryptingCredentials, CompressionAlgorithm = algorithm }); } /// @@ -1253,24 +1206,12 @@ public string EncryptToken( if (additionalHeaderClaims == null) throw LogHelper.LogArgumentNullException(nameof(additionalHeaderClaims)); - return EncryptTokenPrivate(innerJwt, encryptingCredentials, algorithm, additionalHeaderClaims, null); + return EncryptTokenPrivate(innerJwt, new SecurityTokenDescriptor { EncryptingCredentials = encryptingCredentials, CompressionAlgorithm = algorithm, AdditionalHeaderClaims = additionalHeaderClaims }); } private static string EncryptTokenPrivate( string innerJwt, - EncryptingCredentials encryptingCredentials, - string compressionAlgorithm, - IDictionary additionalHeaderClaims, - string tokenType) - { - return EncryptToken( - Encoding.UTF8.GetBytes(innerJwt), - encryptingCredentials, - compressionAlgorithm, - additionalHeaderClaims, - tokenType, - true); - } + SecurityTokenDescriptor tokenDescriptor) => EncryptToken(Encoding.UTF8.GetBytes(innerJwt), tokenDescriptor); internal static string EncryptToken( byte[] innerTokenUtf8Bytes, @@ -1278,13 +1219,24 @@ internal static string EncryptToken( string compressionAlgorithm, IDictionary additionalHeaderClaims, string tokenType, - bool includeKeyIdInHeader) + bool includeKeyIdInHeader) => EncryptToken(innerTokenUtf8Bytes, new SecurityTokenDescriptor + { + EncryptingCredentials = encryptingCredentials, + CompressionAlgorithm = compressionAlgorithm, + AdditionalHeaderClaims = additionalHeaderClaims, + TokenType = tokenType, + IncludeKeyIdInHeader = includeKeyIdInHeader + }); + + internal static string EncryptToken(byte[] innerTokenUtf8Bytes, SecurityTokenDescriptor tokenDescriptor) { + EncryptingCredentials encryptingCredentials = tokenDescriptor.EncryptingCredentials; CryptoProviderFactory cryptoProviderFactory = encryptingCredentials.CryptoProviderFactory ?? encryptingCredentials.Key.CryptoProviderFactory; if (cryptoProviderFactory == null) throw LogHelper.LogExceptionMessage(new ArgumentException(TokenLogMessages.IDX10620)); + IDictionary additionalHeaderClaims = tokenDescriptor.AdditionalHeaderClaims; SecurityKey securityKey = JwtTokenUtilities.GetSecurityKey(encryptingCredentials, cryptoProviderFactory, additionalHeaderClaims, out byte[] wrappedKey); using (AuthenticatedEncryptionProvider encryptionProvider = cryptoProviderFactory.CreateAuthenticatedEncryptionProvider(securityKey, encryptingCredentials.Enc)) @@ -1292,8 +1244,9 @@ internal static string EncryptToken( if (encryptionProvider == null) throw LogHelper.LogExceptionMessage(new SecurityTokenEncryptionFailedException(LogMessages.IDX14103)); - byte[] jweHeader = WriteJweHeader(encryptingCredentials, compressionAlgorithm, tokenType, additionalHeaderClaims, includeKeyIdInHeader); + byte[] jweHeader = WriteJweHeader(tokenDescriptor); byte[] plainText; + string compressionAlgorithm = tokenDescriptor.CompressionAlgorithm; if (!string.IsNullOrEmpty(compressionAlgorithm)) { try diff --git a/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs b/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs index ed16a28516..e9c10ef213 100644 --- a/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs +++ b/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs @@ -346,18 +346,16 @@ public virtual string CreateEncodedJwt( DateTime? notBefore, DateTime? expires, DateTime? issuedAt, - SigningCredentials signingCredentials) - { - return CreateJwtSecurityTokenPrivate( - issuer, - audience, - subject, - notBefore, - expires, - issuedAt, - signingCredentials, - null, null, null, null, null, true).RawData; - } + SigningCredentials signingCredentials) => CreateJwtSecurityTokenPrivate(new SecurityTokenDescriptor + { + Issuer = issuer, + Audience = audience, + Subject = subject, + NotBefore = notBefore, + Expires = expires, + IssuedAt = issuedAt, + SigningCredentials = signingCredentials + }).RawData; /// /// Creates a JWT in 'Compact Serialization Format'. @@ -385,18 +383,17 @@ public virtual string CreateEncodedJwt( DateTime? expires, DateTime? issuedAt, SigningCredentials signingCredentials, - EncryptingCredentials encryptingCredentials) - { - return CreateJwtSecurityTokenPrivate( - issuer, - audience, - subject, - notBefore, - expires, - issuedAt, - signingCredentials, - encryptingCredentials, null, null, null, null, true).RawData; - } + EncryptingCredentials encryptingCredentials) => CreateJwtSecurityTokenPrivate(new SecurityTokenDescriptor + { + Issuer = issuer, + Audience = audience, + Subject = subject, + NotBefore = notBefore, + Expires = expires, + IssuedAt = issuedAt, + SigningCredentials = signingCredentials, + EncryptingCredentials = encryptingCredentials + }).RawData; /// /// Creates a JWT in 'Compact Serialization Format'. @@ -426,19 +423,18 @@ public virtual string CreateEncodedJwt( DateTime? issuedAt, SigningCredentials signingCredentials, EncryptingCredentials encryptingCredentials, - IDictionary claimCollection) - { - return CreateJwtSecurityTokenPrivate( - issuer, - audience, - subject, - notBefore, - expires, - issuedAt, - signingCredentials, - encryptingCredentials, - claimCollection, null, null, null, true).RawData; - } + IDictionary claimCollection) => CreateJwtSecurityTokenPrivate(new SecurityTokenDescriptor + { + Issuer = issuer, + Audience = audience, + Subject = subject, + NotBefore = notBefore, + Expires = expires, + IssuedAt = issuedAt, + SigningCredentials = signingCredentials, + EncryptingCredentials = encryptingCredentials, + Claims = claimCollection + }).RawData; /// /// Creates a Json Web Token (JWT). @@ -450,21 +446,7 @@ public virtual JwtSecurityToken CreateJwtSecurityToken(SecurityTokenDescriptor t if (tokenDescriptor == null) throw LogHelper.LogArgumentNullException(nameof(tokenDescriptor)); - return CreateJwtSecurityTokenPrivate( - tokenDescriptor.Issuer, - tokenDescriptor.Audience, - tokenDescriptor.Audiences, - tokenDescriptor.Subject, - tokenDescriptor.NotBefore, - tokenDescriptor.Expires, - tokenDescriptor.IssuedAt, - tokenDescriptor.SigningCredentials, - tokenDescriptor.EncryptingCredentials, - tokenDescriptor.Claims, - tokenDescriptor.TokenType, - tokenDescriptor.AdditionalHeaderClaims, - tokenDescriptor.AdditionalInnerHeaderClaims, - tokenDescriptor.IncludeKeyIdInHeader); + return CreateJwtSecurityTokenPrivate(tokenDescriptor); } /// @@ -496,18 +478,17 @@ public virtual JwtSecurityToken CreateJwtSecurityToken( DateTime? expires, DateTime? issuedAt, SigningCredentials signingCredentials, - EncryptingCredentials encryptingCredentials) - { - return CreateJwtSecurityTokenPrivate( - issuer, - audience, - subject, - notBefore, - expires, - issuedAt, - signingCredentials, - encryptingCredentials, null, null, null, null, true); - } + EncryptingCredentials encryptingCredentials) => CreateJwtSecurityTokenPrivate(new SecurityTokenDescriptor + { + Issuer = issuer, + Audience = audience, + Subject = subject, + NotBefore = notBefore, + Expires = expires, + IssuedAt = issuedAt, + SigningCredentials = signingCredentials, + EncryptingCredentials = encryptingCredentials + }); /// /// Creates a @@ -540,19 +521,18 @@ public virtual JwtSecurityToken CreateJwtSecurityToken( DateTime? issuedAt, SigningCredentials signingCredentials, EncryptingCredentials encryptingCredentials, - IDictionary claimCollection) - { - return CreateJwtSecurityTokenPrivate( - issuer, - audience, - subject, - notBefore, - expires, - issuedAt, - signingCredentials, - encryptingCredentials, - claimCollection, null, null, null, true); - } + IDictionary claimCollection) => CreateJwtSecurityTokenPrivate(new SecurityTokenDescriptor + { + Issuer = issuer, + Audience = audience, + Subject = subject, + NotBefore = notBefore, + Expires = expires, + IssuedAt = issuedAt, + SigningCredentials = signingCredentials, + EncryptingCredentials = encryptingCredentials, + Claims = claimCollection + }); /// /// Creates a @@ -580,17 +560,16 @@ public virtual JwtSecurityToken CreateJwtSecurityToken( DateTime? notBefore = null, DateTime? expires = null, DateTime? issuedAt = null, - SigningCredentials signingCredentials = null) - { - return CreateJwtSecurityTokenPrivate( - issuer, - audience, - subject, - notBefore, - expires, - issuedAt, - signingCredentials, null, null, null, null, null, true); - } + SigningCredentials signingCredentials = null) => CreateJwtSecurityTokenPrivate(new SecurityTokenDescriptor + { + Issuer = issuer, + Audience = audience, + Subject = subject, + NotBefore = notBefore, + Expires = expires, + IssuedAt = issuedAt, + SigningCredentials = signingCredentials + }); /// /// Creates a Json Web Token (JWT). @@ -602,59 +581,14 @@ public override SecurityToken CreateToken(SecurityTokenDescriptor tokenDescripto if (tokenDescriptor == null) throw LogHelper.LogArgumentNullException(nameof(tokenDescriptor)); - return CreateJwtSecurityTokenPrivate( - tokenDescriptor.Issuer, - tokenDescriptor.Audience, - tokenDescriptor.Audiences, - tokenDescriptor.Subject, - tokenDescriptor.NotBefore, - tokenDescriptor.Expires, - tokenDescriptor.IssuedAt, - tokenDescriptor.SigningCredentials, - tokenDescriptor.EncryptingCredentials, - tokenDescriptor.Claims, - tokenDescriptor.TokenType, - tokenDescriptor.AdditionalHeaderClaims, - tokenDescriptor.AdditionalInnerHeaderClaims, - tokenDescriptor.IncludeKeyIdInHeader); + return CreateJwtSecurityTokenPrivate(tokenDescriptor); } - private JwtSecurityToken CreateJwtSecurityTokenPrivate( - string issuer, - string audience, - ClaimsIdentity subject, - DateTime? notBefore, - DateTime? expires, - DateTime? issuedAt, - SigningCredentials signingCredentials, - EncryptingCredentials encryptingCredentials, - IDictionary claimCollection, - string tokenType, - IDictionary additionalHeaderClaims, - IDictionary additionalInnerHeaderClaims, - bool includeKidInHeader) - { - return CreateJwtSecurityTokenPrivate( - issuer, audience, [], subject, notBefore, expires, issuedAt, signingCredentials, encryptingCredentials, - claimCollection, tokenType, additionalHeaderClaims, additionalInnerHeaderClaims, includeKidInHeader); - } - - private JwtSecurityToken CreateJwtSecurityTokenPrivate( - string issuer, - string audience, - IList audiences, - ClaimsIdentity subject, - DateTime? notBefore, - DateTime? expires, - DateTime? issuedAt, - SigningCredentials signingCredentials, - EncryptingCredentials encryptingCredentials, - IDictionary claimCollection, - string tokenType, - IDictionary additionalHeaderClaims, - IDictionary additionalInnerHeaderClaims, - bool includeKeyIdInHeader) + private JwtSecurityToken CreateJwtSecurityTokenPrivate(SecurityTokenDescriptor tokenDescriptor) { + DateTime? expires = tokenDescriptor.Expires; + DateTime? issuedAt = tokenDescriptor.IssuedAt; + DateTime? notBefore = tokenDescriptor.NotBefore; if (SetDefaultTimesOnTokenCreation && (!expires.HasValue || !issuedAt.HasValue || !notBefore.HasValue)) { DateTime now = DateTime.UtcNow; @@ -668,8 +602,13 @@ private JwtSecurityToken CreateJwtSecurityTokenPrivate( notBefore = now; } - JwtPayload payload = new JwtPayload(issuer, audience, audiences, (subject == null ? null : OutboundClaimTypeTransform(subject.Claims)), (claimCollection == null ? null : OutboundClaimTypeTransform(claimCollection)), notBefore, expires, issuedAt); - JwtHeader header = new JwtHeader(signingCredentials, OutboundAlgorithmMap, tokenType, additionalInnerHeaderClaims, includeKeyIdInHeader); + string issuer = tokenDescriptor.Issuer; + ClaimsIdentity subject = tokenDescriptor.Subject; + IDictionary claimCollection = tokenDescriptor.Claims; + JwtPayload payload = new JwtPayload(issuer, tokenDescriptor.Audience, tokenDescriptor.Audiences, (subject == null ? null : OutboundClaimTypeTransform(subject.Claims)), (claimCollection == null ? null : OutboundClaimTypeTransform(claimCollection)), notBefore, expires, issuedAt); + SigningCredentials signingCredentials = tokenDescriptor.SigningCredentials; + string tokenType = tokenDescriptor.TokenType; + JwtHeader header = new JwtHeader(signingCredentials, OutboundAlgorithmMap, tokenType, tokenDescriptor.AdditionalInnerHeaderClaims, tokenDescriptor.IncludeKeyIdInHeader); if (LogHelper.IsEnabled(EventLogLevel.Verbose)) LogHelper.LogVerbose(LogMessages.IDX12721, LogHelper.MarkAsNonPII(issuer ?? "null"), LogHelper.MarkAsNonPII(payload.Aud.ToString() ?? "null")); @@ -689,13 +628,14 @@ private JwtSecurityToken CreateJwtSecurityTokenPrivate( if (LogHelper.IsEnabled(EventLogLevel.Informational)) LogHelper.LogInformation(LogMessages.IDX12722, rawHeader, rawPayload); + EncryptingCredentials encryptingCredentials = tokenDescriptor.EncryptingCredentials; if (encryptingCredentials != null) { return EncryptToken( new JwtSecurityToken(header, payload, rawHeader, rawPayload, rawSignature), encryptingCredentials, tokenType, - additionalHeaderClaims); + tokenDescriptor.AdditionalHeaderClaims); } return new JwtSecurityToken(header, payload, rawHeader, rawPayload, rawSignature);