Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use 'refresh_token' in IdentityServer 4?

I'm using .net core with IdentityServer 4. I have a Web api, and an MVC app which accesses secure endpoints on the api. It's very similar in setup to the IdentityServer quickstart:

https://github.com/IdentityServer/IdentityServer4.Samples/tree/release/Quickstarts/6_AspNetIdentity

I'm finding that my access_tokens are expiring, and I'd like to understand how to renegotiate refresh_tokens.

Take the following code for example (taken from the quickstart here):

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

        var client = new HttpClient();
        client.SetBearerToken(accessToken);
        var content = await client.GetStringAsync("http://localhost:5001/identity");

        ViewBag.Json = JArray.Parse(content).ToString();
        return View("json");
    }

If the access_token has expired, it will fail with 401 response. Is there a built-in mechanism for re-negotiating the access_token using the refresh_token?

like image 429
Stephen Ellis Avatar asked May 25 '17 07:05

Stephen Ellis


People also ask

What is a refresh token in Identity server 4?

Since access tokens have finite lifetimes, refresh tokens allow requesting new access tokens without user interaction. Refresh tokens are supported for the following flows: authorization code, hybrid and resource owner password credential flow.

What is sliding token refresh lifetime?

Sliding: when refreshing the token, the lifetime of the refresh token will be renewed (by the amount specified in SlidingRefreshTokenLifetime). The lifetime will not exceed the absolute lifetime.

How do I get refresh token?

To get a refresh token, you send a request to your Okta Authorization Server. The only flows that support refresh tokens are the authorization code flow and the resource owner password flow.

What is the use of identityserver4?

IdentityServer is an authentication server that implements OpenID Connect (OIDC) and OAuth 2.0 standards for ASP.NET Core. It's designed to provide a common way to authenticate requests to all of your applications, whether they're web, native, mobile, or API endpoints.


1 Answers

There is not a build in system to refresh the access_token. However you can use the IdentityModel package to request a new access_token with a refresh_token.

The Client has a property AllowOfflineAccess which you should set to true in the IdentityServer. Note that this does not work for the implicit/client credentials flow.

  • Always refresh the access_token prior to making the call to the protected resource
  • Check if the current access_token is about to expire by checking its lifetime and request a new access_token with the refresh_token (personal preference)
  • Wait for the API to return the 401 and request a new access_token with the refresh_token

Prior to this code you can check the access_token lifetime and/or wrap this code in a service before you request a new access_token

    var discoveryResponse = await DiscoveryClient.GetAsync("IdentityServer url");
    if (discoveryResponse.IsError)
    {
        throw new Exception(discoveryResponse.Error);
    }
    
    var tokenClient = new TokenClient(discoveryResponse.TokenEndpoint, "ClientId", "ClientSecret");
    // This will request a new access_token and a new refresh token.
    var tokenResponse = await tokenClient.RequestRefreshTokenAsync(await httpContext.Authentication.GetTokenAsync("refresh_token"));
    
    if (tokenResponse.IsError)
    {
        // Handle error.
    }
    
    var oldIdToken = await httpContext.Authentication.GetTokenAsync("id_token");
    
    var tokens = new List<AuthenticationToken>
    {
        new AuthenticationToken
        {
            Name = OpenIdConnectParameterNames.IdToken,
            Value = oldIdToken
        },
        new AuthenticationToken
        {
            Name = OpenIdConnectParameterNames.AccessToken,
            Value = tokenResult.AccessToken
        },
        new AuthenticationToken
        {
            Name = OpenIdConnectParameterNames.RefreshToken,
            Value = tokenResult.RefreshToken
        }
    };
    
    var expiresAt = DateTime.UtcNow.AddSeconds(tokenResult.ExpiresIn);
    tokens.Add(new AuthenticationToken
    {
        Name = "expires_at",
        Value = expiresAt.ToString("o", CultureInfo.InvariantCulture)
    });
    
    // Sign in the user with a new refresh_token and new access_token.
    var info = await httpContext.Authentication.GetAuthenticateInfoAsync("Cookies");
    info.Properties.StoreTokens(tokens);
    await httpContext.Authentication.SignInAsync("Cookies", info.Principal, info.Properties);

Taken from and slightly modified: Source

like image 172
user1336 Avatar answered Sep 21 '22 05:09

user1336