ruby-on-railsoauthruby-on-rails-4oauth-2.0omniauth

Refresh token using Omniauth-oauth2 in Rails application


I am using omniauth-oauth2 in rails to authenticate to a site which supports oauth2. After doing the oauth dance, the site gives me the following, which I then persist into the database:

  1. Access Token
  2. Expires_AT (ticks)
  3. Refresh token

Is there an omniauth method to refresh the token automatically after it expires or should I write custom code which to do the same?

If custom code is to be written, is a helper the right place to write the logic?


Solution

  • Omniauth doesn't offer this functionality out of the box so i used the previous answer and another SO answer to write the code in my model User.rb

    def refresh_token_if_expired
      if token_expired?
        response    = RestClient.post "#{ENV['DOMAIN']}oauth2/token", :grant_type => 'refresh_token', :refresh_token => self.refresh_token, :client_id => ENV['APP_ID'], :client_secret => ENV['APP_SECRET'] 
        refreshhash = JSON.parse(response.body)
    
        token_will_change!
        expiresat_will_change!
    
        self.token     = refreshhash['access_token']
        self.expiresat = DateTime.now + refreshhash["expires_in"].to_i.seconds
    
        self.save
        puts 'Saved'
      end
    end
    
    def token_expired?
      expiry = Time.at(self.expiresat) 
      return true if expiry < Time.now # expired token, so we should quickly return
      token_expires_at = expiry
      save if changed?
      false # token not expired. :D
    end
    

    And before making the API call using the access token, you can call the method like this where current_user is the signed in user.

    current_user.refresh_token_if_expired
    

    Make sure to install the rest-client gem and add the require directive require 'rest-client' in the model file. The ENV['DOMAIN'], ENV['APP_ID'] and ENV['APP_SECRET'] are environment variables that can be set in config/environments/production.rb (or development)