简体   繁体   中英

How to Authorize Using JWT token

I have a web api end point that give me JWT token. It is not an fully authorization server. It just can generate a JWT token.

Now I have another web app written in aspnet core. In which inside the startup.cs I have added the following lines so that I can authorize using the JWT token I receive

            services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

        }).AddJwtBearer(configureOptions =>
        {...});

I also have a login form (in the web app) where user enters username and password that I send to web api and get the token. And to protect any controller in the web app I just use the [Authorize] attribute.

Everything works fine until the token expires. The token is very short lived but it does come with a refresh token.

My question is that , how can I detect that the Token (from the web api) is now expired and I need to get a new one using the refresh token. I know that in javascript world I can intercept the http request and renew the token with the refresh token.

But how do I do this in an aspnet core client app??

(NOTE: I do not want to use any authentication server like IdentityServer4 etc)

Thank you in advance!!

You can totally achieve what you want:

services
    .AddAuthentication()
    .AddJwtBearer("Firebase", options =>
    {
        options.Authority = "https://securetoken.google.com/my-firebase-project"
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuer = "my-firebase-project"
            ValidateAudience = true,
            ValidAudience = "my-firebase-project"
            ValidateLifetime = true
        };
    })
    .AddJwtBearer("Custom", options =>
    {
        // Configuration for your custom
        // JWT tokens here
    });

services
    .AddAuthorization(options =>
    {
        options.DefaultPolicy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("Firebase", "Custom")
            .Build();
    });

Let's go through the differences between your code and that one.

AddAuthentication has no parameter If you set a default authentication scheme, then on every single request the authentication middleware will try to run the authentication handler associated with the default authentication scheme. Since we now have two opssible authentication schemes, there's no point in running one of them.

Use another overload of AddJwtBearer Every single AddXXX method to add an authentication has several overloads:

One where the default authentication scheme associated with the authentication method is used, as you can see here for cookies authentication One where you pass, in addition to the configuration of the options, the name of the authentication scheme, as on this overload Now, because you use the same authentication method twice but authentication schemes must be unique, you need to use the second overload.

Update the default policy Since the requests won't be authenticated automatically anymore, putting [Authorize] attributes on some actions will result in the requests being rejected and an HTTP 401 will be issued.

Since that's not what we want because we want to give the authentication handlers a chance to authenticate the request, we change the default policy of the authorization system by indicating both the Firebase and Custom authentication schemes should be tried to authenticate the request.

That doesn't prevent you from being more restrictive on some actions; the [Authorize] attribute has an AuthenticationSchemes property that allows you to override which authentication schemes are valid.

If you have more complex scenarios, you can make use of policy-based authorization. I find the official documentation is great.

Let's imagine some actions are only available to JWT tokens issued by Firebase and must have a claim with a specific value; you could do it this way:

services
    .AddAuthorization(options =>
    {
        options.DefaultPolicy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("Firebase", "Custom")
            .Build();

        options.AddPolicy("FirebaseAdministrators", new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("Firebase")
            .RequireClaim("role", "admin")
            .Build());
    });

You could then use [Authorize(Policy = "FirebaseAdministrators")] on some actions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM