Skip to content

Commit

Permalink
JwtSecurityTokenConverter initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Keegan Caruso committed Jun 20, 2023
1 parent 3ffa857 commit 7fc29ae
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
[assembly: InternalsVisibleTo("Microsoft.IdentityModel.JsonWebTokens.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
[assembly: InternalsVisibleTo("Microsoft.IdentityModel.Protocols.SignedHttpRequest, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
[assembly: InternalsVisibleTo("System.IdentityModel.Tokens.Jwt, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
[assembly: InternalsVisibleTo("System.IdentityModel.Tokens.Jwt.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
[assembly: InternalsVisibleTo("Microsoft.IdentityModel.S2S, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
[assembly: InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tokens, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
[assembly: InternalsVisibleTo("Microsoft.IdentityModel.S2S.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
Expand Down
43 changes: 43 additions & 0 deletions src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using Microsoft.IdentityModel.JsonWebTokens;

namespace System.IdentityModel.Tokens.Jwt
{
/// <summary>
/// Static class to converts an object to a <see cref="JwtSecurityToken"/>
/// </summary>
public static class JwtSecurityTokenConverter
{
/// <summary>
/// Initializes a new instance of a <see cref="JwtSecurityToken"/> from a <see cref="JsonWebToken"/>
/// </summary>
/// <param name="token">A JSON Web Token to convert from.</param>
/// <exception cref="ArgumentNullException"><paramref name="token"/> is null</exception>
public static JwtSecurityToken Convert(JsonWebToken token)
{
if (token == null)
throw new ArgumentNullException(nameof(token));

if (token.InnerToken != null)
{
var outerToken = new JwtSecurityToken(token.EncodedToken);
outerToken.InnerToken = new JwtSecurityToken(token.InnerToken.EncodedToken);
return outerToken;
}
else if (!string.IsNullOrEmpty(token.EncodedToken))
{
return new JwtSecurityToken(token.EncodedToken);
}
else if (token.Header != null && token.Payload != null)
{
var header = JwtHeader.Deserialize(token.Header.RootElement.GetRawText());
var payload = JwtPayload.Deserialize(token.Payload.RootElement.GetRawText());
return new JwtSecurityToken(header, payload);
}

throw new ArgumentException("token.EncodedToken or token.Header and token.Payload must be set");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Collections.Generic;
using System.Linq;
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.TestUtils;
using Microsoft.IdentityModel.Tokens;
using Xunit;

namespace System.IdentityModel.Tokens.Jwt.Tests
{
#pragma warning disable CS3016 // Arrays as attribute arguments is not CLS-compliant
public class JwtSecurityTokenConverterTests
{
[Fact]
public void JwtSecurityTokenConverter_ThrowsOnNull()
{
Assert.Throws<ArgumentNullException>(() => JwtSecurityTokenConverter.Convert(null));
}

[Theory, MemberData(nameof(ConverterTheoryData))]
public void JsonWebTokenToJwtSecurityTokenConversions(JwtSecurityTokenConverterTheoryData theoryData)
{
var output = JwtSecurityTokenConverter.Convert(theoryData.InputToken);
Assert.NotNull(output);
theoryData.Validator(output);
}

public static TheoryData<JwtSecurityTokenConverterTheoryData> ConverterTheoryData()
{
var tdJwe = new SecurityTokenDescriptor
{
SigningCredentials = KeyingMaterial.JsonWebKeyRsa256SigningCredentials,
EncryptingCredentials = KeyingMaterial.DefaultSymmetricEncryptingCreds_Aes256_Sha512_512,
Claims = Default.PayloadDictionary
};

var tdJws = new SecurityTokenDescriptor
{
SigningCredentials = KeyingMaterial.JsonWebKeyRsa256SigningCredentials,
Claims = Default.PayloadDictionary
};

var handler = new JsonWebTokenHandler();
var jweTokenString = handler.CreateToken(tdJwe);
var jwsTokenString = handler.CreateToken(tdJws);

var validationParameters = new TokenValidationParameters
{
RequireExpirationTime = false,
ValidateAudience = false,
ValidateIssuer = false,
TokenDecryptionKey = KeyingMaterial.DefaultSymmetricEncryptingCreds_Aes256_Sha512_512.Key,
IssuerSigningKey = KeyingMaterial.JsonWebKeyRsa256SigningCredentials.Key
};

var result = handler.ValidateToken(jweTokenString, validationParameters);
var jweToken = result.SecurityToken as JsonWebToken;

result = handler.ValidateToken(jwsTokenString, validationParameters);
var jwsTokenFromString = result.SecurityToken as JsonWebToken;

var jwsTokenFromHeaderAndPayload = new JsonWebToken(
Default.PayloadString,
new Microsoft.IdentityModel.Json.Linq.JObject
{
{ JwtHeaderParameterNames.Alg, SecurityAlgorithms.Sha512 },
{ JwtHeaderParameterNames.Kid, Default.AsymmetricSigningKey.KeyId },
{ JwtHeaderParameterNames.Typ, JwtConstants.HeaderType }
}.ToString(Microsoft.IdentityModel.Json.Formatting.None));

return new TheoryData<JwtSecurityTokenConverterTheoryData>
{
new JwtSecurityTokenConverterTheoryData
{
First = true,
TestId = "JweToJwe",
InputToken = jweToken,
Validator = (token) =>
{
Assert.NotNull(token.InnerToken);

foreach (var header in jweToken.Header.Claims((string)Default.PayloadDictionary[JwtRegisteredClaimNames.Iss]))
{
Assert.True(token.Header.ContainsKey(header.Type));
var otherHeader = token.Header[header.Type];
Assert.Equal(header.Value, otherHeader);
}

foreach (var header in jweToken.InnerToken.Header.Claims((string)Default.PayloadDictionary[JwtRegisteredClaimNames.Iss]))
{
Assert.True(token.InnerToken.Header.ContainsKey(header.Type));
var otherHeader = token.InnerToken.Header[header.Type];
Assert.Equal(header.Value, otherHeader);
}

var jweTokenClaims = new List<Security.Claims.Claim>(jweToken.Claims).ToDictionary(c => c.Type, c => c.Value);
var otherTokenClaims = new List<Security.Claims.Claim>(token.Claims).ToDictionary(c => c.Type, c => c.Value);;

Assert.Equal(jweTokenClaims.Count, otherTokenClaims.Count);

foreach (var claim in jweTokenClaims)
{
Assert.True(otherTokenClaims.ContainsKey(claim.Key));
Assert.True(otherTokenClaims[claim.Key] == claim.Value);
}

}
},
new JwtSecurityTokenConverterTheoryData
{
TestId = "JwsCreatedFromString",
InputToken = jwsTokenFromString,
Validator = (token) =>
{
Assert.Null(token.InnerToken);

foreach (var header in jwsTokenFromString.Header.Claims((string)Default.PayloadDictionary[JwtRegisteredClaimNames.Iss]))
{
Assert.True(token.Header.ContainsKey(header.Type));
var otherHeader = token.Header[header.Type];
Assert.Equal(header.Value, otherHeader);
}

var jwsTokenFromStringClaims = new List<Security.Claims.Claim>(jwsTokenFromString.Claims).ToDictionary(c => c.Type, c => c.Value);
var otherTokenClaims = new List<Security.Claims.Claim>(token.Claims).ToDictionary(c => c.Type, c => c.Value);;

Assert.Equal(jwsTokenFromStringClaims.Count, otherTokenClaims.Count);

foreach (var claim in jwsTokenFromStringClaims)
{
Assert.True(otherTokenClaims.ContainsKey(claim.Key));
Assert.True(otherTokenClaims[claim.Key] == claim.Value);
}
}
},
new JwtSecurityTokenConverterTheoryData
{
TestId = "JwsCreatedFromHeaderAndPayload",
InputToken = jwsTokenFromHeaderAndPayload,
Validator = (token) =>
{
Assert.Null(token.InnerToken);

foreach (var header in jwsTokenFromHeaderAndPayload.Header.Claims((string)Default.PayloadDictionary[JwtRegisteredClaimNames.Iss]))
{
Assert.True(token.Header.ContainsKey(header.Type));
var otherHeader = token.Header[header.Type];
Assert.Equal(header.Value, otherHeader);
}

var jwsTokenFromHeaderAndPayloadClaims = new List<Security.Claims.Claim>(jwsTokenFromHeaderAndPayload.Claims).ToDictionary(c => c.Type, c => c.Value);
var otherTokenClaims = new List<Security.Claims.Claim>(token.Claims).ToDictionary(c => c.Type, c => c.Value);;

Assert.Equal(jwsTokenFromHeaderAndPayloadClaims.Count, otherTokenClaims.Count);

foreach (var claim in jwsTokenFromHeaderAndPayloadClaims)
{
Assert.True(otherTokenClaims.ContainsKey(claim.Key));
Assert.True(otherTokenClaims[claim.Key] == claim.Value);
}
}
}
};
}


public class JwtSecurityTokenConverterTheoryData : TheoryDataBase
{
public JsonWebToken InputToken { get; set; }

public Action<JwtSecurityToken> Validator { get; set; }
}
#pragma warning restore CS3016 // Arrays as attribute arguments is not CLS-compliant
}
}

0 comments on commit 7fc29ae

Please sign in to comment.