I am trying to come up with a simple API with ASP.NET Core and I would like to limit access to some endpoints based on the authorization header of the request.
In ASP.NET MVC5 I was able to do it by inheriting from the AuthorizationFilterAttribute and overriding the check method,m like so:
public class BasicAuthorizationAttribute : AuthorizationFilterAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
try
{
if (actionContext.Request.Headers.Authorization == null)
{
actionContext.Response = actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
return;
}
var authorizationToken = Encoding.UTF8.GetString(Convert.FromBase64String(actionContext.Request.Headers.Authorization.Parameter)).Split(':');
var username = authorizationToken[0];
var password = authorizationToken[1];
if (SecurityHelper.Login(username, password))
{
Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(username), null);
actionContext.RequestContext.Principal = Thread.CurrentPrincipal;
}
else
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
return;
}
} catch
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
return;
}
}
}
But from what it seems, Core uses an entirely different authorization system, which seems to require much more code and the setup doesn't seem like it's meant to be used with header checks. The entire Policy system seems like it's overcomplicated for this case. Is that what I should be using for this case? Or is there some built-in alternative for checking basic auth?
Thank you!
You needn't to add header as claims , you can access the authorization header by injecting an instance of an IHttpContextAccessor into your AuthorizationHandler :
public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
{
IHttpContextAccessor _httpContextAccessor = null;
public MinimumAgeHandler(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
MinimumAgeRequirement requirement)
{
HttpContext httpContext = _httpContextAccessor.HttpContext;
string authHeader = httpContext.Request.Headers["Authorization"];
if (authHeader != null && authHeader.StartsWith("Basic "))
{
// Get the encoded username and password
var encodedUsernamePassword = authHeader.Split(' ', 2, StringSplitOptions.RemoveEmptyEntries)[1]?.Trim();
// Decode from Base64 to string
var decodedUsernamePassword = Encoding.UTF8.GetString(Convert.FromBase64String(encodedUsernamePassword));
// Split username and password
var username = decodedUsernamePassword.Split(':', 2)[0];
var password = decodedUsernamePassword.Split(':', 2)[1];
// Check if login is correct
}
........
if (.....)
{
context.Succeed(requirement);
}
//TODO: Use the following if targeting a version of
//.NET Framework older than 4.6:
// return Task.FromResult(0);
return Task.CompletedTask;
}
}
You may need to register this in your DI setup , as follows:
services.AddHttpContextAccessor();
Injecting the IHttpContextAccessor in the Constructor is not needed.
You can access the HttpContext by doing
if (context.Resource is HttpContext httpContext)
{
...
}
or for MVC
// Requires the following import:
// using Microsoft.AspNetCore.Mvc.Filters;
if (context.Resource is AuthorizationFilterContext mvcContext)
{
// Examine MVC-specific things like routing data.
}
Source: https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-6.0#access-mvc-request-context-in-handlers
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With