Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix JwtSecurityToken Missing Mapping When Creating a Token. #2578

Merged
merged 16 commits into from
May 20, 2024
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ namespace Microsoft.IdentityModel.Tokens
/// </summary>
public class X509EncryptingCredentials : EncryptingCredentials
{
internal const string _useShortNameForRsaOaepKey = "Switch.Microsoft.IdentityModel.UseShortNameForRsaOaepKey";
FuPingFranco marked this conversation as resolved.
Show resolved Hide resolved
FuPingFranco marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Designed to construct <see cref="EncryptingCredentials"/> based on a x509 certificate.
/// </summary>
Expand All @@ -21,7 +23,7 @@ public class X509EncryptingCredentials : EncryptingCredentials
/// </remarks>
/// <exception cref="ArgumentNullException">if 'certificate' is null.</exception>
public X509EncryptingCredentials(X509Certificate2 certificate)
: this(certificate, SecurityAlgorithms.DefaultAsymmetricKeyWrapAlgorithm, SecurityAlgorithms.DefaultSymmetricEncryptionAlgorithm)
: this(certificate, GetEncryptionAlgorithm(), SecurityAlgorithms.DefaultSymmetricEncryptionAlgorithm)
{
}

Expand All @@ -48,5 +50,15 @@ public X509Certificate2 Certificate
get;
private set;
}

private static string GetEncryptionAlgorithm()
{
return ShouldUseShortNameForRsaOaepKey() ? SecurityAlgorithms.RsaOAEP : SecurityAlgorithms.DefaultAsymmetricKeyWrapAlgorithm;
}

private static bool ShouldUseShortNameForRsaOaepKey()
{
return AppContext.TryGetSwitch(_useShortNameForRsaOaepKey, out var useKeyWrap) && useKeyWrap;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class JwtSecurityTokenHandler : SecurityTokenHandler
private Dictionary<string, string> _outboundAlgorithmMap = null;
private static string _shortClaimType = _namespace + "/ShortTypeName";
private bool _mapInboundClaims = DefaultMapInboundClaims;

FuPingFranco marked this conversation as resolved.
Show resolved Hide resolved
/// <summary>
/// Default claim type mapping for inbound claims.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.TestUtils;
using Microsoft.IdentityModel.Tokens;
using Xunit;

namespace System.IdentityModel.Tokens.Jwt.Tests
{
[CollectionDefinition("JwtSecurityTokenHandlerTestsWithContextSwitches", DisableParallelization = true)]
public class JwtSecurityTokenHandlerTestsWithContextSwitches
{
[Theory]
[InlineData(SecurityAlgorithms.RsaOAEP, true)]
[InlineData(SecurityAlgorithms.RsaOaepKeyWrap, false)]
public void JwtSecurityTokenHandler_CreateToken_AddShortFormMappingForRsaOAEP(string algorithm, bool useShortNameForRsaOaepKey)
{
AppContext.SetSwitch(X509EncryptingCredentials._useShortNameForRsaOaepKey, useShortNameForRsaOaepKey);
var encryptingCredentials = new X509EncryptingCredentials(Default.Certificate);
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();

JwtSecurityToken token = CreateJwtSecurityToken(tokenHandler, encryptingCredentials);

Assert.Equal(token.Header.Alg, algorithm);

AppContext.SetSwitch(X509EncryptingCredentials._useShortNameForRsaOaepKey, false);
}
FuPingFranco marked this conversation as resolved.
Show resolved Hide resolved

[Theory]
[InlineData(SecurityAlgorithms.RsaOAEP, true)]
[InlineData(SecurityAlgorithms.RsaOaepKeyWrap, false)]
public void JsonWebTokenHandler_CreateToken_AddShortFormMappingForRsaOAEP(string algorithm, bool useShortNameForRsaOaepKey)
{
AppContext.SetSwitch(X509EncryptingCredentials._useShortNameForRsaOaepKey, useShortNameForRsaOaepKey);
var encryptingCredentials = new X509EncryptingCredentials(Default.Certificate);
JsonWebTokenHandler tokenHandler = new JsonWebTokenHandler();

JsonWebToken jsonToken = new JsonWebToken(CreateJwtSecurityTokenAsString(tokenHandler, encryptingCredentials));

Assert.Equal(jsonToken.Alg, algorithm);

AppContext.SetSwitch(X509EncryptingCredentials._useShortNameForRsaOaepKey, false);
}

private JwtSecurityToken CreateJwtSecurityToken(JwtSecurityTokenHandler tokenHandler, X509EncryptingCredentials encryptingCredentials)
{
return tokenHandler.CreateJwtSecurityToken(CreateTokenDescriptor(encryptingCredentials));
}

private string CreateJwtSecurityTokenAsString(JsonWebTokenHandler tokenHandler, X509EncryptingCredentials encryptingCredentials)
{
return tokenHandler.CreateToken(CreateTokenDescriptor(encryptingCredentials));
}

private SecurityTokenDescriptor CreateTokenDescriptor(X509EncryptingCredentials encryptingCredentials)
{
return new SecurityTokenDescriptor
{
Issuer = Default.Issuer,
SigningCredentials = Default.AsymmetricSigningCredentials,
EncryptingCredentials = encryptingCredentials,
};
}
}
}
Loading