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

问题描述

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

有谁知道如何为所有使用 bottles(X) :- X > 1,%% ← check that X is greater than one. write(X),write(' bottles of beer on the wall,'),nl,write(X),write(' bottles of beer,write('Take one down,and pass it around,X1 is X - 1,write(X1),write(' bottles of beer on the wall.'),bottles(X1). bottles(1) :- write('1 bottle of beer on the wall,1 bottle of beer,write('Now they are alle gone.'),nl.omniauth gems 的请求设置自定义请求标头?

例如,我尝试过类似以下的操作,但我在 Chrome 的开发人员工具中看不到标题

omniauth-oauth2

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


根据回复进行编辑:

为什么我需要自定义标头集在这里并不重要——正如我在问题顶部提到的:这只是我的好奇心。限制是我想在任何操作系统或浏览器上测试自定义标头,因此仅在 Chrome 中使用开发人员工具是不够的,因为并非所有浏览器都在所有操作系统上都具有该功能

我想要做的是为来自 gem 的所有传出 OAuth 请求添加一个自定义标头。就是这样。

解决方法

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

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

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

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

因此,首先您需要确定要在哪个请求/响应中设置哪些标头,其中有几个。简化序列: diagram

,

OAuth 请求处理程序不能强制浏览器(或任何类似的用户代理)披露比 HTTP 协议中指定的更多的信息。值得庆幸的是:任何其他姿势都可能导致信息泄漏。

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

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 客户端的标准构造函数,并在将其返回堆栈之前注入额外的标头。在内部,它被移交给 oauth2 gem,后者又使用法拉第,因此法拉第接受的任何东西都可能是一个有效的选项。

如果需要额外的信息携带到认证服务器,可以通过策略将其编码在重定向URL中。例如,omniauth-google-oauth2 策略可配置为在 Google 身份验证端点上的网址中携带身份验证范围和电子邮件提示。

通常还包含 XSRF 状态参数和加密会话 cookie,以防止身份欺骗。根据身份验证服务器的合作,部分或全部数据可能会反映在重定向回您的处理程序中。

最简单的情况是,由策略子类中的 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 方法,它是这项繁重工作的切入点。

在整个事物流程中,这些是服务器端代码实际上可以影响事物的接触点。有一个基本的期望,即用户的客户端/浏览器通过执行正常的 HTTPS 请求来参与。