Истечение срока действия и продление токена Facebook с помощью Koala и omniauth-facebook

Я пишу приложение Rails, которое использует omniauth-facebook для аутентификации пользователя по FB (и для получения токена доступа FB OAuth для пользователя). Затем приложение использует Koala для выполнения различных вызовов FB Graph API, используя сохраненный токен OAuth.

Я обновляю сохраненный токен каждый раз, когда пользователь повторно аутентифицируется (обычно, когда он входит в мое приложение). Даже в этом случае срок действия сохраненного токена истечет (или станет недействительным) время от времени.

Как лучше всего защитить себя от сбоев аутентификации и обновить токен при использовании Koala?

Должны ли все вызовы быть заключены в блоки begin / rescue с обработчиком исключений, который повторно аутентифицирует пользователя по FB?

Есть ли способ (с помощью Koala) воспользоваться процессом «расширения токенов доступа», описанным здесь? Если нет, есть ли лучшие практики по написанию моего собственного кода для извлечения нового токена самостоятельно из вызова Koala?


person Steve Bourne    schedule 20.04.2012    source источник


Ответы (3)


У меня есть before_filter, который запускается на каждой странице, требующей активного сеанса Facebook. Примерно так должно работать:

  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

Срок действия токена истек? метод выглядит так:

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
person heavysixer    schedule 01.05.2012
comment
Спасибо за ответ. Где / как устанавливается сессия [: fb] [истекает]? Вы используете его в описанном выше методе reconnect_with_facebook. - person Steve Bourne; 07.05.2012
comment
Я установил это при первом успешном входе в систему для создания сеанса. Все остальные подключения считаются повторными. - person heavysixer; 07.05.2012
comment
Спасибо. Я реализовал несколько иначе, но это помогло мне встать на правильный путь. - person Steve Bourne; 16.05.2012
comment
Как насчет обработки ситуаций, когда токен истекает преждевременно, например, когда пользователь меняет свой пароль в facebook или удаляет приложение? - person Christian Schlensker; 19.10.2012

Я наткнулся на этот пост, который адаптирует код из Railscast на Facebook, чтобы показать, как можно обменять недолговечный токен на 60-дневный. :

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
person manafire    schedule 23.05.2013
comment
Спасибо, это хороший метод. Мне потребовалось время, чтобы понять, почему мои тесты жаловались на Koala::Facebook::OAuthTokenRequestError: type: OAuthException, code: 101, message: Missing client_id parameter. [HTTP 400]. В конце концов я понял, что не определил ENV["FACEBOOK_APP_ID"] или ENV["FACEBOOK_SECRET"] для своей тестовой среды в secrets.yml. - person DazBaldwin; 05.02.2015

Вы можете сделать что-то подобное, когда вы проверяете, истек ли срок действия access_token, и генерируете еще один.

 %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

Вы можете проверить скринкаст gorails, объясняет это на глубине.

person Diogo    schedule 04.12.2017