Taking it to production

OAuth with Google · lesson 8 of 9 · 5 min read

Consent screen, verification, and what breaks on the day you launch.

Open this lesson in the learning hub

Key points

  • A project in testing mode only allows the test users you list, and refuses everyone else. Moving to production requires publishing the consent screen.
  • Requesting sensitive or restricted scopes triggers Google verification, which takes time and may require a security assessment. Basic openid profile email does not.
  • Register every redirect URI you actually use - local development, staging and production are three different entries, matched exactly.
  • A refresh token is only issued when you request offline access, and typically only on the first consent. Losing it means the user has to re-consent, so store it when you get it.
  • Rotate the client secret if it has ever been committed, printed in a log, or shared. Google lets you hold two secrets briefly so rotation need not be an outage.
  • Handle the user revoking access from their Google account page: your refresh token stops working, and the correct response is to prompt them to sign in again rather than retrying.

Example

# The console checklist, in order:
#
#   1. OAuth consent screen
#      - External unless you are Workspace-only
#      - app name, support email, logo, privacy policy and terms URLs
#      - authorised domains
#      - PUBLISH it, or only listed test users can sign in
#
#   2. Scopes
#      openid, profile, email          no verification needed
#      Gmail, Drive, Calendar          SENSITIVE or RESTRICTED
#                                      -> verification, and possibly a
#                                         third-party security assessment
#
#   3. Credentials -> OAuth client ID -> Web application
#      Authorised redirect URIs, EXACT, one line per environment:
#        http://localhost:8080/login/oauth2/code/google
#        https://staging.example.com/login/oauth2/code/google
#        https://example.com/login/oauth2/code/google

---
# Refresh token: only with offline access, and usually only ONCE.
spring:
  security:
    oauth2:
      client:
        provider:
          google:
            authorization-uri: >-
              https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&prompt=consent
#   access_type=offline  -> issue a refresh token
#   prompt=consent       -> force re-consent, so you get one again
#
#   Without prompt=consent, a returning user consents silently and NO
#   refresh token is issued - which is why it works in development
#   (first consent) and fails in production (returning users).

---
# THE FAILURES YOU WILL ACTUALLY HIT:
#
#   redirect_uri_mismatch   the URI is not registered EXACTLY.
#                           Behind a proxy? set forward-headers-strategy.
#   access_blocked          consent screen is unpublished, or the scope
#                           needs verification
#   invalid_grant           refresh token revoked or expired ->
#                           prompt a fresh sign-in, do not retry
#   no refresh_token        missing access_type=offline, or a returning
#                           user consented silently

Publish the consent screen, register every redirect URI exactly, and request offline access or you will never get a refresh token.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the OAuth with Google course, and every lesson in it is listed on the OAuth with Google contents page.