validation用户使用omniauth和Facebook的轨道API?
我构build了一个Rails API,并成功构build了一个用户使用Omniauth Identity进行身份validation的方法。
我们只需从客户端发送auth / identity / callback,传入一个auth_key和密码。
服务器然后返回一个守门员令牌,然后用户从此使用门禁令牌来访问应用程序并识别他们自己。
这张图解释了这一点:
我们现在希望从客户端实现Facebooklogin,但在理论和实践上都难以实现。
在一个带有Omniauth Identity的简单Rails应用程序中,您只需调用auth / facebook,但是如果我们在客户端中放置了一个链接,就会调用服务器,然后服务器就会logging:
INFO -- omniauth: (facebook) Request phase initiated.
该应用程序在Facebook中设置正确的ID和秘密,所以也许login提示返回到服务器?
虽然链接authentication,我感到困惑。 任何帮助感激地感谢!
我发现的最好的方法(在这个问题上被卡住一段时间后)是手动执行你的omniauth2(具体来说就是在我的情况下使用satellizer angular plugin)。
我会讨论Facebook的解决scheme,因为这是我的情况,但一切可能适用于任何其他供应商。
首先你必须知道omniauth2是如何工作的
- 客户端:打开一个popup窗口供用户进行身份validation。
- 客户:login(如有必要),然后授权应用程序。
- 客户端:成功授权后,popup窗口被redirect回您的应用程序。 用
code
(授权码)查询string参数
redirect返回url必须匹配您的前端应用程序url而不是后端url,它必须在您的facebook应用程序configuration中指定
- 客户端:
code
参数被发回到打开popup窗口的父窗口。 - 客户端:父窗口closurespopup窗口并使用
code
参数向backend/auth/facebook
发送POST
请求。 - 服务器:
code
( 授权码 )被交换为access token
这里详细描述如何从facebook开发者文档交换access-token
的code
-
服务器:使用步骤6中检索的
access-token
来检索用户的信息。 正如这里所记载的那样具有很好的视觉帮 -
VOILA你有自己的用户,你可以合并/创build帐户/链接与其他oauth提供商/等。 但记住,用户可以撤销一些权限(如电子邮件 ,Facebook支持撤销一些权限)…
(足够的说话,给我看一些代码)
首先你必须添加HTTParty gem到你的Gemfile
gem 'httparty' # Makes http fun again (http client)
我已经添加了这个包含步骤(6,7和8)stream程的要点 ,这些步骤是最有问题的步骤,几乎没有logging在任何地方。
主要出口2主要方法:
Omniauth::Facebook.authenticate(authorization_code)
用于通过facebookauthentication用户并返回user_info,long_live_access_token(有效期为60天)
Omniauth::Facebook.deauthorize(access_token)
这是用来取消授权/撤销access_token和应用程序在Facebook上的权限…
这是用于特殊要求,我有,当用户撤销在Facebooklogin请求的电子邮件许可…我们撤销整个应用程序的权限…这将提示用户在下次login,就好像这是他的第一次login(不需要去facebook应用程序并手动撤销应用程序)...
这里是如何在控制器中使用的
user_info, access_token = Omniauth::Facebook.authenticate(params['code']) if user_info['email'].blank? Omniauth::Facebook.deauthorize(access_token) end
就是这样…现在如果你对实现的内部感兴趣的话,这里就是代码。 (添加参考)随意分叉,编辑它,帮助使其更好。
require 'httparty' module Omniauth class Facebook include HTTParty # The base uri for facebook graph API base_uri 'https://graph.facebook.com/v2.3' # Used to authenticate app with facebook user # Usage # Omniauth::Facebook.authenticate('authorization_code') # Flow # Retrieve access_token from authorization_code # Retrieve User_Info hash from access_token def self.authenticate(code) provider = self.new access_token = provider.get_access_token(code) user_info = provider.get_user_profile(access_token) return user_info, access_token end # Used to revoke the application permissions and login if a user # revoked some of the mandatory permissions required by the application # like the email # Usage # Omniauth::Facebook.deauthorize(access_token) # Flow # Send DELETE /me/permissions?access_token=XXX def self.deauthorize(access_token) options = { query: { access_token: access_token } } response = self.delete('/me/permissions', options) # Something went wrong most propably beacuse of the connection. unless response.success? Rails.logger.error 'Omniauth::Facebook.deauthorize Failed' fail Omniauth::ResponseError, 'errors.auth.facebook.deauthorization' end response.parsed_response end def get_access_token(code) response = self.class.get('/oauth/access_token', query(code)) # Something went wrong either wrong configuration or connection unless response.success? Rails.logger.error 'Omniauth::Facebook.get_access_token Failed' fail Omniauth::ResponseError, 'errors.auth.facebook.access_token' end response.parsed_response['access_token'] end def get_user_profile(access_token) options = { query: { access_token: access_token } } response = self.class.get('/me', options) # Something went wrong most propably beacuse of the connection. unless response.success? Rails.logger.error 'Omniauth::Facebook.get_user_profile Failed' fail Omniauth::ResponseError, 'errors.auth.facebook.user_profile' end response.parsed_response end private # access_token required params # https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.3#confirm def query(code) { query: { # The authorization_code we want to exchange for the access_token code: code, # This must match the redirectUrl registerd in the facebook app. # You can save it to ENV['WEB_APP_URL'] if you have multiple facebook apps for development and testing # so you can support testing app on development and production app on production env. redirect_uri: "http://localhost:9000/", client_id: ENV['FB_APP_ID'], # Facebook appId client_secret: ENV['FB_APP_SECRET'], # Facebook app secret (must not exist on front-end app for security) } } end end end
这里是另一个nodejs教程实施oauth的instagram ,帮助我了解oauth2如何工作(添加为参考)
为了解决这个问题,我find的最好的资源是在卫星github回购轨道的示例应用程序: https : //github.com/sahat/satellizer/tree/master/examples/server/ruby
您的卫星代码调用AuthController.authenticate方法。 此方法使用每个提供程序的oauth模型类将您收到的代码转换为访问令牌。 然后在您的用户类中,您可以检索与您从提供者那里获得的信息相匹配的用户。
控制器方法最后将jwt令牌返回给客户端。
在我的情况下,控制器部分是有点不同,因为我也使用devise的邮件/密码authentication,但我复制th oauth类是原样,它的作品就像一个魅力。
与Facebook的API通信。 我build议使用'omniauth-facebook'gem 。 你可以克隆这个例子来了解更多: https : //github.com/ralphos/omniauth-facebook-example