Выпуск и обновление токена Facebook, с Koala и omniauth-facebook
Я пишу приложение Rails, которое использует omniauth-facebook для аутентификации пользователя против FB (и получения токена доступа FB OAuth для пользователя). Затем приложение использует Koala для выполнения различных вызовов API-интерфейса FB, используя этот сохраненный токен OAuth.
Я обновляю сохраненный токен каждый раз, когда пользователь повторно аутентифицируется (обычно, когда он входит в мое приложение). Тем не менее, этот сохраненный токен истекает (или иным образом становится недействительным) время от времени.
Что лучше всего защищает от сбоев auth и обновляет токен при использовании Koala?
Должны ли все вызовы быть обернуты в блоки start/rescue с обработчиком исключений, который повторно аутентифицирует пользователя против FB?
Есть ли какой-то способ (используя Koala), чтобы воспользоваться описанным здесь процессом "продления доступа к токенам" здесь? Если нет, есть ли рекомендации по написанию собственного кода для извлечения нового токена из коала?
Ответы
Ответ 1
У меня есть файл 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
Token_expired? метод выглядит следующим образом:
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
Ответ 2
Я встретил этот пост, который адаптирует код из 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
Ответ 3
Вы можете сделать что-то подобное, когда вы проверяете, истек ли срок действия 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 screencast, который объясняет это по глубине.