JwtAuthProvider and RefreshToken cookie

Using the JwtAuthProvider + CustomCredentialsProvider and wanting to know how to configure/implement this pattern:

When JS client Authenticates, get back a HTTPOnly cookie containing the refresh_token (could also have the access_token), but need the access_token in the JSON response as well. (JS client needs to read the access_token and store in memory, and put in cross-origin Authorization header).

JS client then needs at anytime, to refresh the access_token. Ideally by calling AuthN server, with refresh_token_cookie and retrieving a new refresh_token in a cookie, and a new access_token in the JSON response.

Is this pattern either Supported or Supportable in the JwtAuthProvider?

The JwtAuthProvider does also register the ConvertSessionToTokenService which can provide the access_token in the response as well as force a refresh via request.PreserveSession = false.

I think that addresses your second part about refreshing the token at any time, but I think you would need to replicate the construction and returning of the token in your own CustomCredentialsProvider and include the access_token in your response. I’m not aware of how to do this with the standard AuthenticateResponse.

I’m also making a bunch of assumption about your OAuth2 and how it interacts with the JS client + SS server, any additional details would be appreciated.

Thanks @layoric.

The two pieces I think I am missing from the current JwtAuthProvider are:

  1. Being issued a cookie containing a refresh_token value. The current ss-tok contains only the access_token, but not the refresh_token. I don’t actually care if the cookie had both, but do need the refresh_token in there, or have a separate cookie (ss-tokref`?? with it in).
  2. I need an endpoint that can read this ss-tokref cookie, and return a JSON response with a new access_token in the body. I know that GET /session-to-token does something similar, just not sure its the same semantic?

Currently, the JSApp would want to just call Authenticate, and have returned the access_token and refresh_token (as it does now), but with both cookies when UseTokenCookie=true.

It would store the access_token from the JSON response in memory ready to stuff it into Authorization header on subsequent ajax calls (cross-domain).
It would keep the ss-tokref cookie in hand to refresh that access_token, whenever it expires or the browser tab is refreshed or opened (ie when lose access_token in memory).

I’ve added support for Refresh Token Cookies in this commit where you can choose to have RefreshToken Cookies returned at authentication in the ss-reftok in addition to ss-tok HTTP Only Cookies by configuring it on:

Plugins.Add(new AuthFeature(() => new AuthUserSession(),
    new IAuthProvider[] {
        new JwtAuthProvider {
            UseTokenCookie = true,
            UseRefreshTokenCookie = true,
        },
    }));

Where the GetAccessToken API used to generate new JWT Tokens from Refresh Tokens also supports accepting RefreshToken stored in ss-reftok Cookies.

Refresh Token Cookie support is now available from the latest v5.10.5 that’s now available on MyGet.

Thanks heaps @mythz, awesome.

I had attempted do do the same in a custom JwtAuthProvider and custom RefreshAccessTokenService. Looks similar to what you have done.

It turns out, that it needs 2 other things though.

  1. Since the ss-reftok cookie is now being sent, a call to Authenticate{Provider="Logout"} will now need to clear that new ss-reftok cookie as well as the other cookies, otherwise they are never actually logged out.
  2. An extension method IServiceClient.GetRefreshTokenCookie same as IServiceClient.GetTokenCookie

(or did I miss that you had already done that, in the commit somewhere?)

ok yeah nice catch, these are both in the latest v5.10.5 that’s now available on MyGet.

1 Like

FYI just a heads up, as using cookies for refresh tokens provides a nicer (i.e. maintenance-free) UX, it’s now being enabled by default (can be disabled) when JWT is configured with UseTokenCookie = true:

Plugins.Add(new AuthFeature(() => new AuthUserSession(),
    new IAuthProvider[] {
        new JwtAuthProvider {
            UseTokenCookie = true,
        },
    }));

Also all of ServiceStack’s Service Clients in all languages, i.e. C#, TypeScript/JS, Dart, Java/Kotlin, Swift all now include built-in support for Refresh Token Cookies where they’ll automatically fetch new Access Tokens & Auto Retry Requests on 401 Unauthorized responses.