2012-04-20 10 views
22

Sto scrivendo un'app Rails che utilizza omniauth-facebook per autenticare l'utente contro FB (e ottenere un token di accesso OAuth per l'utente). L'app utilizza quindi Koala per effettuare varie chiamate all'API grafico FB, utilizzando quel token OAuth salvato.Scadenza e rinnovo del token Facebook, con Koala e omniauth-facebook

Aggiorno il token salvato ogni volta che l'utente si autentica di nuovo (in genere quando accede alla mia app). Anche così, il token salvato scadrà (o altrimenti non sarà più valido) di volta in volta.

Qual è la migliore pratica in merito alla protezione da errori di autenticazione e aggiornamento del token durante l'utilizzo di Koala?

Tutte le chiamate devono essere incapsulate nei blocchi begin/rescue, con un gestore di eccezioni che rianalizza l'utente contro FB?

C'è un modo (utilizzando Koala) per sfruttare il processo di estensione dei token di accesso descritto here? In caso contrario, ci sono le migliori pratiche per scrivere il mio codice per estrarre il nuovo token da una chiamata Koala?

risposta

16

Quello che ho è un before_filter che viene attivato su ogni pagina che richiede una sessione di Facebook attiva. Qualcosa del genere dovrebbe funzionare:

before_filter :reconnect_with_facebook 
    def reconnect_with_facebook 
    if current_account && current_account.token_expired?(session[:fb]["expires"]) 

    # re-request a token from facebook. Assume that we got a new token so 
    # update it anyhow... 
    session[:return_to] = request.env["REQUEST_URI"] unless request.env["REQUEST_URI"] == facebook_request_path 
    redirect_to(with_canvas(facebook_request_path)) and return false 
    end 
end 

Il token_expired? metodo è simile al seguente:

def token_expired?(new_time = nil) 
    expiry = (new_time.nil? ? token_expires_at : Time.at(new_time)) 
    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 
+0

Grazie per la risposta. Dove/come viene impostata la sessione [: fb] ["espira"]? Lo usi nel metodo reconnect_with_facebook qui sopra. –

+0

l'ho impostato la prima volta che qualcuno accede con successo per creare una sessione. Tutte le altre connessioni sono considerate "riconnessioni" – heavysixer

+0

Grazie. Ho implementato un po 'diversamente, ma questo è stato utile per farmi sulla strada giusta. –

16

mi sono imbattuto this post che adatta il codice dal Railscast on Facebook per mostrare come è possibile scambiare il token di breve durata per i 60 giorni uno:

user.rb

def self.from_omniauth(auth) 

    # immediately get 60 day auth token 
    oauth = Koala::Facebook::OAuth.new(ENV["FACEBOOK_APP_ID"], ENV["FACEBOOK_SECRET"]) 
    new_access_info = oauth.exchange_access_token_info auth.credentials.token 

    new_access_token = new_access_info["access_token"] 
    # Facebook updated expired attribute 
    new_access_expires_at = DateTime.now + new_access_info["expires_in"].to_i.seconds 

    where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user| 
     user.provider = auth.provider 
     user.uid = auth.uid 
     user.name = auth.info.name 
     user.image = auth.info.image 
     user.email = auth.info.email 
     user.oauth_token = new_access_token #originally auth.credentials.token 
     user.oauth_expires_at = new_access_expires_at #originally Time.at(auth.credentials.expires_at) 
     user.save! 
    end 
    end 
+0

Grazie per lo snippet di codice! – okysabeni

+0

Grazie questo è un buon metodo. Ci ho messo un po 'a capire perché i miei test si sono lamentati di un 'Koala :: Facebook :: OAuthTokenRequestError: tipo: OAuthException, codice: 101, messaggio: Parametro client_id mancante. [HTTP 400] '. Alla fine, mi sono reso conto che non avevo definito 'ENV [" FACEBOOK_APP_ID "]' o 'ENV [" FACEBOOK_SECRET "]' per il mio ambiente di test in 'secrets.yml'. – DazBaldwin

0

Si può fare qualcosa di simile in cui si controlla se il token di accesso è scaduto e ne genera un altro.

%w[facebook].each do |provider| 
    scope provider, -> { where(provider: provider) } 
end 

def client 
    send("#{provider}_client") 
end 

def expired? 
    expires_at? && expires_at <= Time.zone.now 
end 

def access_token 
    send("#{provider}_refresh_token!", super) if expired? 
    super 
end 

def facebook_refresh_token!(token) 
    new_token_info = 
    Koala::Facebook::OAuth.new.exchange_access_token_info(token) 
    update(access_token: new_token_info["access_token"], expires_at: Time.zone.now + new_token_info["expires_in"]) 
end 

È possibile controllare gorails screencast che spiega questo sulla profondità.

Problemi correlati