20

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.

Kirk Larkin
  • 84,915
  • 16
  • 214
  • 203
Afshar Mohebi
  • 10,479
  • 17
  • 82
  • 126

1 Answers1

38

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.

Kirk Larkin
  • 84,915
  • 16
  • 214
  • 203
  • would `context.Token` always been null or empty in this scope? is that why you mean by telling JwtBearer process that you'v taken care f extracting the token yourself? no processing would occur before or after? – Brett Caswell Jun 07 '21 at 18:32
  • 1
    @BrettCaswell Yes, it'll typically be `null` or empty here. You can trace through the latest GA of the source [here](https://github.com/dotnet/aspnetcore/blob/release/5.0/src/Security/Authentication/JwtBearer/src/JwtBearerHandler.cs#L69) to check it for yourself. – Kirk Larkin Jun 07 '21 at 18:46