如何为所有通过 OmniAuth 的请求设置自定义 header?

How to set custom header for all requests that go through OmniAuth?

这主要是一个我不知道如何解决的思维练习。 :)

有谁知道如何为所有使用 omniauthomniauth-oauth2 gem 的请求设置自定义请求 header?

我试过类似下面的方法,但是我在 Chrome 的开发者工具中没有看到 header,例如。

OmniAuth.config.before_request_phase do |env|
  env['MY_CUSTOM_HEADER'] = 'true'
end

我在这里做错了什么?我在这里错过了什么?


根据回复进行编辑:

为什么我需要自定义 header 集在这里并不重要——正如我在问题顶部提到的:这只是我的好奇心。约束是我想在任何 OS 或浏览器上测试自定义 header,所以仅仅在 Chrome 中使用开发人员工具是不够的,因为并非所有浏览器都有能力跨越所有 OSes.

我想做的是向 gem 发出的所有外发 OAuth 请求添加自定义 header。就是这样。

在浏览器开发人员工具中,您只能看到浏览器发送的请求 header 或浏览器接收的响应 header。由负载平衡器、反向代理、中间件等设置的任何请求 headers - 仅对请求处理链中的下一阶段可见。

OmniAuth 存在于中间件中,因此从技术上讲,您应用中的任何请求都会使用它,除非其他一些中间件终止请求链并呈现一些响应。 此外,omniauth 术语中的“请求”不是 http 请求,它是一个身份验证阶段,通常发生在 /auth/:provider(也有“选项”和“回调”阶段)。

不清楚为什么您需要在中间件中针对进入您自己的应用程序的请求设置请求 - 当请求将由 omniauth 处理时,它不会到达您的控制器,除了callback 将设置 request.env['omniauth.auth'] 的阶段。

既然提到了开发人员工具 - 可能您希望在请求阶段响应 header,要设置这些,您需要覆盖策略中从 request_phase 返回的机架响应。但是对于oauth2只有一个重定向(仍然可以设置headers,但意义更小)。

因此,首先您需要确定要将哪个 header 设置为哪个 request/response,其中有几个。简化序列:

OAuth 请求处理程序不能强制浏览器(或任何类似的 user-agent)披露比 HTTP 协议中规定的信息更多的信息。庆幸:任何其他姿势都可能导致信息泄露。

Omniauth 可能建立的唯一联系是用代码交换 access/refresh 令牌。这特定于所讨论的策略,但策略有机会在其内部客户端中包含任意 header。如果您正在编写在访问令牌交换期间需要基本身份验证 header 的自定义策略,它可能如下所示:

require 'omniauth-oauth2'

module OmniAuth
  module Strategies
    class DemoStrategy < OmniAuth::Strategies::OAuth2
      option :name, "demo"
      option :client_options, {
        site: 'https://api.example.org',
        authorize_url: 'https://auth.example.org/oauth2/authorize',
        token_url: 'https://auth.example.org/oauth2/token'
      }

      uid { raw_info['id'].to_s }

      info do
        { email: raw_info['email'], image: raw_info['avatar_url'] }
      end

      extra do
        { raw_info: raw_info }
      end

      def raw_info
        @raw_info ||= access_token.get('user').parsed
      end

      def build_access_token
        options.token_params.merge!(headers: {
          'Authorization' => special_auth_header
        })
        super
      end

      def basic_auth_header
        "Basic " + Base64.strict_encode64("#{options[:demo_id]}:#{options[:demo_secret]}")
      end
    end
  end
end

在这里,build_access_token 覆盖超类的内部 HTTP 客户端的标准构造函数,并在将其返回堆栈之前注入额外的 headers。在内部,它被移交给 oauth2 gem,后者又使用法拉第,因此法拉第接受的任何东西都可能是有效的选择。

如果您需要将额外的信息传送到认证服务器,它可能会被策略编码在重定向 URL 中。例如,omniauth-google-oauth2 策略可配置为在 URL 中携带身份验证范围和电子邮件提示,该 URL 位于 Google 的身份验证端点。

包含 XSRF 状态参数以及加密的 session cookie 以防止身份欺骗也很常见。根据身份验证服务器的 co-operation,部分或全部数据可能会反映在重定向回您的处理程序中。

最简单的,由策略子类中的 authorize_params 方法处理,例如

def authorize_params
  super.tap do |params|
    params[:something] = 'my_extra_value'
  end
end

但是,在实践中,设置扩展参数所涉及的代码量可能相当大。对于使用 Omniauth 执行此操作的有效示例,我建议您查看 source code of the Google strategy,我将再次提请您注意 authorize_params 方法,它是这项繁重工作的入口点。

在事物的整体流程中,这些是 server-side 代码实际上可以影响事物的接触点。有一个基本期望,即用户的 client/browser 只执行正常的 HTTPS 请求来参与。