More OAuth 2.0 Surprises: The Refresh Token

Cory Forsyth
3 min readJan 15, 2016

Last week I wrote a post about some of the things about OAuth that have surprised me as I learned more about it for Torii. This is a follow-up post focused on the OAuth 2 refresh token.

As I explained in the first post, access tokens are the primary goal of an OAuth client. They are what allow you to read/write data on behalf of a user. Access tokens offer a lot of power, however, and when using an OAuth flow to obtain them there is a lot of risk — aspects of the OAuth flow are difficult to secure properly. (There is a very long, very detailed OAuth 2 Threat Model IETF draft that will give you a taste for all the ways thing can go wrong.)

Since access tokens are so powerful yet also so potentially insecure, their risk is mitigated by giving them short-lived expiration windows. If they’re hard to safeguard properly, at least they don’t last very long. However, this introduces another difficulty for web programmers — how to continue to access data on behalf of your users when their access tokens expire? Enter refresh tokens.

Refresh tokens can be issued by OAuth providers alongside access tokens. Typically this happens when the OAuth client requests an access scope that warrants long-lived or offline access (often the name of the scope is “offline”, but there’s no specification for this so the value may vary). Refresh tokens can also expire but they often don’t, or have very long expiration times relative to access tokens. Because refresh tokens are more valuable than access tokens they are usually only issued via the OAuth “Authorization Code Grant” flow which uses authenticated backend-server-to-backend-server communication and not via the “Implicit Grant” flow. The OAuth 2 spec doesn’t enforce this, though.

Note: Auth0 has an excellent write-up about refresh tokens and JWTs that is worth reading.

Misconception: “Refresh tokens refresh an access token.”

When refresh tokens were first explained to me, I was told something along the lines that a refresh token is used to refresh an access token. The word “refresh” certainly implies that that is the case. When I thought about it this way I imagine the access token as a battery-operated toy with dead batteries. It is “stale”, and cannot be used. In order to “refresh” it you replace the batteries and now the freshened toy works again.

But that is not what a refresh token does. Access tokens do not become stale only to be refreshed later on and reused. Access tokens expire, never to be valid again. A refresh token is not tied to an access token. It is simply used to get a new, valid access token when you need it.

When do you need a new access token? When the access token you are trying to use is expired or otherwise not valid.

How do you know when your access token is not valid? By attempting to use it and having the OAuth provider reject it.

A few more notes on what refresh tokens do and how they can be used:

  • Refresh tokens are not connected to access tokens. They do not “refresh” a given access token.
  • You do not even provide an access token when using the refresh flow. It just takes a valid refresh token and gives you an access token.
  • Refresh tokens are (initially) provided by OAuth providers alongside access tokens in certain circumstances that vary by the provider. Typically you’ll be able to get a refresh token when using the Authorization Code Grant and requesting an “offline” scope.
  • Refresh tokens can expire, although their expiration time is usually much longer than access tokens.
  • Refresh tokens can become invalid in other ways (for example if your user revokes your OAuth client app’s access — in this case all your refresh tokens and access tokens for that provider would be invalidated).
  • If your refresh token is invalid and also don’t have a valid access token for a user, you must send them through an OAuth authorization flow again.
  • Refresh tokens cannot be used for read/write access to a user’s information. Only access tokens do this. Refresh tokens are only used to get new access tokens, not read data.

--

--

Cory Forsyth

Lifelong learner and technologist, based in NYC. Engineer @ Addepar, formerly co-ran Ember consultancy 201 Created.