通过OmniAuth传递参数

59
我需要将一些参数传递给回调操作。从源代码来看,OmniAuth应该将查询字符串添加到回调URL中,但奇怪的是它没有这样做。当我打开时。
/auth/facebook?from=partner

...然后被重定向到 Facebook,return_url 只是

/auth/facebook/callback

...没有任何参数。


2
https://dev59.com/DVzUa4cB1Zd3GeqP7eBM - Zabba
41
您可以通过 env["omniauth.params"] 获取您的 "from" 参数。 - David Morales
1
如使用Devise,请参见:Devise + Omniauth - 如何传递额外的参数? - Damien
7个回答

82

在处理了以上所有答案后,我找到了如何解决关于 Facebook 的问题,因为默认情况下在request.env["omniauth.auth"]中不会显示参数。

所以—— 如果您正在使用类似以下内容的回调查询字符串:

"/auth/facebook?website_id=#{@website.id}"

获取website_id参数的唯一方法是使用request.env["omniauth.params"]注意:确保使用omniauth.params而不是omniauth.auth--这个问题困扰了我一段时间

然后,为了测试这个,你可以在控制器操作中检查它(注意RAISE行...):

def create
  raise request.env["omniauth.params"].to_yaml 
  # the rest of your create action code...
end

你应该能在那里看到你的参数。很好。现在回到你的控制器,并删除那个 RAISE 行。然后,你可以在控制器操作中按以下方式访问参数:

params = request.env["omniauth.params"]
website_id = params["website_id"]

注意:在 params["website_id"] 中需要使用引号而不是符号。


我在omniauth.auth中得到了输出,但在omniauth.params中却是nil。出了什么问题?我已经在URL中传递了参数"/auth/facebook/state=123"。 - harsh4u
1
@harsh4u 可能是因为你的 URL 在参数前缺少了一个“?”。应该是“auth/facebook/?state=123”。 - Oleksandr Kruk
1
谢谢你!在阅读你的回答之前,我一直在劫持状态参数来实现这个。感谢! - septerr
2
这是omniauth的一个很棒的功能,可惜文档不够好。 - SirRawlins

22

我猜这个cookie的方式可以工作,但是为什么要这样做呢?你可以像这里https://github.com/mkdynamic/omniauth-facebook文档中所述使用状态变量。

这是我如何使用它的:

在创建URL时,您只需在查询字符串中添加状态,它将在回调URL中同样可用。

user_omniauth_authorize_path(:facebook, :display => 'page', :state=>'123') %>

现在回调URL将是:

http://localhost:3000/users/auth/facebook/callback?state=123&code=ReallyLongCode#_=_
现在在回调处理程序中,您可以处理该状态。

21
您可以使用:params选项,如下所示
omniauth_authorize_path(:user, :facebook, var: 'value', var2: 'value2' )

在回调函数中,你可以访问request.env['omniauth.params']来获取哈希值! :)(摘自this answer

1
一个救命稻草,长久耐用在最底部 :) - Aleks
你救了我的一天。谢谢! - Franchy

8
你需要做的是根据涉及的伙伴动态设置回调url(不是url参数),每个身份验证事务都要这样做,具体取决于涉及的伙伴。这意味着为每个身份验证请求动态设置回调url。请参阅此博客文章以开始操作。回调url会自动删除url参数,正如你已经注意到的那样,因此使用参数进行操作无法实现。
所以,如果您不尝试将伙伴名称/ID作为参数传递(该参数被删除),而是构建您的路由,使得partner_id和OmniAuth provider成为回调URL的一部分,那么您会得到类似以下的内容:
/auth/:omniauth_provider/callback/:partner_id

...其中有效的回调函数可能是这样的

/auth/facebook/callback/123456

如果您熟悉IT技术,那么您应该知道一个给定的回调是来自Facebook的,合作伙伴ID为123456


很好的回答,Normalocity。我自己也在尝试弄清楚这个问题。我不太确定如何执行你上面所描述的操作,而且博客文章也没有提供太多信息。你能否发布一些代码?具体来说,如何生成上述路由,以及如何创建相应的控制器动作来处理不同的回调?我特别希望回调提供用户离开的上下文,这样一旦OAuth完成,我就可以将用户返回到他们之前的位置。 - John
用户“离开”的URL可以在重定向到OAuth门户时存储在cookie中,当回调返回时,可以查找cookie,检索值并将cookie过期/删除。至于其他内容,我认为我可以制作一个快速演示应用程序,并将其发布为概念验证,然后我可以在GitHub上分享代码。然后,假设它有效,我可以在答案中再次发布代码。给我几个小时来尝试一下。 - jefflunt

6

1

你知道吗,我觉得我可能一直在用困难的方式来解决这个问题。

Cookie 可能是答案。我认为你可以通过让你的登录操作存储一个 cookie 来解决这个问题,然后重定向到适当的 /auth/:provider 路径进行身份验证,当回调被触发时(在 SessionsController#create 中),你只需读取 cookie 即可知道要将他们重定向到哪里。

所以,现在,你的“使用 Facebook 登录”链接(或者你的应用程序中的任何其他链接)可能会转到 /auth/facebook。如果你创建了一个自定义操作,例如

POST /partner_auth

...并通过URL调用它...

POST example.com/partner_auth?from=partner&provider=facebook

那么你可能会有一个控制器如下:

class PartnerAuth < ApplicationController
  def create
    cookies[:from] = params[:from]  # creates a cookie storing the "from" value
    redirect_to "auth/#{params[:provider]"
  end
end

然后在 SessionsController#create 动作中,你会有...

def create
  ...

  destination = cookies[:from]
  cookies[:from].delete

  redirect_to destination    # or whatever the appropriate thing is for your
                             # app to do with the "from" information
end

我尝试构建一个演示应用程序来完成我在其他答案中概述的内容,但你是对的 - 动态注入自定义回调到OmniAuth代码中太复杂了。虽然有一个配置选项可以覆盖默认回调,但似乎很难动态设置它。

所以,我想到了使用cookie会更简单、用户特定,并且由于理论上你只需要为这个from信息存储很短的时间(在用户尝试进行身份验证和触发回调之间),所以创建一个cookie并在回调被触发时删除它也没什么大不了的。


-2

使用“state”变量。Facebook允许用户设置STATE变量。

这是我的做法,我在AUTH URL后面附加了?state=providername

http://localhost/users/auth/facebook?state=providername

这个参数将在回调函数中作为params ['providername']返回给我

我从原始的Omniauth路径方法中设计了解决方案

user_omniauth_authorize_path(:facebook, :display => 'page', :state=>'123') %>

这是非常糟糕的方法。状态参数存在的目的是为了避免来自另一个域的令牌伪造。状态是一个生成的密钥,与用户一起传递到IDP,并由IDP返回,以便您可以再次检查此授权请求是否确实由您的服务器发出。 - Jakub

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接