【问题标题】:Getting No route matches [GET] "/auth/google_oauth2" error while trying to authenticate with Gmail API in rails尝试在 rails 中使用 Gmail API 进行身份验证时出现 No route matches [GET] "/auth/google_oauth2" 错误
【发布时间】:2020-12-15 14:23:52
【问题描述】:

在尝试使用 Rails 中的 Gmail API 进行身份验证时,我发现没有路由匹配 [GET] "/auth/google_oauth2" 错误。

按照这篇文章https://www.twilio.com/blog/2014/09/gmail-api-oauth-rails.html,我正在实现Gmail API 集成。

代码似乎是正确的。但不知道是什么问题。

在路由文件中:

  root to: 'visitors#index'
  if defined?(Devise)
    devise_for :users, :controllers => { :registrations => "registrations", :passwords => "passwords", omniauth_callbacks: 'omniauth_callbacks' }
    devise_scope :user do
      get 'auth/:provider/callback', :to => 'users/omniauth_callbacks#facebook'
    end
  end
  get "/auth/:provider/callback" => "candidates#authenticate_from_google"

在 rake 路线中,我什至也有路线。

GET /auth/:provider/callback(.:format)  candidates#authenticate_from_google

  

在 Gemfile 中:-

gem "omniauth"
gem "omniauth-linkedin"
gem "jwt", "~> 1.4.1"
gem "linkedin-scraper", "~> 0.1.5"
gem "omniauth-facebook"
gem "omniauth-google-oauth2"
gem 'signet' 
gem 'google-api-client', '0.8.2'

在视图中

   <%= link_to("Sync", "/auth/google_oauth2" , class: "btn btn-sm btn-primary", method: :get)%>

在 /app/controllers/candidates_controller.rb 中

   def authenticate_from_google
    @auth = request.env['omniauth.auth']['credentials']
    if @auth
      @identity = current_user.identities.new
      @identity.provider = "google_oauth2"
      @identity.access_token = @auth['token']
      @identity.refresh_token = @auth['refresh_token']
      @identity.expires_at = Time.at(@auth['expires_at']).to_datetime
      @identity.save
      flash[:notice] = "Successfully Authenticated from Google"
    else
      flash[:notice] = "Google Authentication failed"
    end
    redirect_to account_path
  end

在 /config/initializers/omniauth.rb 中

  Rails.application.config.middleware.use OmniAuth::Builder do
  provider :google_oauth2, ENV['GOOGLE_API_KEY'], ENV['GOOGLE_SECRET_KEY'], {
  scope: ['email',
    'https://www.googleapis.com/auth/gmail.send'],
    access_type: 'offline'}
end

在 /config/initializers/devise.rb 中

Devise.setup do |config|

  config.omniauth :linkedin, ENV['LINKEDIN_API_KEY'], ENV['LINKEDIN_SECRET_KEY']
  config.omniauth :facebook, ENV['FACEBOOK_API_KEY'], ENV['FACEBOOK_SECRET_KEY'] ,
              :info_fields => 'email,name,first_name,last_name,verified', :display => 'page', :scope => 'email'

   config.omniauth :google_oauth2, ENV['GOOGLE_API_KEY'],
                               ENV['GOOGLE_SECRET_KEY'],
                               scope: 'email,https://www.googleapis.com/auth/gmail.send',
                               access_type: 'offline'#, :prompt => "select_account",
                                skip_jwt: true
    config.timeout_in = 7.days
end

【问题讨论】:

    标签: ruby-on-rails routes gmail-api omniauth


    【解决方案1】:

    对于omniauth gem >= 2.0.0,您必须在链接按钮中指定要允许的请求方法。

    只需添加一行OmniAuth.config.allowed_request_methods = [:post, :get]

    # config/initializers/omniauth.rb
    Rails.application.config.middleware.use OmniAuth::Builder do
      OmniAuth.config.allowed_request_methods = [:post, :get]
      provider :google_oauth2, ENV['GOOGLE_API_KEY'], ENV['GOOGLE_SECRET_KEY'], {
      scope: ['email',
        'https://www.googleapis.com/auth/gmail.send'],
        access_type: 'offline'}
    end
    

    【讨论】:

      【解决方案2】:

      使用以下代码更改您的 config/initializers/onmiauth.rb 文件。

      Rails.application.config.middleware.use OmniAuth::Builder do
        provider :google_oauth2, ENV['GOOGLE_CLIENT_ID'], 
        ENV['GOOGLE_CLIENT_SECRET']
      end
      
      OmniAuth.config.allowed_request_methods = %i[get]
      

      【讨论】:

        【解决方案3】:

        从omniauth 2.0 开始,您必须对/auth/:provider 端点使用POST 方法,而不是GET,请参阅upgrade notes

        所以正确的处理方法是:

        1. 将模板中的登录链接更改为使用 POST
        link_to 'Login with Facebook', '/auth/facebook', rel: 'nofollow', method: :post
        
        1. omniauth-rails_csrf_protection gem 添加到您的 Gemfile 中
        gem 'omniauth-rails_csrf_protection'
        
        1. 调整测试
          before { OmniAuth.config.test_mode = true }
        
          it 'redirects to callback url' do
            token = SecureRandom.base64(ActionController::RequestForgeryProtection::AUTHENTICITY_TOKEN_LENGTH)
            allow_any_instance_of(ActionDispatch::Request).to receive(:session) { { _csrf_token: token } }
        
            post '/auth/facebook', params: { authenticity_token: token }
            expect(response).to redirect_to('/auth/facebook/callback')
          end
        

        就是这样!

        如果您将allowed_request_methods 设置为%i[get],您将收到此警告,因为这里的其他答案建议:

        You are using GET as an allowed request method for OmniAuth. This may leave
          you open to CSRF attacks. As of v2.0.0, OmniAuth by default allows only POST
          to its own routes. You should review the following resources to guide your
          mitigation:
          https://github.com/omniauth/omniauth/wiki/Resolving-CVE-2015-9284
          https://github.com/omniauth/omniauth/issues/960
          https://nvd.nist.gov/vuln/detail/CVE-2015-9284
          https://github.com/omniauth/omniauth/pull/809
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-12-21
          • 2017-10-23
          • 2021-09-07
          • 2021-05-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多