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");
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.
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.