Google oauth2 with devise and omniauth processed a

2019-09-08 15:36发布

问题:

I'm trying to configure a new rails4.2 app to authenticate against Google Oauth2.

I seem to be successfully going through the process, but it's being treated as a failure.

The initial authorisations seems to go well until google sends to the callback. Then it seems to be incorrectly identified as a failure.

The error message given is: Could not authenticate you from Google because "Invalid credentials".

I've googled for a solution, but to no avail.

Is it possible to turn on additional logging to understand why it's choosing to process via the failure method?

Here's the log of a request:

Started GET "/users/auth/google" for 127.0.0.1 at 2016-04-17 09:37:33 +0800
Started GET "/users/auth/google/callback?state=<<state>>&code=<<code>>" for 127.0.0.1 at 2016-04-17 09:37:45 +0800
Processing by Users::OmniauthCallbacksController#failure as HTML
  Parameters: {"state"=>"<<state>>", "code"=>"<<code>>"}
Redirected to http://test_app.dev/sign_in
Completed 302 Found in 1ms (ActiveRecord: 0.0ms)

When testing, I clicked allow when google prompted me, and the url looks good, so why is this being processed as if it were a failure?

config/initializer/devise.rb

  config.omniauth :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ['GOOGLE_CLIENT_SECRET'],
         :strategy_class => OmniAuth::Strategies::GoogleOauth2,
         :name => 'google',
         :scope => 'email,profile,contacts',
         :access_type => 'offline',
         :image_aspect_ratio => 'square'

routes.rb

  devise_for :users, :controllers => { omniauth_callbacks: 'users/omniauth_callbacks' }
  resources :users

  devise_scope :user do
    get 'sign_in', :to => 'devise/sessions#new', :as => :new_user_session
    get 'sign_out', :to => 'devise/sessions#destroy', :as => :destroy_user_session
  end

controllers/users/omniauth_callbacks_controller.rb

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def google
      logger.debug 'Omniauth callback called' # Never get's called
  end
end

application_controller.rb

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception

  # Direct to user profile after sign in
  def after_sign_in_path_for(resource)
    user_path(current_user)
  end

  # Needed by Devise when using omniauth
  def new_session_path(scope)
    new_user_session_path
  end
end

My gems:

Using warden 1.2.6
Using devise 3.5.6
Using oauth2 1.0.0
Using omniauth 1.2.2
Using omniauth-oauth2 1.4.0
Using omniauth-google-oauth2 0.4.1

回答1:

The short answer is because your creds are wrong. You're calling ENV on the first but not on the second argument in your config hash.

The better answer is.. use a better mousetrap.

Sometimes using ENV for storing keys can be problematic, you might not have a key loaded in the same terminal that you launched your server in, or if you are in production you might not be able to use see the ENV to know that it's missing keys. It easier to use a secrets file. That's ok, rails provides it for just that reason.

config/secrets.yml

You can store any key you want in there in yml format. MAKE SURE to add the file to your .gitignore because you absolutely don't want to store a file with secret keys in a repo somewhere. You'll ahve to manually copy your secrets file to your production server.

development:
  omniauth_provider_key: 13232423423242315
  omniauth_provider_secret: 2222222222228eff721a0322c
  domain_name: lvh.me
  secret_key_base: 6ec9ae65d4de59aa1a7ssxxsdifwn9392203905c53a264ffd8255a601d7417b1ed7d4cef67f359e373472f0160aeb9698fa69578a1497b5b99209afd0e

You can also have the same structure for production staging or test

Now.. once you've done that (created the file and added your keys to it) now you can call the key from the initializer

  config.omniauth :google_oauth2, Rails.application.secrets.omniauth_provider_key, Rails.application.secrets.omniauth_provider_secret,
     :strategy_class => OmniAuth::Strategies::GoogleOauth2,
     :name => 'google',
     :scope => 'email,profile,contacts',
     :access_type => 'offline',
     :image_aspect_ratio => 'square'