gpt4 book ai didi

ruby-on-rails - 使用 omniauth 和 Facebook 对 Rails API 的用户进行身份验证?

转载 作者:行者123 更新时间:2023-11-30 05:13:43 26 4
gpt4 key购买 nike

我正在构建一个 Rails API,并且已经成功地为用户构建了一种使用 Omniauth Identity 进行身份验证的方法。

我们只是从客户端发送到 auth/identity/callback,传入 auth_key 和密码。
然后,服务器返回一个看门人 token ,用户随后使用该 token 访问应用程序并识别自己。

这张图说明了这一点:

Client server relationship

我们现在想从客户端实现 Facebook 登录,但在理论上和实践上都难以实现。

在带有 Omniauth Identity 的简单 Rails 应用程序上,您只需调用 auth/facebook,但如果我们在客户端中放置一个链接,它会调用服务器,然后服务器会记录:

INFO -- omniauth:(facebook) 请求阶段已启动。

应用程序在 Facebook 中正确设置了 ID 和 Secret,所以登录提示可能会返回到服务器?

我对链接身份验证感到困惑。非常感谢任何帮助!

enter image description here

最佳答案

我发现的最好方法(在这个问题上被困了一段时间之后)是手动执行 omniauth2(特别是在我的情况下使用 satellizer angular 插件)...

我将根据我的情况讨论适用于 Facebook 的解决方案,但所有内容都适用于任何其他提供商。

首先您必须了解 omniauth2 的工作原理 ( as documented for humans here )...

  1. 客户端:打开一个弹出窗口供用户进行身份验证。
  2. 客户:登录(如有必要),然后授权应用程序。
  3. 客户端:授权成功后,弹出窗口将重定向回您的应用。使用code (authorization code)查询字符串参数

重定向返回 url 必须与您的前端应用程序 url 而不是后端 url 匹配,并且必须在您的 facebook 应用程序配置中指定

  1. 客户端:code 参数被发送回打开弹出窗口的父窗口。
  2. 客户端:父窗口关闭弹出窗口并使用代码发送POST请求到backend/auth/facebook > 参数。
  3. Server: code (Authorization code) 换成access token

此处详细描述了如何将 codefacebook developers documentation 交换为 access-token

  1. 服务器:使用在步骤6中检索到的access-token来检索用户的信息。

    <
  2. VOILA,您已经拥有了一个用户,您可以合并/创建帐户/链接​​到其他 oauth 提供商等。但请记住,用户可以撤消某些权限(例如电子邮件,facebook 支持撤消某些权限)...


(说的够多了,给我看一些代码)

首先你必须添加 HTTParty gem 到你的 Gemfile

gem 'httparty'  # Makes http fun again (http client)

我添加了 this gist其中包含步骤(6、7 和 8)的流程,这些是最有问题的步骤,几乎没有任何记录。

要点导出了 2 个主要方法:

Omniauth::Facebook.authenticate(authorization_code)

用于facebook认证用户,返回user_info,long_live_access_token(有效期60天)

Omniauth::Facebook.deauthorize(access_token)

用于取消授权/撤销facebook上的access_token和应用权限...

这用于我的特殊要求,当用户撤销在 facebook 登录时请求的电子邮件权限......我们撤销整个应用程序权限......这将在下次登录时提示用户,就好像这是他的第一次登录(不需要去facebook apps手动撤销申请)...

这是它在 Controller 中的使用方式

user_info, access_token = Omniauth::Facebook.authenticate(params['code'])
if user_info['email'].blank?
Omniauth::Facebook.deauthorize(access_token)
end

就是这样……现在如果您对实现的内部结构感兴趣……这里是要点中的代码。 (添加以供引用)随意 fork 、编辑它,帮助让它变得更好。

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 tutorial implementing oauth for instagram这帮助我理解了 oauth2 是如何工作的(添加以供引用)

关于ruby-on-rails - 使用 omniauth 和 Facebook 对 Rails API 的用户进行身份验证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19989391/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com