Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refresh tokens are not being revoked when new access token is created #1462

Closed
verenion opened this issue Dec 14, 2020 · 2 comments
Closed

Comments

@verenion
Copy link

Steps to reproduce

  1. Create a new access token using the Authorisation Code grant type.
  2. Client saves refresh token and uses access token to access resources.
  3. Token expiry is set to 10 seconds (for testing), so after expiry, client uses refresh token to acquire new access token
  4. This generates a new access token with a new refresh token, but previous refresh/access token is still active, valid and never gets revoked.

Expected behavior

When an access token is generated from a refresh token, the previous access token should be revoked, according to the OAuth spec.

Actual behavior

Access tokens are never revoked, every refresh just causes a new access token to be created.

This is becoming a very large issue for us, we have fairly short-lived tokens on a very busy application. We are currently racking up 100m+ rows in oauth_access_tokens, and cleaning them out is pointless if it keeps creating more.

System configuration

Doorkeeper initializer:

Doorkeeper.configure do
  orm :active_record

  resource_owner_authenticator do
    if current_user
      current_user
    else
      # Refer the HERE document at the bottom on why this session variable
      # is being set.
      session[:user_return_to] = request.fullpath
      redirect_to(new_user_session_url)
    end
  end

  resource_owner_from_credentials do |_routes|
    User.authenticate(params[:email], params[:password])
  end

  access_token_expires_in 10.seconds

  access_token_generator '::Doorkeeper::JWT'

  use_refresh_token

  default_scopes  :public

  grant_flows %w(authorization_code)

  skip_authorization do |resource_owner, client|
    true
  end
end

Doorkeeper::JWT.configure do
  token_payload do |opts|

    exp = Time.now + 10.seconds
    user = User.find(opts[:resource_owner_id])
    iat         = Time.current.utc.to_i

    {
        iss: 'user-service',
        iat: iat,
        exp: exp.to_i,
        jti: SecureRandom.uuid,
        application_id: opts[:application].id,
        user: {
            id: user.member_id,
            username: user.name,
            email: user.email,
        }
    }
  end

  use_application_secret false

  secret_key "testsecret"

  secret_key_path File.join('/', 'app', 'secret.pem')

  encryption_method :rs256
end
@verenion
Copy link
Author

Forgot to add, we have the previous_refresh_token in the database, and from what I've read, this should be working correctly already.

@linhdangduy
Copy link
Contributor

Forgot to add, we have the previous_refresh_token in the database, and from what I've read, this should be working correctly already.

I have also check the code again.

If you don't migrate the previous_refresh_token column. The refresh_token will be revoke immediately when you use it to get new access token.

The previous_refresh_token is added from this pull. As it's description:

Also allows for refresh tokens to not be revoked until an access token created with that refresh token is successfully used once

Memo for the code related to previous_refresh_token:

@verenion So I think we can close this issue.

@verenion verenion closed this as completed Jan 6, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants