12
votes

I am porting an ASP.NET Web API 4.6 OWIN application to ASP.NET Core 2.1. The application is working based on JWT token. But the token in passed via cookie instead of header. I'm not sure why headers are not used, it is just the situation that I have to deal with.

Consider that authentication is not done via cookie. The cookie is just used as a transfering media. In the legacy application CookieOAuthBearerProvider is employed to extract JWT token from cookie. Configuration code is as like this:

    app.UseJwtBearerAuthentication(
        new JwtBearerAuthenticationOptions
        {
            AuthenticationMode = AuthenticationMode.Active,
            AllowedAudiences = new[] { audienceId },
            IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
            {
                new SymmetricKeyIssuerSecurityTokenProvider(issuer, audienceSecret)
            },
            Provider = new CookieOAuthBearerProvider("token")
        });
}

CookieOAuthBearerProvider class source source code is as follow:

public class CookieOAuthBearerProvider : OAuthBearerAuthenticationProvider
{
    readonly string _name;
    public CookieOAuthBearerProvider(string name)
    {
        _name = name;
    }

    public override Task RequestToken(OAuthRequestTokenContext context)
    {
        var value = context.Request.Cookies[_name];

        if (!string.IsNullOrEmpty(value))
        {
            context.Token = value;
        }

        return Task.FromResult<object>(null);
    }

This solution is discussed here with more detail.

Now I need to implement similar solution for ASP.NET Core. Problem is that UseJwtBearerAuthentication does not exists in ASP.NET Core anymore and I do not know how I can introduce a custom AuthenticationProvider.

Any helps is highly appreciated.

UPDATE: There is a solution that tries to validate JWT by its own code. It is not what I need. I'm just searching for a way to pass token recieved from cookie to header reader.

1

1 Answers

24
votes

In ASP.NET Core 2.0, the authentication system was somewhat overhauled. Rather than using e.g. UseJwtBearerAuthentication as middleware, ASP.NET Core 2.0+ configures things using DI. For example, this looks something like this:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options => {
            // ...
        });
}

With that out of the way, the next question would be: how do we instruct the JwtBearer authentication process to look at a cookie using this new system?

That options object being passed in to AddJwtBearer contains an Events property of its own, which allows you to customise various parts of the process. Using OnMessageReceived, you can achieve what you're looking for:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options => {
            options.Events = new JwtBearerEvents
            {
                OnMessageReceived = context =>
                {
                    context.Token = context.Request.Cookies["CookieName"];
                    return Task.CompletedTask;
                }
            };
        });
}

By setting context.Token, you're telling the JwtBearer process that you've taken care of extracting the token yourself.

Here's a useful migration document that explains the authentication changes in more detail.