Theory

Same token, a different door

In lesson 8a we built the session-token contract: the server issues one JWT, the client stores and sends it. Google sign-in doesn't create a new contract — it just adds another way to obtain that same token.

Compare the two paths:

Email (8a):   email+password    ─▶ POST /login       ─▶ our JWT
Google (8b):  Google ID token   ─▶ POST /auth/google ─▶ our JWT   (the same one!)

From there on, the app can't tell the differenceSecureTokenStorage, AuthInterceptor, orders (lesson 9) all work identically no matter how you signed in. That's the heart of this lesson: same token, a different door.

The full Google flow:

1. App: Credential Manager shows the Google account picker
2. User picks an account → Google returns an "ID token" (a signed JWT)
3. App sends the ID token → POST /auth/google
4. Server verifies it with Google (signature, aud, exp) → idtoken.Validate
5. Server finds/creates the user → issues OUR session JWT
6. App stores that JWT — exactly like 8a

The Google ID token ≠ our session token. The Google token only proves "Google confirms this is user X." We trust it only after verifying on the server, and then we issue our own token. The client never talks to our DB directly with a Google token.

Console setup (Google Cloud Console). Before writing code you need two OAuth clients:

  • Android client — tied to your app's package name (eif.viko.lt.pica) and your debug SHA-1 signature. It's what lets the phone obtain a Google token at all.
  • Web client — its ID is used by BOTH the app (setServerClientId) AND the server (as the aud it checks). This is the source of the most common gotcha, which we'll cover.

Verify-docs. We use Credential Manager (androidx.credentials + "Sign in with Google") — the current API. The old GoogleSignInClient is deprecated — don't author against it.