Sign in with Google
Auth
Sign in with Google
Exchange a Firebase Google ID token for a Swappr session. Creates the account on first use.
POST
Sign in with Google
Overview
Signs a user in (or registers them on first use) with their Google account. The mobile app performs native Google sign-in via the Firebase Auth SDK, obtains a Firebase ID token, and POSTs that token here. The backend verifies the token withfirebase-admin — checking the signature against Google’s rotating public keys, the expiry, the issuer, and that the token’s audience matches our Firebase project — then returns a Swappr access + refresh token pair, exactly like /login.
There are three outcomes:
- First-time Google user → a new account is created (
emailVerifiedmirrors the token’semail_verifiedclaim,firstName/lastNamestartnull, consent flags startfalse). The response is201 CreatedwithisNewUser: true. The client should route the user into onboarding. - Returning Google user (same Google identity) →
200 OKwithisNewUser: false. - Email already owned by a non-Google account →
409 ACCOUNT_EXISTS_VIA_OAUTH. Swappr does not silently attach Google to a pre-existing email/password (or Apple) account — that would allow account takeover by anyone able to mint a Google token for that address. The user must sign in with their original method and link Google deliberately from settings (account linking is future work).
isNewUser (or onboardingStep) to decide whether to show onboarding.
Authentication
None required. The Firebase ID token in the body is the credential.Path parameters
None.Query parameters
None.Request body
| Field | Type | Required | Allowed values | Example |
|---|---|---|---|---|
idToken | string | yes | A Firebase ID token (signed JWT) from the app’s native Google sign-in. 1..8192 chars. | eyJhbGciOiJSUzI1NiIsImtpZCI6... |
Example payload
Response — 201 Created (new user) / 200 OK (returning user)
| Field | Type | Notes | Example |
|---|---|---|---|
accessToken | string | Short-lived RS256 JWT (15 min). Send as Authorization: Bearer <token>. | eyJhbGci... |
refreshToken | string | Opaque 256-bit token. Exchange via /refresh. | r8Kf... |
isNewUser | boolean | true when this call created the account (HTTP 201), false for a returning user (HTTP 200). | true |
user.id | string | The user’s ID. | usr_01HZQ7K3M4N5P6Q7R8S9T0V1W2 |
user.email | string | The verified Google email (lowercased). | alice@gmail.com |
user.firstName | string | null | null until set during onboarding / profile edit. | null |
user.lastName | string | null | null until set. | null |
user.avatarUrl | string | null | null until set. | null |
user.onboardingStep | string | Current onboarding step; first step for a brand-new user. | verify_tenancy |
user.tenancyStatus | string | Tenancy verification status. | not_submitted |
user.subscriptionStatus | string | Subscription state. | free_launch |
Example response — 201
Error responses
| Status | Code | Meaning |
|---|---|---|
| 400 | VALIDATION_FAILED | idToken missing, blank, or longer than 8192 chars. |
| 401 | OAUTH_INVALID_TOKEN | Token failed verification — malformed, expired, wrong signature, or minted for a different Firebase project; or it carried no email. |
| 403 | ACCOUNT_BANNED | The matched account is banned. |
| 409 | ACCOUNT_EXISTS_VIA_OAUTH | The email already belongs to a non-Google account. Sign in with the original method, then link Google. |
| 503 | OAUTH_NOT_CONFIGURED | Firebase credentials (FCM_SERVICE_ACCOUNT_JSON + FIREBASE_PROJECT_ID) are not set in this environment. |
Example error — 401
Side effects
- First-time sign-in only: inserts a new row into the
userscollection withoauthProvider: 'GOOGLE',oauthIdset to the Firebaseuid,passwordHash: null, andemailVerifiedtaken from the token. - Issues a new session: inserts a
refresh_tokensrow and signs an access JWT. - No email is sent (no OTP needed — Google has already verified the address).
Rate limiting
This endpoint shares the auth burst limiter (10 requests / minute / IP) with/login, on top of the router-level /auth/* cap.
Notes for the client
- Configure Firebase in the app with the bundled
google-services.json(Android) /GoogleService-Info.plist(iOS) for projectswappr-de6ce, bundle idcom.swappr.app. - Do native Google sign-in (Firebase Auth
GoogleAuthProvider), then read the ID token (user.getIdToken()), not the access token. - POST
{ idToken }here, store the returned SwappraccessToken/refreshToken, and proceed exactly as with email login.
See also
- Login (email + password) — the equivalent password flow.
- Refresh — rotate the session.
- Errors — full error code catalog.