Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In ASP.NET Core read JWT token from Cookie instead of Headers

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.

like image 598
Afshar Mohebi Avatar asked Sep 05 '18 11:09

Afshar Mohebi


People also ask

Can I use JWT with cookies?

On every request to server, the JWT will be read from Cookies and added in the Authorization header using Bearer scheme. The server can then verify the JWT in the request header (as opposed to reading it from the cookies).

Should I send JWT token in header or body?

Yep. When making requests that needs authorization or when accessing a part in your API that needs authentication, you need to send the jwt to the server for authentication. The common and best practice is too add it to the request header as authorization header.

How do I pass a JWT token in headers?

We can send this token to other endpoints. This can be done easily. We have to add an authorization header in our request and this will be a Bearer TOKEN. To avoid any manual copy-pasting of JWT token, we can use variables to add a script in the Tests tab of API request which is generating token.

How do I store JWT in HTTP only cookies?

HTTP Only JWT Cookie: In a SPA(Single Page Application) Authentication JWT token either can be stored in browser 'LocalStorage' or in 'Cookie'. Storing JWT token inside of the cookie then the cookie should be HTTP Only. The HTTP-Only cookie nature is that it will be only accessible by the server application.


1 Answers

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.

like image 165
Kirk Larkin Avatar answered Oct 04 '22 04:10

Kirk Larkin