I am trying to implement an authentication/authorization process which when user signs in, generates a JWT and places it in a cookie (while implementing I was mainly using this article - thought it's for .NET Core and I am using .NET 4.6: https://stormpath.com/blog/token-authentication-asp-net-core ). So far, this process works ok, but when I try to make a request to a secured endpoint (decorated with an [Authorize] attribute) with the JWT in the cookie, I always get a 401 Unauthorized response. Even though the JWT seams to get validated and an AuthenticationTicket is being returned from the Unprotect method of the CustomJwtDataFormat class.
As recommended in the answer to this question Why is my ClaimsIdentity IsAuthenticated always false (for web api Authorize filter)? I added the AuthenticationType parameter while creating the ClaimsIdentity. But still the same 401 response.
Here is my ConfigureAuth method:
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
Provider = new CookieAuthenticationProvider(),
CookieName = "access_token",
AuthenticationMode =
Microsoft.Owin.Security.AuthenticationMode.Active,
AuthenticationType = AuthenticationTypes.Password,
TicketDataFormat = new CustomJwtDataFormat(
SecurityAlgorithms.HmacSha256,
SettingsConfig.TokenValidationParameters)
});
}
The Unprotect method of the CustomJwtDataFormat class:
public AuthenticationTicket Unprotect(string protectedText)
{
var handler = new JwtSecurityTokenHandler();
ClaimsPrincipal principal = null;
SecurityToken validToken = null;
try
{
principal = handler.ValidateToken(protectedText, this.validationParameters, out validToken);
var validJwt = validToken as JwtSecurityToken;
if (validJwt == null)
{
throw new ArgumentException("Invalid JWT");
}
if (!validJwt.Header.Alg.Equals(algorithm, StringComparison.Ordinal))
{
throw new ArgumentException($"Algorithm must be '{algorithm}'");
}
}
catch (SecurityTokenValidationException e)
{
var ex = e;
return null;
}
catch (ArgumentException e)
{
var ex = e;
return null;
}
var identity = new ClaimsIdentity(principal.Identities.FirstOrDefault().Claims, AuthenticationTypes.Password);
// Validation passed. Return a valid AuthenticationTicket:
var authTicket = new AuthenticationTicket(identity, new AuthenticationProperties());
return authTicket;
My TokenValidationParameters:
public static TokenValidationParameters TokenValidationParameters = new TokenValidationParameters
{
// The signing key must match!
ValidateIssuerSigningKey = true,
IssuerSigningKey = signingKey,
// Validate the JWT Issuer (iss) claim
ValidateIssuer = true,
ValidIssuer = "ExampleIssuer",
// Validate the JWT Audience (aud) claim
ValidateAudience = true,
ValidAudience = "ExampleAudience",
// Validate the token expiry
ValidateLifetime = true,
ClockSkew = TimeSpan.FromMinutes(5)
};
The GenerateToken method:
public static string GenerateToken(MetadataForToken tokenContentAndMetadata)
{
var symmetricKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(tokenContentAndMetadata.SecretKey));
var tokenHandler = new JwtSecurityTokenHandler();
var now = DateTime.UtcNow;
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(tokenContentAndMetadata.Claims),
Expires = now.AddMinutes(Convert.ToInt32(tokenContentAndMetadata.ExpireMinutes)),
SigningCredentials = new SigningCredentials(symmetricKey, tokenContentAndMetadata.SecurityAlgorithm),
Issuer = "ExampleIssuer",
Audience = "ExampleAudience"
};
var sToken = tokenHandler.CreateToken(tokenDescriptor);
var token = tokenHandler.WriteToken(sToken);
return token;
}
What am I doing wrong?