2012-04-20 2 views
22

omniauth-facebook을 사용하여 FB에 대해 사용자를 인증하고 (사용자에 대한 FB OAuth 액세스 토큰을 얻는) Rails 앱을 작성하고 있습니다. 그런 다음 응용 프로그램은 Koala를 사용하여 저장된 OAuth 토큰을 사용하여 FB Graph API에 대한 다양한 호출을 수행합니다.Koala 및 omniauth-facebook으로 Facebook 토큰 만료 및 갱신

사용자가 재 인증 할 때마다 (일반적으로 내 앱에 로그인 할 때) 저장된 토큰을 업데이트합니다. 그렇더라도 저장된 토큰은 수시로 만료됩니다 (그렇지 않으면 무효가됩니다).

코알라를 사용하는 동안 인증 실패 및 토큰 업데이트를 방지하기위한 최적의 방법은 무엇입니까?

FB에서 사용자를 다시 인증하는 예외 처리기로 모든 호출을 시작/복구 블록으로 묶어야합니까?

코알라를 사용하는 어떤 방법으로 here에 설명 된 '확장 액세스 토큰'프로세스를 활용할 수 있습니까? 그렇지 않다면 코알라 전화에서 직접 새 토큰을 추출하기위한 코드를 작성하는 모범 사례가 있습니까?

답변

16

내가 가지고있는 것은 활성 Facebook 세션이 필요한 모든 페이지에서 트리거되는 before_filter입니다. 이 같은 것이 작동해야합니다.

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 
+0

답변 해 주셔서 감사합니다. 세션 [: fb] [ "만료"]가 설정되는 곳/방법은 무엇입니까? 위의 reconnect_with_facebook 메소드에서 사용하십시오. –

+0

누군가가 세션을 만들기 위해 처음으로 로그인 할 때 설정됩니다. 다른 모든 연결은 "다시 연결"됩니다. – heavysixer

+0

감사. 다소 다르게 구현되었지만 이것이 올바른 길로 인도하는 데 도움이되었습니다. –

16

난 당신이 60 일 하나 단명 한 토큰을 교환 할 수있는 방법을 보여 Railscast on Facebook에서 코드를 적응 this post 건너 온 :

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

코드 스 니펫을 보내 주셔서 감사합니다! – okysabeni

+0

감사합니다. 좋은 방법입니다. 내 테스트가 왜 코알라 :: 페이즈 :: OAuthTokenRequestError : 타입에 대해 불평하는지 알아 내려고했다. OAuthException, code : 101, message : client_id 파라미터가 빠졌다. [HTTP 400]'. 결국 나는'secrets.yml'에서 테스트 환경에 대해'ENV [ "FACEBOOK_APP_ID"]'또는'ENV [ "FACEBOOK_SECRET"]'을 정의하지 않았다는 것을 깨달았습니다. – DazBaldwin

0

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를 확인할 수 있습니다.