2012-04-20 44 views
22

Tôi đang viết ứng dụng Rails sử dụng omniauth-facebook để xác thực người dùng chống lại FB (và nhận mã thông báo truy cập FB OAuth cho người dùng). Sau đó, ứng dụng sử dụng Koala để thực hiện các cuộc gọi khác nhau tới API FB Graph, sử dụng mã thông báo OAuth đã lưu đó.Hết hạn và gia hạn mã thông báo Facebook, với Koala và omniauth-facebook

Tôi cập nhật mã thông báo đã lưu mỗi khi người dùng xác thực lại (thường là khi họ đăng nhập vào ứng dụng của tôi). Mặc dù vậy, mã thông báo đã lưu sẽ hết hạn (hoặc nếu không trở thành không hợp lệ) theo thời gian.

Thực tiễn tốt nhất xung quanh việc bảo vệ chống lại lỗi xác thực và cập nhật mã thông báo khi sử dụng Koala là gì?

Mọi cuộc gọi có được gói trong khối bắt đầu/cứu hộ, với trình xử lý ngoại lệ xác thực lại người dùng chống lại FB không?

Có cách nào (sử dụng Koala) để tận dụng quy trình 'mở rộng mã thông báo truy cập' được mô tả here không? Nếu không, có cách nào tốt nhất để viết mã của riêng tôi để trích xuất mã thông báo mới từ cuộc gọi Koala?

Trả lời

16

Điều tôi có là before_filter được kích hoạt trên mọi trang yêu cầu phiên hoạt động trên Facebook. Một cái gì đó như thế này sẽ hoạt động:

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 

Mã thông báo_expired? phương pháp trông như thế này:

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

Cảm ơn câu trả lời. Phiên làm việc [/ fb] ["hết hạn"] ở đâu/như thế nào? Bạn sử dụng nó trong phương thức reconnect_with_facebook ở trên. –

+0

tôi đặt rằng lần đầu tiên ai đó đăng nhập thành công để tạo phiên. Tất cả các kết nối khác được coi là "kết nối lại" – heavysixer

+0

Cảm ơn. Tôi đã thực hiện một chút khác biệt, nhưng điều này rất hữu ích trong việc đưa tôi đi đúng hướng. –

16

Tôi đã xem qua this post mà điều chỉnh mã từ các Railscast on Facebook để hiển thị như thế nào bạn có thể trao đổi token ngắn ngủi cho 60 ngày đầu tiên:

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

Cảm ơn đoạn mã! – okysabeni

+0

Cảm ơn đây là một phương pháp hay. Đã cho tôi một thời gian để tìm hiểu lý do tại sao các thử nghiệm của tôi phàn nàn về một số 'Koala :: Facebook :: OAuthTokenRequestError: loại: OAuthException, mã: 101, thông báo: Thiếu thông số client_id. [HTTP 400] '. Cuối cùng, tôi nhận ra rằng tôi đã không xác định 'ENV [" FACEBOOK_APP_ID "]' hoặc 'ENV [" FACEBOOK_SECRET "]' cho môi trường thử nghiệm của tôi trong 'secrets.yml'. – DazBaldwin

0

Bạn có thể làm điều gì đó như thế này, nơi bạn kiểm tra xem access_token đã hết hạn chưa và tạo một truy vấn khác.

%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 

Bạn có thể kiểm tra độ sâu gorails screencast.

Các vấn đề liên quan