ruby-on-rails - 为自定义 omniauth 策略获取 "Authentication failure! invalid_credentials: OAuth2::Error"

标签 ruby-on-rails ruby oauth faraday

目前我正在处理 Rails 4 项目,现在我必须链接/连接另一个应用程序(不是 sso,而是用于访问 API),比如 example.com。 (注意 example.com 使用三足式 oauth 安全架构)

搜索后发现必须要实现omniouth策略。

为此我引用了this关联。根据 Strategy-Contribution-Guide我能够完成设置和请求阶段,您可以在此处找到我的示例代码。

require 'multi_json'
require 'omniauth/strategies/oauth2'
require 'uri'

module OmniAuth
  module Strategies
    class MyAppStrategy < OmniAuth::Strategies::OAuth2
      option :name, 'my_app_strategy'

   option :client_options, {
    site: site_url,
    authorize_url: authorize_url,
    request_url: request_url,
    token_url: token_url,
    token_method: :post,
    header: { Accept: accept_header }
  }

  option :headers, { Accept: accept_header }
  option :provider_ignores_state, true

  def consumer
    binding.pry
    ::OAuth::Consumer.new(options.client_id, options.client_secret, options.client_options)
  end

  def request_phase # rubocop:disable MethodLength
    binding.pry
    request_token = consumer.get_request_token({:oauth_callback => callback_url}, options.request_params)
    session["oauth"] ||= {}
    session["oauth"][name.to_s] = {"callback_confirmed" => request_token.callback_confirmed?, "request_token" => request_token.token, "request_secret" => request_token.secret}

    if request_token.callback_confirmed?
      redirect request_token.authorize_url(options[:authorize_params])
    else
      redirect request_token.authorize_url(options[:authorize_params].merge(:oauth_callback => callback_url))
    end

  rescue ::Timeout::Error => e
    fail!(:timeout, e)
  rescue ::Net::HTTPFatalError, ::OpenSSL::SSL::SSLError => e
    fail!(:service_unavailable, e)
  end

  def callback_phase # rubocop:disable MethodLength
    fail(OmniAuth::NoSessionError, "Session Expired") if session["oauth"].nil?

    request_token = ::OAuth::RequestToken.new(consumer, session["oauth"][name.to_s].delete("request_token"), session["oauth"][name.to_s].delete("request_secret"))

    opts = {}
    if session["oauth"][name.to_s]["callback_confirmed"]
      opts[:oauth_verifier] = request["oauth_verifier"]
    else
      opts[:oauth_callback] = 'http://localhost:3000/auth/callback' #callback_url
    end

    @access_token = request_token.get_access_token(opts)
    super
    rescue ::Timeout::Error => e
      fail!(:timeout, e)
    rescue ::Net::HTTPFatalError, ::OpenSSL::SSL::SSLError => e
      fail!(:service_unavailable, e)
    rescue ::OAuth::Unauthorized => e
      fail!(:invalid_credentials, e)
    rescue ::OmniAuth::NoSessionError => e
      fail!(:session_expired, e)
  end

  def custom_build_access_token
    binding.pry
    verifier = request["oauth_verifier"]
    client.auth_code.get_token(verifier, get_token_options(callback_url), deep_symbolize(options.auth_token_params))
  end
  alias_method :build_access_token, :custom_build_access_token

  def raw_info
    binding.pry
    @raw_info ||= access_token.get('users/me').parsed || {}
  end

  private

  def callback_url
    options[:redirect_uri] || (full_host + script_name + callback_path)
  end

  def get_token_options(redirect_uri)
    { :redirect_uri => redirect_uri }.merge(token_params.to_hash(:symbolize_keys => true))
  end
end
end

结束

我可以重定向到 example.com,登录后我也可以返回到我的 callback_phase(你会问你怎么知道的,所以答案是我已在 callback_phase 方法中添加 binding.pry 以检查流程)。

但是在执行策略后出现以下错误

错误——omniauth:(my_app_strategy)身份验证失败!无效凭证:OAuth2::错误。

调试后发现我在 super 调用中遇到了这个错误(来自 callback_phase 方法)。

首先,我虽然可能存在一些凭据问题,但我可以使用以下方法获取访问 token (在 super 调用之前执行)

