OAuth2 Provider and refresh tokens

I am moving from a purely access_token on the wire architecture to using the AuthFeature() with its cookies on the wire.
We have our own OAuth2 server that serves up access_token as well as refresh_token that takes the users and applications credentials. Standard OAuth2 stuff.

As I understand it, once the access_token is obtained from the OAuth2 server (through our custom OAuth2Provider), the user is authenticated, and the access_token and potentially refresh_token is saved in the IAuthSession.
The session and session_id is created and stored.
The user is now authenticated as long as the ‘session_id/cookie’ is remembered by the client, or when the session expires (if configured to).

Now, we would like sessions created by authn with our OAuthProvider to expire on the same frequency as the access_token expires, but we want to use the refresh_token to create a new session (with a new access_token) when or before that happens. So that the user still remains authenticated, but we still permit the session/access_token to expire frequently.

Is this feasible? How and where in the code would it be done?

When the Session expires the User is unauthenticated, so you’ll need to refresh the Session/Token before this happens.

The built-in AuthProviders don’t provide a way to refresh tokens so you’ll need to create your own Service to fetch a new token before their session expires, if successful you can just resave the Session with the new Expiry, something like:

TimeSpan tokenExpiry;
var accessToken = MyRefreshToken(request.RefreshToken, out tokenExpiry);
if (accessToken != null)
{
    var session = base.SessionAs<AuthUserSession>();
    var provider = session.ProviderOAuthAccess.First(x => x.Provider="Name");
    provider.AccessToken = accessToken;
    this.SaveSession(session, tokenExpiry);
}

Before v4.0.62 of Servicestack there was no JWT Auth Providers out of the box, so we have implemented our custom solution based on this. We use it for mobile applications authentication.

We extended this example by using refresh tokens. Refresh tokens are saved by us in the storage and during invoking renew token request it it get from there and the new token is generated.

We would like to leave our custom solution to use Servicestack components (especially becasue standard user / password authentication is used in parallel for web).

My first idea for that is to override API Key Provider and add storing the keys in storage. Then override JWTAuthProvider and add there this custom API Key Provider to generate refresh token.
Client would firstly authenticate using login / password (and the session would be established) then he would use the token until it would expire.
After that he can use refresh token generated by API Key Provider to regenerate token and create new JWTAuthProvider session.

As you can see there is still lot custom work to do and before we start doing it I`d like to make sure if it is doable and it would not bring some other problems. @mythz What is your opinion about it?

Do you plan to provide similar refresh token solutions in the next versions of Servicestack?

We have a solution to transparently refresh expired JWT Tokens by using the ServiceClient’s OnAuthenticationRequired callback. It’s open to what authentication method you use to create a new JWT Token and the example shown uses an API Key to authenticate with the Auth Server. Is there a scenario you need Refresh Tokens for that you can’t achieve with this? IMO its simple, clean and intuitive that I can’t see why I’d prefer Refresh Tokens based solutions myself.

We haven’t implemented Refresh Tokens and wont be able to for a while as we have our hands full with .NET Core support which is the overwhelming highest priority feature right now. Please leave a feature request so we have a record of it and can measure interest in it.

As it looks like you plan to do a lot of customization I recommend working with a customized version of our JWT Implementation which is encapsulated in these 2 files:

If the implementation is generic enough and not too disruptive we can accept any changes that might be useful to others.