Is it possible to decode a SessionSecurityToken
?
I've set up a site to work with ThinkTecture IdentityServer
using MachineKeySessionSecurityTokenHandler
, and everything works as expected.
But now I need to pass the token to another service, but in an Authorization
HTTP header instead of a cookie.
I've tried the following:
var cookie = HttpContext.Current.Request.Cookies[FederatedAuthentication.FederationConfiguration.CookieHandler.Name];
if (cookie != null)
{
var t = MachineKey.Unprotect(Convert.FromBase64String(cookie.Value), "System.IdentityModel.Services.MachineKeyTransform");
}
but this throws a System.Security.Cryptography.CryptographicException
Found the solution.
The only (easy) way of sending the data across the wire is to convert the SessionSecurityToken
to a JwtSecurityToken
and use the RawData
property.
Sample implementation (dependent on ThinkTecture.IdentityModel
):
public JwtSecurityToken ConvertSessionToJsonWebSecurityToken(SessionSecurityToken sessionToken)
{
var h = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.SecurityTokenHandlers[typeof(JwtSecurityToken)] as JwtSecurityTokenHandler;
if (h != null)
{
var issuer = ((ValidatingIssuerNameRegistry)h.Configuration.IssuerNameRegistry).IssuingAuthorities.First().Name;
var audience = h.Configuration.AudienceRestriction.AllowedAudienceUris.First().AbsoluteUri;
var signingKey = ((ValidatingIssuerNameRegistry)h.Configuration.IssuerNameRegistry).IssuingAuthorities.First().SymmetricKeys.First();
var securityKey = ((NamedKeyIssuerTokenResolver)h.Configuration.IssuerTokenResolver).SecurityKeys.First().Value.First();
// Create token
var t = h.CreateToken(
null,
null,
(ClaimsIdentity)sessionToken.ClaimsPrincipal.Identity,
new Lifetime(sessionToken.ValidFrom, sessionToken.ValidTo),
new SigningCredentials(
securityKey,
Algorithms.HmacSha256Signature,
Algorithms.Sha256Digest));
// Serialize token for validaiton
var s = h.WriteToken(t);
// Validate token
var validationParameters = new TokenValidationParameters()
{
AllowedAudience = audience,
ValidIssuer = issuer,
SigningToken = new BinarySecretSecurityToken(Convert.FromBase64String(signingKey))
};
h.ValidateToken(s, validationParameters);
// Return token with correct type
return h.ReadToken(s) as JwtSecurityToken;
}
return null;
}
[Test]
public void GetToken_WhenValidSessionTokenExist_ShouldReturnValidJwtToken()
{
JwtSecurityToken c;
FederatedAuthentication.SessionAuthenticationModule.TryReadJwtTokenFromCookie(container.GetInstance<ISecurityTokenOperations>(), out c)
Assert.That(!string.IsNullOrEmpty(c.RawData));
}