Google OAuth — Plan
Complexity: Medium Integration: Google OAuth2 login via Devise + OmniAuth
External Setup
- Go to Google Cloud Console
- Create project (e.g., "Your App Name")
- APIs & Services → Library → Enable "People API"
- APIs & Services → OAuth consent screen:
- User type: External
- App name, support email, developer email
- Scopes:
email,profile,openid - Add authorized domain
- APIs & Services → Credentials → Create OAuth Client ID:
- Type: Web application
- Redirect URIs:
https://yourdomain.com/users/auth/google_oauth2/callbackhttp://localhost:3000/users/auth/google_oauth2/callback
- Note Client ID and Client Secret
- (If in testing mode) Add test users under OAuth consent screen
Code Changes
- Add to
Gemfile:gem "omniauth" gem "omniauth-google-oauth2" gem "omniauth-rails_csrf_protection" bundle install- Add credentials via
bin/rails credentials:edit:google_oauth: client_id: "xxx.apps.googleusercontent.com" client_secret: "GOCSPX-xxx" - Migration:
bin/rails g migration AddOmniauthToUsers provider:string uid:string- Add index:
add_index :users, [:provider, :uid], unique: true bin/rails db:migrate
- Add index:
- Update
config/initializers/devise.rb: addconfig.omniauth :google_oauth2, credentials.dig(:google_oauth, :client_id), credentials.dig(:google_oauth, :client_secret), scope: "email,profile" - Add
:omniauthableto Devise modules inapp/models/concerns/user/authentication.rb:devise :magic_link_authenticatable, :invitable, :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :trackable, :omniauthable, omniauth_providers: [:google_oauth2] - Create
User::OmniauthHandlernamespaced class inapp/models/user/omniauth_handler.rb:resolvemethod: find by provider+uid, or find by email and link, or create new user
- Create
app/controllers/users/omniauth_callbacks_controller.rb:google_oauth2action: callsUser::OmniauthHandler.new(auth).resolve, signs in, redirectsfailureaction: redirects to sign_in with error
- Update
config/routes.rb— add to devise_for controllers hash:omniauth_callbacks: "users/omniauth_callbacks" - Update
app/views/devise/shared/_links.html.erbto render OmniAuth provider button with graceful error handling
Verification
- Visit
/users/sign_in→ "Sign in with Google" button visible - Click → Google OAuth flow → redirected back → signed in
- Existing user with same email can link Google account
- New OAuth user gets personal organization created
- Run
bin/ci— existing tests still pass