@access_token = request_token.get_access_token(opts)

此外,有关更多信息,我收到 build_access_token 错误,这是 oauth2 方法

可以引用this更多信息的链接(只需在页面上搜索 build_access_token)。

编辑 - 1

调试后发现从request method得到这个问题. (在提出法拉第请求时)。这是代码片段

response = connection.run_request(verb, url, opts[:body], opts[:headers]) do |req|
    yield(req) if block_given?
  end

这是我的法拉第请求

#<struct Faraday::Request method=:post, path="example.com/oauth/access_token", params={}, headers={"User-Agent"=>"Faraday v0.9.2", "Content-Type"=>"application/x-www-form-urlencoded"}, body={"grant_type"=>"authorization_code", "code"=>"aPexxxvUg", "client_id"=>"xxxxxur303GXEch7QK9k", "client_secret"=>"xxxxxxcad97b3d252e2bcdd393a", :redirect_uri=>"http://localhost:3000/auth/my_app_strategy/callback"}, options=#<Faraday::RequestOptions (empty)>>

作为响应,我收到以下错误消息

HTTP 状态 400 - OAuth 消费者凭据不足。

那么有人可以帮助解决这个问题吗?

是否有任何其他方式来存储访问 token ,以便我可以将其用于通信目的。 谢谢

最佳答案

首先,我想弄清楚Oauth2是如何工作的:

Oauth2,协议(protocol)说:

  1. 您将用户重定向到提供商登录端点,添加一些必需的参数(Ejm:PROVIDER/public/oauth?redirect_uri=MYWEB/oauthDemo& response_type=code&client_id=ABCDE)。有时还有一个范围/权限/资源参数表明您的目的是什么。

    -> 然后用户登录并使用代码重定向到您的端点 MYWEB/public/oauth

  2. 现在您必须通过 POST 请求访问 token 到提供者端点。示例:

    POST 提供商?code=d5Q3HC7EGNH36SE3N& client_id=d4HQNPFIXFD255H& client_secret=1a98b7cb92407cbd8961cd8db778de53& redirect_uri= https://example.com/oauthDemo& grant_type=authorization_code

  3. 现在您拥有了 access_token,您可以使用它来获取信息或使用 JWT 对其进行解码。


清楚这一点,并看到您的调用似乎是正确的:

  #<struct Faraday::Request method=:post, path="PROVIDER/oauth/access_token", params={}, headers={"User-Agent"=>"Faraday v0.9.2", "Content-Type"=>"application/x-www-form-urlencoded"}, body={"grant_type"=>"authorization_code", "code"=>"aPexxxvUg", "client_id"=>"xxxxxur303GXEch7QK9k", "client_secret"=>"xxxxxxcad97b3d252e2bcdd393a", :redirect_uri=>"MYWEB/auth/my_app_strategy/callback"}, options=#<Faraday::RequestOptions (empty)>>

由于响应是“HTTP Status 400 - Inadequal OAuth consumer credentials.”,我想也许你:

一个。您的客户端在提供者上配置不当。通常,您过去常常在提供商网站上进行基本配置,以便他可以识别您。所以可能没有配置好。

第一步(在重定向到提供程序中)缺少或配置了错误的资源/权限/范围参数。因此,当您请求 token 时,就会出现问题。

关于ruby-on-rails - 为自定义 omniauth 策略获取 "Authentication failure! invalid_credentials: OAuth2::Error",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37342663/

相关文章:

ruby-on-rails - 我仍然不赞成rake/rdoctask

ruby - 带哈希的 RSpec match_array

ruby-on-rails - Ruby Net::FTP,从 ftp.list() 中提取文件名

javascript - react 路由器需要oauth 2客户端实现

oauth - 为什么下载字幕会返回“需要登录”?

ruby-on-rails - 如何在 collection_radio_buttons 中使用枚举

ruby-on-rails - gem 安装错误,找不到索引,ruby on rails

ruby-on-rails - 记录运动队的比赛 - 多对多关系?

ruby - 在本地扩展 Faker gem 未初始化常量 Faker::xxx

google-cloud-platform - 添加源时,对于给定客户端 ID,源是 "not allowed"