JSON 参数在请求哈希中不可用(Rails,omniauth-google-oauth2 gem)

JSON parameters not available in request hash (Rails, omniauth-google-oauth2 gem)

概览

我想用 Omniauth Google OAuth2 Gem (0.2.6) 实现 Google OAuth2 服务器端(混合)。但是,我发送到我的应用程序的代码参数没有添加到 request.params 哈希中。因此,OmniAuth 会抛出一个错误,因为它找不到代码。

详情

从 Google 获取授权码后,我将其发送到服务器(通过 AJAX):

// Send the code to the server
    $.ajax({
      type: 'POST',
      url: '/auth/google_oauth2/callback',
      contentType: 'application/json',
      success: function(result) {
        // Handle or verify the server response.
      },
      processData: false,
      data: JSON.stringify(password_result)
    });

这会引发错误:

"error" : "invalid_request",
"error_description" : "Missing required parameter: code"

遍历堆栈后,我得出以下结论:

  1. 只要我将 'application/json' 设置为内容类型,Rack 就会正确解析参数并且 env 对象包含解析的参数:

    "action_dispatch.request.request_parameters"=>{"code"=>"<sent_in_code>"}
    
  2. 但是,request.params 哈希仍然是空的。由于 OmniAuth 检查 request.params['code'],这就是错误的来源。

  3. request.POST 为空,从 Rack 的源代码来看,这是空 request.params 散列的根本原因。

  4. 当以 data:"code="+authResult['code'] 的标准格式发送代码时,参数在 request.params 散列中可用。 (然后我收到一个奇怪的未定义路由错误,但这是一个不同的问题。)

问题

现在,即使我可以通过不使用 JSON 来避免这个问题,我仍然对以下问题的答案非常感兴趣:

  1. 为什么 code 参数在 request.POST/request.params 中不可用,即使它已被正确解析?
  2. 有没有办法解决这个问题,这样我仍然可以将 JSON 中的授权码发送到我的应用程序?

我自己花了两个下午试图得到答案,但到目前为止还没有真正得出一个好的结论。

omniauth-google-oauth2 尝试从 Rack::Request.params 哈希中获取授权码。但是,Rack 显然没有内置 JSON 解析。 Params calls POST which then calls form_data? which only looks for application/x-www-form-urlencoded or multipart/form-data. It then also tries parseable_data?, which does not parse JSON either. Seems like Rack does not support JSON out of the box, also look at this answer.

"action_dispatch.request.request_parameters"=>{"code"=>"<sent_in_code>"} 哈希有效,因为这是由 rails ActionDispatch::Request 完成的,它是 Rack::Request 的子类。然而,因为 omniauth gem 作为 Rack 中间件包含在您的应用程序中,它不知道 ActionDispatch 请求对象。

问题仍然是为什么 this example 使用 JSON。

可能的解决方案:

  • money-Patch JSON 支持 Rack - 不推荐
  • 只需使用 application/x-www-form-urlencoded - 推荐