Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refreshing access tokens in IdentityServer4 clients

I wonder how to refresh a access token in a IdentityServer4 client using the hybrid flow and which is built using ASP.NET Core MVC.

If I have understood the whole concept correctly the client first need to have the "offline_access" scope in order to be able to use refresh tokens which is best practice to enable short lived access tokens and ability to revoke refresh tokens preventing any new access tokens to be issued to the client.

I successfully get a access token and a refresh token, but how should I handle the actual update procedure of the access token in the MVC client?

Can the OpenId Connect (OIDC) middleware handle this automatically? Or should I rather check the expire time of the access token everywhere I call WEB Api's by basically check if the access token have expired or will expire very soon (upcoming 30 seconds) then refresh the access token by calling the token endpoint using the refresh token?

Is it recommended to use the IdentityModel2 library TokenClient extension method RequestRefreshTokenAsync in my Controller action methods for calling the token endpoint?

I have seen code that in the OIDC middleware events request access token and using the response store a claim containing a expire datetime. The problem is that my OIDC in somehow already request a access token automatically so it doesn't feel good to request a new access token directly after recieving the first one.

Example of a Controller action method without access token refresh logic:

public async Task<IActionResult> GetInvoices()
    {
        var token = await HttpContext.Authentication.GetTokenAsync("access_token");

        var client = new HttpClient();
        client.SetBearerToken(token);

        var response = await client.GetStringAsync("http://localhost:5001/api/getInvoices");
        ViewBag.Json = JArray.Parse(response).ToString();

        return View();
    }
like image 484
Jonas Avatar asked Dec 15 '16 15:12

Jonas


People also ask

How do you use Refresh token in identityserver4?

Requesting an access token using a refresh tokenTo get a new access token, you send the refresh token to the token endpoint. This will result in a new token response containing a new access token and its expiration and potentially also a new refresh token depending on the client configuration (see above).

How do you refresh access tokens?

To refresh your access token as well as an ID token, you send a token request with a grant_type of refresh_token . Be sure to include the openid scope when you want to refresh the ID token. If the refresh token is valid, then you get back a new access and the refresh token.

How do access tokens and refresh tokens work?

Normally, a user with an access token can only access protected resources or perform specific actions for a set period of time, which reduces the risk of the token being compromised. A refresh token allows the user to get a new access token without needing to log in again.

Does PKCE support refresh tokens?

Using an Authorization Code flow with PKCE, a frontend web application can request identity tokens, access tokens and refresh tokens. With a refresh token, the frontend application can quickly obtain new access tokens.


1 Answers

The OIDC middleware will not take care of this for you. It's being executed when it detects a HTTP 401 response, it then redirects the user to IdentityServer login page. After the redirection to your MVC application, it will turn claims into a ClaimsIdentity and pass this on to the Cookies middleware which will materialise that into a session cookie.

Every other request will not involve the OIDC middleware as long as the cookie is still valid.

So you have to take care of this yourself. Another thing you want to consider is that whenever you're going to refresh the access token, you'll have to update the existing one so you don't lose it. If you don't do this, the session cookie will always contain the same token - the original one - and you'll refresh it every time.

A solution I found is to hook that into the Cookies middleware. Here's the general flow:

  • On every request, use the Cookies middleware events to inspect the access token
  • If it's close to its expiration time, request a new one
  • Replace the new access and refresh tokens in the ClaimsIdentity
  • Instruct the Cookies middleware to renew the session cookie so it contains the new tokens

What I like with this approach is that in your MVC code, you're pretty much guaranteed to always have a valid access token, unless refereshing the token keeps failing several times in a row.

What I don't like is that it's very tied to MVC - more specifically the Cookies middleware - so it's not really portable.

You can have a look at this GitHub repo I put together. It indeed uses IdentityModel as this takes care of everything and hides most of the complexity of the HTTP calls you'd have to make to IdentityServer.

like image 56
Mickaël Derriey Avatar answered Sep 30 '22 03:09

Mickaël Derriey