如何解决为仅限 Rails Api 的应用实现社交登录
我正在努力寻找一种工作方法来通过 Facebook 和 Google 为我现有的仅限 api 的 rails 应用程序实现 oauth2 登录。登录流程和 jwt 管理由 Devise & Doorkeeper 完成,遵循 this guide。
我尝试了 Doorkeeper-grants-assertion 个示例,但它们都不起作用。 我遇到的问题是我无法用我的 jwt 令牌交换提供者的令牌。
客户端(Android 和 iOS 应用程序)我可以使用提供程序登录并获取令牌,但是当我尝试授权用户创建新令牌时,它给了我错误。
代码与示例相同。在 Google 的情况下,我正在跳过令牌请求,因为我已经可以从客户端获取它:
class GoogleController
def initialize(auth_code)
@auth_code = auth_code
@user_data = user_data
end
def user_data
url = "https://www.googleapis.com/oauth2/v3/userinfo?access_token=" + @auth_code
response = Faraday.get(url,{:Accept => 'application/json'})
@resp = JSON.parse(response.body)
end
def email
@resp['email']
end
def first_name
@resp['first_name']
end
def last_name
@resp['last_name']
end
def get_user!
# below you should implement the logic to find/create a user in your app basing on @user_data
# It should return a user object
user = User.find_by(email: email)
if user
Rails.logger.info "User"
user
else
user = User.new(email: email,password: Devise.friendly_token.first(10))
user.save
Rails.logger.info "No User"
user
end
end
end
我正在使用邮递员提出请求,下面是我的身体的响应:
{
"client_id": "doorkeeper_app_uid","client_secret": "doorkeeper_app_secret","grant_type": "assertion","provider": "google","assertion": "MY USER TOKEN" }
{ "error": "invalid_client","error_description": "Client authentication failed due to unknown client,no client authentication included,or unsupported authentication method." }
我刚刚发现我没有返回 User 对象,这就是 Facebook 不起作用的原因。 现在,使用相同的代码,只有不同的令牌端点,Facebook 登录正在工作,我可以找到或创建用户并返回 jwt 令牌,而 Google 则不是。
如果有人能指出我正确的方向,那就太好了。
编辑
经过进一步调查,我现在: 我可以找到或创建我的 Google 身份验证用户,但是当我将其返回给 doorkeeper assert grant extension 时,验证失败
def validate_resource_owner
!resource_owner.nil?
end
上课
密码访问令牌请求
而且我无法生成新的 jwt 令牌。 与 facebook 有什么不同导致此验证失败?
解决方法
不可思议的家伙,神秘的事情发生了,但我找到了解决方案。
不知何故,doorkeeper.rb
初始化程序中的 2 个提供程序发生了冲突,如果这样写:(不要这样做)
resource_owner_from_assertion do
if provider == "facebook"
g = Api::V1::FacebookController.new(params[:assertion])
g.get_user!
end
if provider == "google"
g = Api::V1::GoogleController.new(params[:assertion])
return g.get_user!
end
end
改为执行以下操作:
resource_owner_from_assertion do
provider = params[:provider]
controller = (provider == "facebook") ? Api::V1::FacebookController.new(params[:assertion]) : Api::V1::GoogleController.new(params[:assertion])
controller.get_user!
end
然后控制器内部还有另一个问题,因为我使用了“user”作为变量名:
user = User.find_by(email: email)
这显然很糟糕,所以使用
facebook_user = User.find_by(email: email)
现在一切似乎都按预期进行。我希望有人会觉得这很有用。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。