8
votes

Fellow programmers,

I'm currently struggling with Microsoft account JWT token validation in Web Api 2. I've found OWIN middleware for that (NuGet package Microsoft.Owin.Security.Jwt) and here is the code from my Startup.cs configuring that:

    public void ConfigureAuth(IAppBuilder app)
    {
        var sha256 = new SHA256Managed();
        var secretBytes = System.Text.Encoding.UTF8.GetBytes(@"(My app client secret)" + "JWTSig");
        byte[] signingKey = sha256.ComputeHash(secretBytes);

        app.UseJwtBearerAuthentication(
            new JwtBearerAuthenticationOptions
            {
                AllowedAudiences = new[] { "(My API's domain )" },
                IssuerSecurityTokenProviders =
                    new[]
                            {
                                new SymmetricKeyIssuerSecurityTokenProvider(
                                    "urn:windows:liveid", signingKey)
                            }
            });
    }

I've found that snippet here:

http://code.lawrab.com/2014/01/securing-webapi-with-live-id.html

The JWT token is sent from my Windows Store app client using Live SDK. I'm sending the authentication token, not access token, so I'm sure it's JWT. Using online debuggers like this one: http://jwt.io/ I'm able to successfully decode the header & payload part, but I cannot find a way to validate the signature. The debug output from my Web API when a request with that JWT is sent is:

Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationMiddleware Error: 0 : Authentication failed
System.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException: IDX10500: Signature validation failed. Unable to resolve SecurityKeyIdentifier: 'SecurityKeyIdentifier
    (
    IsReadOnly = False,
    Count = 1,
    Clause[0] = System.IdentityModel.Tokens.NamedKeySecurityKeyIdentifierClause
    )
', 
token: '{"alg":"HS256","kid":"0","typ":"JWT"}.{"ver":1,"iss":"urn:windows:liveid","exp":1408666611,"uid":"my Microsoft account uid","aud":"(My API's domain)","urn:microsoft:appuri":"ms-app://(client app store id)","urn:microsoft:appid":"(ID of the app from account.live.com/developers)"}
RawData: (the JWT token)'.
   w System.IdentityModel.Tokens.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters)
   w System.IdentityModel.Tokens.JwtSecurityTokenHandler.ValidateToken(String securityToken, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
   w Microsoft.Owin.Security.Jwt.JwtFormat.Unprotect(String protectedText)
   w Microsoft.Owin.Security.Infrastructure.AuthenticationTokenReceiveContext.DeserializeTicket(String protectedData)
   w Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationHandler.d__0.MoveNext()

Sorry for my english, any corrections are more than welcome.

1

1 Answers

0
votes

One of the Easiest way I can use , is to validate it from the Source itself.

in your case right now you are using live.com , then send one request to live.com and use your token in the header and if it's a valid header it will return the known value (ex. user account information)

choose a url like this : https://outlook.live.com/ows/v1.0/OutlookOptions

and send the token in the header as Authorization: Bearer TOKEN_VALUE

if it returned the expected value , then it's a valid token and the session also is working