Permalink
Browse files

Use JwtSecurityTokenHandler.CreateEncodedJwt() instead of CreateToken…

…()/WriteToken() to ensure the resulting token is not signed twice
  • Loading branch information...
PinpointTownes committed Jul 30, 2017
1 parent 3073ceb commit a499f11cc5dceaf74c60d111c7c4268452cd8ddd
@@ -5,6 +5,7 @@
*/
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
@@ -237,23 +238,36 @@ public partial class OpenIdConnectServerHandler : AuthenticationHandler<OpenIdCo
break;
}
var token = notification.SecurityTokenHandler.CreateToken(new SecurityTokenDescriptor
var descriptor = new SecurityTokenDescriptor
{
Subject = identity,
Issuer = notification.Issuer,
SigningCredentials = notification.SigningCredentials,
IssuedAt = notification.Ticket.Properties.IssuedUtc?.UtcDateTime,
NotBefore = notification.Ticket.Properties.IssuedUtc?.UtcDateTime,
Expires = notification.Ticket.Properties.ExpiresUtc?.UtcDateTime
});
};
string token;
// When the token handler is a JWT token handler, directly use JwtSecurityTokenHandler.CreateEncodedJwt()
// instead of calling JwtSecurityTokenHandler.WriteToken() to avoid signing the token twice.
if (notification.SecurityTokenHandler is JwtSecurityTokenHandler jwtSecurityTokenHandler)
{
token = jwtSecurityTokenHandler.CreateEncodedJwt(descriptor);
}
var result = notification.SecurityTokenHandler.WriteToken(token);
else
{
token = notification.SecurityTokenHandler.WriteToken(
notification.SecurityTokenHandler.CreateToken(descriptor));
}
Logger.LogTrace("A new access token was successfully generated using the specified " +
"security token handler: {Token} ; {Claims} ; {Properties}.",
result, ticket.Principal.Claims, ticket.Properties.Items);
token, ticket.Principal.Claims, ticket.Properties.Items);
return result;
return token;
}
private async Task<string> SerializeIdentityTokenAsync(
@@ -439,7 +453,7 @@ public partial class OpenIdConnectServerHandler : AuthenticationHandler<OpenIdCo
break;
}
var token = notification.SecurityTokenHandler.CreateToken(new SecurityTokenDescriptor
var token = notification.SecurityTokenHandler.CreateEncodedJwt(new SecurityTokenDescriptor
{
Subject = identity,
Issuer = notification.Issuer,
@@ -449,13 +463,11 @@ public partial class OpenIdConnectServerHandler : AuthenticationHandler<OpenIdCo
Expires = notification.Ticket.Properties.ExpiresUtc?.UtcDateTime
});
var result = notification.SecurityTokenHandler.WriteToken(token);
Logger.LogTrace("A new identity token was successfully generated using the specified " +
"security token handler: {Token} ; {Claims} ; {Properties}.",
result, ticket.Principal.Claims, ticket.Properties.Items);
token, ticket.Principal.Claims, ticket.Properties.Items);
return result;
return token;
}
private async Task<string> SerializeRefreshTokenAsync(
@@ -242,7 +242,11 @@ public partial class OpenIdConnectServerHandler : AuthenticationHandler<OpenIdCo
notification.Ticket.Properties.ExpiresUtc?.UtcDateTime)
});
var result = notification.SecurityTokenHandler.WriteToken(token);
// When the access token is a JWT token, directly use RawData instead of calling
// JwtSecurityTokenHandler.WriteToken(token) to avoid signing the token twice.
var result = token is JwtSecurityToken jwtSecurityToken ?
jwtSecurityToken.RawData :
notification.SecurityTokenHandler.WriteToken(token);
Logger.LogTrace("A new access token was successfully generated using the specified " +
"security token handler: {Token} ; {Claims} ; {Properties}.",
@@ -442,7 +446,7 @@ public partial class OpenIdConnectServerHandler : AuthenticationHandler<OpenIdCo
notification.Ticket.Properties.ExpiresUtc?.UtcDateTime)
});
var result = notification.SecurityTokenHandler.WriteToken(token);
var result = ((JwtSecurityToken) token).RawData;
Logger.LogTrace("A new identity token was successfully generated using the specified " +
"security token handler: {Token} ; {Claims} ; {Properties}.",
@@ -1220,14 +1220,8 @@ public async Task SerializeAccessTokenAsync_MissingSigningCredentialsCauseAnExce
public async Task SerializeAccessTokenAsync_UsesAccessTokenHandlerWhenRegistered()
{
// Arrange
var token = Mock.Of<SecurityToken>();
var format = new Mock<JwtSecurityTokenHandler>();
format.Setup(mock => mock.CreateToken(It.IsAny<SecurityTokenDescriptor>()))
.Returns(token)
.Verifiable();
format.Setup(mock => mock.WriteToken(token))
format.Setup(mock => mock.CreateEncodedJwt(It.IsAny<SecurityTokenDescriptor>()))
.Returns("7F82F1A3-8C9F-489F-B838-4B644B7C92B2")
.Verifiable();
@@ -1265,8 +1259,7 @@ public async Task SerializeAccessTokenAsync_UsesAccessTokenHandlerWhenRegistered
// Assert
Assert.Equal("7F82F1A3-8C9F-489F-B838-4B644B7C92B2", response.AccessToken);
format.Verify(mock => mock.CreateToken(It.IsAny<SecurityTokenDescriptor>()), Times.Once());
format.Verify(mock => mock.WriteToken(token), Times.Once());
format.Verify(mock => mock.CreateEncodedJwt(It.IsAny<SecurityTokenDescriptor>()), Times.Once());
}
[Fact]
@@ -1936,11 +1929,7 @@ public async Task SerializeIdentityTokenAsync_UsesIdentityTokenHandler()
{
// Arrange
var format = new Mock<JwtSecurityTokenHandler>();
format.Setup(mock => mock.CreateToken(It.IsAny<SecurityTokenDescriptor>()))
.Returns(It.IsAny<SecurityToken>())
.Verifiable();
format.Setup(mock => mock.WriteToken(It.IsAny<SecurityToken>()))
format.Setup(mock => mock.CreateEncodedJwt(It.IsAny<SecurityTokenDescriptor>()))
.Returns("7F82F1A3-8C9F-489F-B838-4B644B7C92B2")
.Verifiable();
@@ -1979,8 +1968,7 @@ public async Task SerializeIdentityTokenAsync_UsesIdentityTokenHandler()
// Assert
Assert.Equal("7F82F1A3-8C9F-489F-B838-4B644B7C92B2", response.IdToken);
format.Verify(mock => mock.CreateToken(It.IsAny<SecurityTokenDescriptor>()), Times.Once());
format.Verify(mock => mock.WriteToken(It.IsAny<SecurityToken>()), Times.Once());
format.Verify(mock => mock.CreateEncodedJwt(It.IsAny<SecurityTokenDescriptor>()), Times.Once());
}
[Fact]
@@ -1774,13 +1774,21 @@ public async Task SerializeIdentityTokenAsync_MissingSigningCredentialsCauseAnEx
public async Task SerializeIdentityTokenAsync_UsesIdentityTokenHandler()
{
// Arrange
var token = new JwtSecurityToken(
"eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzc" +
"yI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5" +
"NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZ" +
"fV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5Nz" +
"AKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6q" +
"Jp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJ" +
"NqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7Tpd" +
"QyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoS" +
"K5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4" +
"XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg");
var format = new Mock<JwtSecurityTokenHandler>();
format.Setup(mock => mock.CreateToken(It.IsAny<SecurityTokenDescriptor>()))
.Returns(It.IsAny<SecurityToken>())
.Verifiable();
format.Setup(mock => mock.WriteToken(It.IsAny<SecurityToken>()))
.Returns("7F82F1A3-8C9F-489F-B838-4B644B7C92B2")
.Returns(token)
.Verifiable();
var server = CreateAuthorizationServer(options =>
@@ -1817,9 +1825,8 @@ public async Task SerializeIdentityTokenAsync_UsesIdentityTokenHandler()
});
// Assert
Assert.Equal("7F82F1A3-8C9F-489F-B838-4B644B7C92B2", response.IdToken);
Assert.Equal(token.RawData, response.IdToken);
format.Verify(mock => mock.CreateToken(It.IsAny<SecurityTokenDescriptor>()), Times.Once());
format.Verify(mock => mock.WriteToken(It.IsAny<SecurityToken>()), Times.Once());
}
[Fact]

0 comments on commit a499f11

Please sign in to comment.