2

In our ASP .NET Core 2.0, Web API, when the user logs in, we generate a GUID and return that to the user after storing it in database. What is the best practice to validate this token when the user submits a request to a controller having Authorize attribute on it.

Should I override AuthorizeAttribute.OnAuthorization and put my custom logic in there ? or is there any other place where I should place my custom logic ?

Thanks in advance.

3
  • Yes. You need to write a custom Authorize attribute to suits for your own logic. disadvantage is there will be a DB call for each request. Commented Jan 22, 2018 at 10:49
  • Don't write a custom attribute. The Authorize attribute serves a very important function. What you need is a custom authorization handler that you add as a service in the Startup.cs file. Commented Jan 22, 2018 at 23:30
  • Hi @Brad, can you please provide a link to an example :) Commented Jan 23, 2018 at 9:23

2 Answers 2

1

In ASP .NET Core 2.0 you can write you own Middleware to validate token. You can see this video as exapmle - https://www.youtube.com/watch?v=n0llyujNGw8.

Summarily: 1. Create TokenMiddleware:

public class TokenMiddleware
{
    // always should be RequestDelegate in constructor
    private readonly RequestDelegate _next;
    public TokenMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    // always should be defiened Invoke or InvokeAsync with HttpContext and returned Task (You can also inject you services here - for example DataContext)
    public async Task InvokeAsync(HttpContext context, DataContext dataContext)
    {
        var validKey = true;

        // than you logic to validate token              

        if (!validKey)
        {
            context.Response.StatusCode = (int) HttpStatusCode.Forbidden;
            await context.Response.WriteAsync("Invalid Token");
        }
        // if validm than next middleware Invoke
        else
        {
            await _next.Invoke(context);
        }
    }
}

// Extension to IApplicationBuilder (to register you Middleware)
public static class TokenExtensions
{
    public static IApplicationBuilder UseTokenAuth(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<TokenMiddleware>();
    }
}
  1. Registred you Middleware in Startup:

app.UseTokenAuth();

Sign up to request clarification or add additional context in comments.

1 Comment

This is great - video link / presentation very helpful in understanding, thanks!
1

Question was made long time ago, but for people that might stumble upon it, here is the way I did it, taking advantage of authentication and authorization middlewares. The question doesn't have details about the way the token is passed in the request but I am assuming a standard Authorization header.

Create a custom AuthenticationHandler

MyCustomTokenHandler.cs

public class MyCustomTokenHandler: AuthenticationHandler<AuthenticationSchemeOptions>
{
    public MyCustomTokenHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
    {
    }

    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        if (!Request.Headers.ContainsKey("Authorization"))
        {
            return AuthenticateResult.NoResult();
        }
        if (!AuthenticationHeaderValue.TryParse(Request.Headers["Authorization"], out AuthenticationHeaderValue? headerValue))
        {
            return AuthenticateResult.NoResult();
        }
        if (!Scheme.Name.Equals(headerValue.Scheme, StringComparison.OrdinalIgnoreCase))
        {
            return AuthenticateResult.NoResult();
        }
        if (headerValue.Parameter == null)
        {
            return AuthenticateResult.NoResult();
        }
        //The token value is in headerValue.Parameter, call your db to verify it and get the user's data

        var claims = new[] { new Claim(ClaimTypes.Name, "username found in db") };
        //set more claims if you want
        var identity = new ClaimsIdentity(claims, Scheme.Name);
        var principal = new ClaimsPrincipal(identity);
        var ticket = new AuthenticationTicket(principal, Scheme.Name);
        return AuthenticateResult.Success(ticket);
    }
}

Register the handler and enable authorization

Program.cs

builder.Services.AddAuthentication("Bearer").AddScheme<AuthenticationSchemeOptions, MyCustomTokenHandler>("Bearer", null);
//...
var app = builder. Build();
app.UseAuthentication();
app.UseAuthorization();

Most of the code is inspired by this blog post: https://joonasw.net/view/creating-auth-scheme-in-aspnet-core-2

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.