2012-04-17 41 views
8

Tôi có một ứng dụng nơi người dùng có thể liên kết tài khoản Facebook của họ. Họ có thể đăng nhập bằng email của họ, nhưng họ có thể liên kết tài khoản Facebook của họ.Rails - Facebook với Omniauth và Koala: Cách gia hạn mã thông báo đã hết hạn

Trong giao diện nơi tôi hiển thị các mạng xã hội kết nối (Facebook và những người khác), tôi có một cái gì đó như thế này:

<%= image_tag @facebook.get_facebook_picture %> 

này sẽ gọi một phương pháp dụ như thế này:

def get_facebook_picture 
    unless self.token.nil? 
     facebook_graph = Koala::Facebook::GraphAPI.new(self.token) 
     fb_picture = facebook_graph.get_picture("me", { :type => "small" }) 
    end 
end 

này sẽ hoạt động tốt trừ khi mã thông báo Facebook mà tôi đã lưu trữ trong DB của tôi đã hết hạn. Vì vậy, tôi đã thêm xử lý ngoại lệ này trong bộ điều khiển được đề cập:

def facebook_exception_handler exception 
    if exception.fb_error_type.eql? 'OAuthException' 
     # Let's get a new auth token... How? 
    else 
     logger.debug "Damn it. We don't know what error is coming from FB" 
     raise exception 
    end 
end 

tôi bắt ngoại lệ một cách chính xác, nhưng tôi không thấy thế nào tôi sẽ làm mới các thẻ truy cập mà tôi có trong cơ sở dữ liệu của tôi. Lưu ý rằng mã thông báo truy cập mà tôi đã được chèn bằng cách sử dụng OmniAuth. Vì vậy, câu hỏi của tôi là:

Cho rằng tôi có OAuthException, làm cách nào tôi có thể gia hạn mã thông báo truy cập của một người dùng cụ thể (UID) bằng cách sử dụng Omniauth?

+0

Vì đây không phải là một câu trả lời cho câu hỏi của bạn, tôi sẽ chỉ để lại nhận xét ... nhưng bạn sẽ có thể lấy hình ảnh không có mã thông báo đang hoạt động bằng cách sử dụng: 'profile_pic = Koala :: Facebook :: GraphAPI.new.get_picture (fb_uid, {: type =>" large "})', phải không? – courtsimas

+0

Nếu bạn muốn nhận mã thông báo 60 ngày mở rộng, [điều này có thể hữu ích] (http://stackoverflow.com/a/16721737/805003) – manafire

Trả lời

9

Trường hợp đơn giản là bạn xác thực lại người dùng bằng FB, chính xác như bạn đã ủy quyền cho họ ngay từ đầu. Để có được mã thông báo ở nơi đầu tiên, tôi giả sử bạn đang sử dụng omniauth (và onmiauth-facebook) để xác thực với FB. Điều đó có nghĩa là bạn đã có một tuyến đường và một hành động điều khiển để xử lý gọi lại auth và một hàm chèn mã thông báo vào db.

Mã thông báo truy cập ban đầu bạn có với omniauth có thể trở thành không hợp lệ vì nhiều lý do khác nhau - hết hạn hoặc do người dùng đã thay đổi mật khẩu FB của họ và những người khác. Trong những trường hợp đó, một cuộc gọi OAuth khác sẽ trả lại mã thông báo hợp lệ. Chỉ cần gọi lại (như bạn đã làm khi bạn lần đầu tiên ủy quyền cho người dùng) và thay thế mã thông báo không hợp lệ bằng mã thông báo mới, trong DB của bạn và bạn tốt.

This gist (my own answer với câu hỏi liên quan mà tôi đã hỏi ở đây) có một số mã bao gồm điều đó, nhưng có vẻ như bạn đã được bảo hiểm. Lưu trạng thái đủ để sau đó lại cố gắng bất cứ điều gì kích hoạt ngoại lệ và bạn tốt.

Cũng có thể mã thông báo hiện không hợp lệ vì người dùng đã thay đổi cài đặt ứng dụng FB của họ để hủy ủy quyền ứng dụng của bạn. Trong trường hợp đó, người dùng sẽ thấy hộp thoại quyền của FB như thể họ là người dùng mới xác thực với FB lần đầu tiên. (FB)

Điều đó có hợp lý không?

+0

Cảm ơn câu trả lời. Câu hỏi của tôi là: Làm cách nào để cập nhật mã thông báo trực tiếp mà không phải hiển thị cửa sổ xác thực cho người dùng? – Nobita

+0

Miễn là ứng dụng vẫn được ủy quyền và người dùng vẫn đăng nhập vào FB, cuộc gọi oauth của bạn sẽ thành công âm thầm.Người dùng sẽ chỉ thấy cửa sổ xác thực nếu cần vì một lý do nào đó (họ đã đăng xuất khỏi FB hoặc họ đã hủy ủy quyền ứng dụng của bạn và cần ủy quyền lại ứng dụng đó). –

+0

Tôi không nói người dùng đăng nhập ở tất cả ... Tôi đang sử dụng Omniauth để cho phép người dùng liên kết tài khoản của họ với ứng dụng (để đăng sau vào tường của họ) nhưng không phải là phương thức ghi nhật ký. – Nobita

2

Bạn có thể thay đổi các kết nối hướng dẫn RailsCasts koala với điều này:

def facebook 
    if self.facebook_expires_at < Time.now 
    oauth = Koala::Facebook::OAuth.new(ENV["FACEBOOK_KEY"], ENV["FACEBOOK_SECRET"]) 
    new_access_info = oauth.exchange_access_token_info self.facebook_token 

    new_access_token = new_access_info["access_token"] 
    new_access_expires_at = DateTime.now + new_access_info["expires"].to_i.seconds 

    self.update_attributes!(:facebook_token => new_access_token, 
          :facebook_expires_at => new_access_expires_at) 
    end 
    @facebook ||= Koala::Facebook::API.new(self.facebook_token) 
    block_given? ? yield(@facebook) : @facebook 

    rescue Koala::Facebook::APIError => e 
    logger.info e.to_s 
    nil 
end 
+1

Thử nghiệm của tôi cho thấy rằng phương pháp này không thực sự kéo dài thời gian hết hạn, mã thông báo mới sẽ hết hạn cùng lúc với mã thông báo cũ. – biomancer

+0

@biomancer Tôi thấy rằng, Có cách nào để gia hạn một mã thông báo? –

+1

@NickGinanto Có vẻ như không có cách nào để làm điều đó mà không cần tương tác với người dùng. Tôi đã kết thúc hiển thị thông báo đặc biệt cho người dùng, những người có mã thông báo của họ đã hết hạn, với cùng một liên kết omniauth được sử dụng để đăng nhập/đăng ký. Người dùng đi qua luồng OAuth chuẩn và tôi nhận được mã thông báo mới trong cuộc gọi lại Omniauth của tôi. – biomancer

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