Search code examples
c#asp.net-corebearer-tokenasp.net-authorization

Custom Bearer Token Authorization for ASP.Net Core


Is this an acceptable implementation of a custom bearer token authorization mechanism?

Authorization Attribute

public class AuthorizeAttribute : TypeFilterAttribute
{
    public AuthorizeAttribute(): base(typeof(AuthorizeActionFilter)){}
}

public class AuthorizeActionFilter : IAsyncActionFilter
{
    private readonly IValidateBearerToken _authToken;
    public AuthorizeActionFilter(IValidateBearerToken authToken)
    {
        _authToken = authToken;
    }

    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        const string AUTHKEY = "authorization";
        var headers = context.HttpContext.Request.Headers;
        if (headers.ContainsKey(AUTHKEY))
        {
            bool isAuthorized = _authToken.Validate(headers[AUTHKEY]);
            if (!isAuthorized)
                context.Result = new UnauthorizedResult();
            else
                await next();
        }
        else
            context.Result = new UnauthorizedResult();
    }
}

Validation Service. APISettings class is used in appSettings, but validation can be extended to use a database ... obviously :)

public class APISettings
{
    public string Key { get; set; }
}

public class ValidateBearerToken : IValidateBearerToken
{
    private readonly APISettings _bearer;

    public ValidateBearerToken(IOptions<APISettings> bearer)
    {
        _bearer = bearer.Value;
    }

    public bool Validate(string bearer)
    {
        return (bearer.Equals($"Bearer {_bearer.Key}"));
    }
}

Implementation

[Produces("application/json")]
[Route("api/my")]
[Authorize]
public class MyController : Controller

appSettings

"APISettings": {
"Key": "372F78BC6B66F3CEAF705FE57A91F369A5BE956692A4DA7DE16CAD71113CF046"

}

Request Header

Authorization: Bearer 372F78BC6B66F3CEAF705FE57A91F369A5BE956692A4DA7DE16CAD71113CF046

Solution

  • That would work, but it's kind of reinventing the wheel.

    I good approach these days is to use JWTs, you can find more info about it here: http://www.jwt.io/

    Some advantages are that it integrates quite nicely with asp.net core and you can also add some information to the token (username, role, etc). That way, you don't even need to access the database for validation (if you want to).

    Also, storing keys in appsettings file could lead to accidentally adding them to your source-code manager (security). You could use user secrets for local development (or disable the key when environment = dev) and environment variables for production.

    Here is one good example of how to use jwt with asp.net: https://jonhilton.net/2017/10/11/secure-your-asp.net-core-2.0-api-part-1-issuing-a-jwt/