Search code examples
.net-4.5wifthinktecture-ident-serverthinktecture-ident-model

How to decode SessionSecurityToken


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


Solution

  • 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));
    }