Identity Server Refresh Token Resource Owner Passw

2020-07-23 05:09发布

问题:

I'm using IdentityServer to control access to an API. I have a separate authentication API which issues the tokens and validates access requests to secure API's.

I give users the ability to generate an access token through a secure web application. I am using the resource owner password credential flow.

Is there a way I can issue a refresh token without the user having to log in and request it? Or is there a way I can set the expiration of the initial access token?

Code

This is the code i'm using to generate tokens.

DiscoveryResponse disco = await DiscoveryClient.GetAsync("http://localhost:27144");
  TokenClient tokenClient = new TokenClient(disco.TokenEndpoint, "My Client", "MySecret");
  TokenResponse tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync("testUser", "testPassword");

回答1:

Yes, this can be accomplished with Refresh Tokens.

  • Set AllowOfflineAccess = true on the client config
  • Include offline_access in the scope on the initial token request

The token response will now include a RefreshToken in addition to the AccessToken. Return the AccessToken to the client and hold on to the RefreshToken.

When a new AccessToken is needed, request one using the RequestRefreshTokenAsync method on TokenClient. The name is confusing - you are actually requesting a new AccessToken FROM the RefreshToken.

TokenResponse refreshTokenResponse = await tokenClient.RequestRefreshTokenAsync("RefreshTokenGoesHere");

There are two ways to manage the RefreshToken expiration. This is controlled by the RefreshTokenExpiration property:

  • Sliding Expiration
  • Absolute Expiration

If sliding expiration is set, the refresh token lifetime will renew after each refresh.

There's also a RefreshTokenUsage property, which determines if a token's can be reused or are one-use only. If set to one-use only with sliding expiration, you'll simply get a new RefreshToken to hold on to on each request.

For expiration timing, there's SlidingRefreshTokenLifetime and AbsoluteRefreshTokenLifetime. Both can be used simulatenousely. For example, if sliding refresh tokens were enabled, the sliding expiration could be 30 days while the absolute expiration could be 1 year. This would allow the user 30 days of inactivity before needing to log in again, but if the user stays active, 1 year of login-free use.

It's important to note in all cases the RefreshToken should never be returned to the user - only the access token should. You'll need some data storage mechanism to hold on to the refresh tokens and their expiration dates.



回答2:

I stand by kg743's answer, but for anyone else stuck I believe I can save some trouble:

Include the scope with a space, like this:

Scopes = "scope1 scope2 offline_access scope3"

I kept including it with a comma(,) or semi-colon(;) and it couldn't work for me.