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

ruby-on-rails - google - rails doorkeeper api



Actualizar token con Omniauth-oauth2 en la aplicaciĆ³n Rails (5)

Aquí hay información, demasiado para enumerar here . Puede depender del proveedor que está utilizando y su uso permitido del refresh-token

Estoy usando omniauth-oauth2 en rieles para autenticar en un sitio que admite oauth2. Después de hacer el baile de oauth, el sitio me da lo siguiente, que luego persisto en la base de datos:

  1. Token de acceso
  2. Expires_AT (ticks)
  3. Actualizar token

¿Existe un método omniauth para actualizar el token automáticamente después de que caduque o debo escribir un código personalizado para hacer lo mismo?

Si se va a escribir un código personalizado, ¿es un ayudante el lugar correcto para escribir la lógica?


De forma similar a otras respuestas, seguí este enfoque, donde se usa el modelo que almacena los tokens de autenticación y actualización, abstrayendo las interacciones de API de esa lógica.

Ver https://.com/a/51041855/1392282


De hecho, la gema omniauth-oauth2 y su dependencia, oauth2 , tienen incorporada alguna lógica de actualización.

Ver en https://github.com/intridea/oauth2/blob/master/lib/oauth2/access_token.rb#L80

# Refreshes the current Access Token # # @return [AccessToken] a new AccessToken # @note options should be carried over to the new AccessToken def refresh!(params = {}) fail(''A refresh_token is not available'') unless refresh_token params.merge!(:client_id => @client.id, :client_secret => @client.secret, :grant_type => ''refresh_token'', :refresh_token => refresh_token) new_token = @client.get_token(params) new_token.options = options new_token.refresh_token = refresh_token unless new_token.refresh_token new_token end

Y en https://github.com/intridea/omniauth-oauth2/blob/master/lib/omniauth/strategies/oauth2.rb#L74 :

self.access_token = access_token.refresh! if access_token.expired?

Por lo tanto, es posible que no pueda hacerlo directamente con omniauth-oauth2, pero ciertamente puede hacer algo similar a esto con oauth2:

client = strategy.client # from your omniauth oauth2 strategy token = OAuth2::AccessToken.from_hash client, record.to_hash # or token = OAuth2::AccessToken.new client, token, {expires_at: 123456789, refresh_token: "123"} token.refresh!


La respuesta de Eero me abrió un camino para resolver esto. Tengo una preocupación de ayuda para mis clases que me da un servicio de Gmail. Como parte de este proceso, el objeto de usuario (que contiene la información de autenticación de google) se verifica si ha caducado. Si es así, se actualiza antes de devolver el servicio.

def gmail_service(user) mail = Google::Apis::GmailV1::GmailService.new # Is the users token expired? if user.google_token_expire.to_datetime.past? oauth = OmniAuth::Strategies::GoogleOauth2.new( nil, # App - nil seems to be ok?! "XXXXXXXXXX.apps.googleusercontent.com", # Client ID "ABC123456" # Client Secret ) token = OAuth2::AccessToken.new( oauth.client, user.google_access_token, { refresh_token: user.google_refresh_token } ) new_token = token.refresh! if new_token.present? user.update( google_access_token: new_token.token, google_token_expire: Time.at(new_token.expires_at), google_refresh_token: new_token.refresh_token ) else puts("DAMN - DIDN''T WORK!") end end mail.authorization = user.google_access_token mail end


Omniauth no ofrece esta funcionalidad lista para usar, por lo que utilicé la respuesta anterior y otra respuesta SO para escribir el código en mi modelo 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

Y antes de realizar la llamada API usando el token de acceso, puede llamar al método de esta manera, donde current_user es el usuario registrado.

current_user.refresh_token_if_expired

Asegúrese de instalar la gema rest-client y agregue la directiva require ''rest-client'' que require ''rest-client'' en el archivo de modelo. ENV[''DOMAIN''] , ENV[''APP_ID''] y ENV[''APP_SECRET''] son variables de entorno que pueden configurarse en config/environments/production.rb (o desarrollo)