Skip to content

Bug: After refreshing token it returns tokens for another account

Config:

  plugin :rodauth, json: :only do
    enable :oauth_jwt, :oidc
  end

Issue: When we want to refresh tokens for User_1 we retrieve tokens for User_X.

Place where i can happened:

oauth_base.rb

    def create_oauth_token_from_token(oauth_token, update_params) 
      redirect_response_error("invalid_grant") unless token_from_application?(oauth_token, oauth_application)

      rescue_from_uniqueness_error do
        oauth_tokens_ds = db[oauth_tokens_table]
        access_token = _generate_access_token(update_params)

        if oauth_refresh_token_protection_policy == "rotation"
          update_params = {
            **update_params,
            oauth_tokens_oauth_token_id_column => oauth_token[oauth_tokens_id_column],
            oauth_tokens_account_id_column => oauth_token[oauth_tokens_account_id_column],
            oauth_tokens_scopes_column => oauth_token[oauth_tokens_scopes_column]
          }
          refresh_token = _generate_refresh_token(update_params)
        else
          refresh_token = param("refresh_token")
        end

        # oauth_tokens_ds -> #<Sequel::Postgres::Dataset: "SELECT * FROM \"oauth_tokens\"">
        # update_params -> {:oauth_application_id=>1, :expires_in=>#<Sequel::SQL::DateAdd @expr=>#<Sequel::SQL::Constant @constant=>:CURRENT_TIMESTAMP>, @interval=>{:seconds=>300}>}
        # __update_and_return__ tries to update whole oauth_tokens table and returns first object in collection

        oauth_token = __update_and_return__(oauth_tokens_ds, update_params) # <-- HERE

        oauth_token[oauth_tokens_token_column] = access_token
        oauth_token[oauth_tokens_refresh_token_column] = refresh_token
        oauth_token
      end
    end

Also, similar issue we have when we use refresh token rotation strategy, it tries update all dataset with rotated refresh token but in this case we have an exception with unique constraint.