I'm currently converting my Web API 2.0 to .NET Core Web API but there is one section I'm struggling with.
In my existing API, I have an attribute with the following code:
public class JwtAuthentication : Attribute, IAuthenticationFilter
{
public string Realm { get; set; }
public bool AllowMultiple => false;
public async Task AuthenticateAsync(
HttpAuthenticationContext context,
CancellationToken cancellationToken)
{
var request = context.Request;
var authorization = request.Headers.Authorization;
// checking request header value having required scheme "Bearer" or not.
if (authorization == null ||
authorization.Scheme.ToLowerInvariant() != "bearer" ||
string.IsNullOrEmpty(authorization.Parameter))
{
context.ErrorResult = new AuthenticationFailureResult("JWT Token is Missing", request);
return;
}
// Getting Token value from header values.
var token = authorization.Parameter;
var principal = await AuthJwtToken(token);
if (principal == null)
{
context.ErrorResult = new AuthenticationFailureResult("Invalid JWT Token", request);
}
else
{
context.Principal = principal;
}
}
private static bool ValidateToken(string token, out ICollection<Claim> claims)
{
claims = null;
var simplePrinciple = JwtAuthManager.GetPrincipal(token);
if (simplePrinciple == null)
{
return false;
}
var identity = simplePrinciple.Identity as ClaimsIdentity;
if (identity == null)
{
return false;
}
if (!identity.IsAuthenticated)
{
return false;
}
var usernameClaim = identity.FindFirst(ClaimTypes.Name);
var emailClaim = identity.FindFirst(ClaimTypes.Email);
var username = usernameClaim?.Value;
var email = emailClaim?.Value;
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(email))
{
return false;
}
claims = identity.Claims.ToList();
return true;
}
protected Task<IPrincipal> AuthJwtToken(string token)
{
if (ValidateToken(token, out var claims))
{
var identity = new ClaimsIdentity(claims, "Jwt");
IPrincipal user = new ClaimsPrincipal(identity);
return Task.FromResult(user);
}
return Task.FromResult<IPrincipal>(null);
}
public Task ChallengeAsync(
HttpAuthenticationChallengeContext context,
CancellationToken cancellationToken)
{
Challenge(context);
return Task.FromResult(0);
}
private void Challenge(HttpAuthenticationChallengeContext context)
{
string parameter = null;
if (!string.IsNullOrEmpty(Realm))
{
parameter = "realm=\"" + Realm + "\"";
}
context.ChallengeWith("Bearer", parameter);
}
}
If I understand correctly, in ASP.NET Core, all I have to do is define the following in my startup:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Jwt:Issuer"],
ValidAudience = Configuration["Jwt:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
};
});
and I'm not sure whether or not I'll need the below but it looks like it:
services.AddMvc();
and all I could do is use the [Authorize] attribute but what if I want to replicate the Attribute I used in my ASP.NET MVC Web API 2.0?
Should I? I like the fact that I can see where things have gone wrong with the token. If it can be used the same way and assuming it is OK to do so, how do I do this? I haven't found anything that would help when googling for a solution?
Thanks.