Enable Refresh Token Credentials

jondavidchristopher edited this page Oct 28, 2015 · 7 revisions

Refresh tokens are credentials used to obtain access tokens. For more information about how they work, check out the OAuth 2 section about refresh tokens.

In particular, note that access tokens obtained via the client credentials and implicit grant flows can not be refreshed using a refresh token.

Configuration

To enable refresh tokens in your provider, go to initializers/doorkeeper.rb and add (or uncomment) this line:

Doorkeeper.configure do
  # Issue access tokens with refresh token (disabled by default)
  use_refresh_token
end

This is basically everything you need to do. From now on, your provider will be issuing refresh tokens. This means that client applications will be able to request new access tokens in case the old ones have expired.

Doorkeeper implementation

The gem implements refresh token rotation, which means that every access token refresh request, it will issue a new refresh token. Previous tokens are invalidated (revoked). For refreshed access tokens, the scopes are identical from the previous access token.

Flow

The flow would look like this (from OAuth spec):

  +--------+                                           +---------------+
  |        |--(A)------- Authorization Grant --------->|               |
  |        |                                           |               |
  |        |<-(B)----------- Access Token -------------|               |
  |        |               & Refresh Token             |               |
  |        |                                           |               |
  |        |                            +----------+   |               |
  |        |--(C)---- Access Token ---->|          |   |               |
  |        |                            |          |   |               |
  |        |<-(D)- Protected Resource --| Resource |   | Authorization |
  | Client |                            |  Server  |   |     Server    |
  |        |--(E)---- Access Token ---->|          |   |               |
  |        |                            |          |   |               |
  |        |<-(F)- Invalid Token Error -|          |   |               |
  |        |                            +----------+   |               |
  |        |                                           |               |
  |        |--(G)----------- Refresh Token ----------->|               |
  |        |                                           |               |
  |        |<-(H)----------- Access Token -------------|               |
  +--------+           & Optional Refresh Token        +---------------+

To understand refresh tokens better, we highly recommend to check out the spec pages about refresh token:

Testing with OAuth2 gem

Assuming that you have a provider with doorkeeper installed running on localhost:3000

client = OAuth2::Client.new(client_id, client_secret, :site => site)
puts client.auth_code.authorize_url(:redirect_uri => redirect_uri)
# => http://localhost:3000/oauth/authorize?response_type=code&client_id=...&redirect_uri=http%3A%2F%2Flocalhost%3A9393%2Fcallback

Authorize the client and request the first access token with:

token = client.auth_code.get_token(code, :redirect_uri => redirect_uri)
# POST '/oauth/token' with grant_type set to authorization_code
# => #<OAuth2::AccessToken:0x007fbcd38415b0 ...>

If you have enabled the refresh token, you can check the generated tokens with:

token.token
# => 'c6212bdd8e4a2dd8218ac22d9cc703eac5ac5f439bafd31594d96ce5be6effa0'
token.refresh_token
# => '4ffee626f0058e1bc1f1a29a76dc4ac5978b27e674f58b7e58f4bd6872b0452b'

When time passes and the access token expires, you can refresh the old token, so you can continue accessing the provider's API.

token.expired?
# => true

new_token = token.refresh!
# POST '/oauth/token' with grant_type set to refresh_token
# => #<OAuth2::AccessToken:0x007fbcd1ae4850 ...>

new_token.token
# => '67aa16d8c0476d2fb478df2876f6d3d3b8eda0b5ff2020960a7d6ad781184258'

new_token.refresh_token
# => '3dde18e1532f1d6f256caa89c366cfed3cd5bce68066ac8f1dbb053dbf65b90f'

new_token.expires_at
# => 1446085207

With this flow, you'll have access to the protected resources until the user revokes access to your application.

You can see how to customize the token expiration here.

Old versions of doorkeeper

Refresh tokens requires database changes, so check out how to migrate from old versions of doorkeeper