skip to Main Content

I am Getting No route matches [GET] "/auth/google_oauth2" error while trying to authenticate with Gmail API in rails.

by following this article https://www.twilio.com/blog/2014/09/gmail-api-oauth-rails.html, i am implementing the Gmail API integration.

code seems to be corrrect. But dont know what was the issue.

in routes file:

  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"

in rake routes, i even have the route as well.

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

  

in 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'

in views

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

in /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

in /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

in /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

3

Answers


  1. For omniauth gem >= 2.0.0 you must specify which request methods you are going to allow in your link button.

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

    Just add the line 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
    
    Login or Signup to reply.
  2. Change your config/initializers/onmiauth.rb file with below code.

    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]
    
    Login or Signup to reply.
  3. Since omniauth 2.0 you must use POST method for /auth/:provider endpoint, not GET, see upgrade notes.

    So the proper way to handle this is:

    1. Change login link in template to use POST
    link_to 'Login with Facebook', '/auth/facebook', rel: 'nofollow', method: :post
    
    1. Add omniauth-rails_csrf_protection gem to your Gemfile
    gem 'omniauth-rails_csrf_protection'
    
    1. Adjust tests
      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
    

    That’s it!

    You will get this warning if you set allowed_request_methods to %i[get] as other answers here suggest:

    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
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search