0% found this document useful (0 votes)
16 views3 pages

Studybo Authentication Workflow

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views3 pages

Studybo Authentication Workflow

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 3

Studybo Authentication — Architecture & Flow

Overview
Studybo uses Firebase Authentication on the client and Firebase Admin (server) to implement a secure
social login flow. The backend verifies third■party tokens, upserts a user document in Firestore, issues a
short■lived Firebase Custom Token, and relies on a NestJS guard to protect APIs by validating Firebase
ID tokens on each request.

Key Components
• Frontend ([Link]): Uses Firebase Web SDK to sign in with Google, obtains a Firebase ID token,
calls the backend. • AuthController (/auth/social-login): Public endpoint to verify a social token and return a
Firebase Custom Token. • AuthService: Verifies Google or Firebase tokens, creates/updates Firestore
user, issues a custom token with custom claims. • FirestoreDatabase: Thin wrapper exposing collections
like users/groups. • FirebaseAuthGuard: Validates Authorization: Bearer for protected routes, attaches
[Link].

End-to-End Social Login (Happy Path)


1) User Action (Browser)
• User clicks “Sign in with Google”. The Firebase Web SDK completes Google sign■in and returns a
Firebase ID token bound to the project.

2) Call Backend for Custom Token


• Frontend POSTs to /auth/social-login with { type: 'FIREBASE', token: }. • Controller delegates to
[Link]().

3) Server: Verify Token


• For FIREBASE type, [Link]() calls firebase-admin
[Link](idToken, true). Passing 'true' enforces revocation checks. • For GOOGLE type
(alternative path), verify via Google [Link]().

4) Server: Upsert User in Firestore


• getUserByEmail() searches users collection by email. • If not found → createUser(email, profile). • If
found → updateProfileDetails(uid, profile).

5) Server: Issue Custom Token


• createCustomToken(uid, { userFirstName }) produces a Firebase Custom Token signed by the service
account.

6) Client: Establish Session


• Frontend receives { firebaseToken, user } from server, then calls
signInWithCustomToken(firebaseToken). • Firebase returns a fresh ID token (1■hour expiry); SDK
auto-refreshes it.

7) Accessing Protected APIs


• Client includes Authorization: Bearer on API calls. • FirebaseAuthGuard verifies the ID token and injects
[Link] = { uid, email, name }.
Sequence (ASCII)
User Browser(Firebase) Backend (NestJS) Firebase Admin Firestore
| Click "Sign in with Google" | | |
|------------------------------>| | |
| Google sign-in popup | | |
| returns ID_TOKEN | | |
|<------------------------------| | |
| POST /auth/social-login | | |
| {type:FIREBASE, token:ID_TOK}|------------->| |
| | verifyIdToken(ID_TOKEN, true) --------->|
| | | decoded {email,name} |
| |<------------------------------------------
| | upsert user ---------------------------->| (users)
| |<------------------------------------------
| | createCustomToken(uid, claims) -------->|
| |<------------------------------------------
| {firebaseToken, user} |<-------------| |
| signInWithCustomToken |------------->| |
| obtain fresh ID_TOKEN |<-------------| |
| Authorization: Bearer ID_TOK |------------->| [Link] |
| (protected API) | |→ [Link] = {uid,email} |

Important Files & Responsibilities


• [Link]: /auth/social-login (public), /auth/test-user-login (public for debugging), /auth/login-ui,
/auth/delete-me. • [Link]: verifySocialToken(), verifyGoogleToken(), verifyFirebaseToken(),
authenticate(), createUser(), updateProfileDetails(), createCustomToken(), deleteUser(). •
guards/[Link]: FirebaseAuthGuard validates ID tokens and sets [Link]. •
firebase/[Link]: Collection helpers and simple operations.

User Deletion & Anonymization


DELETE /auth/delete-me (protected): • Loads the user doc by [Link]. • SHA■256 hashes PII (email,
firstName, lastName, avatar), sets isDeleted=true and anonymizedAt. • Note: Code currently comments
out disabling in Firebase Auth; consider disabling or deleting the auth user as a follow■up.

Security Considerations & Good Practices


• Always require HTTPS and set secure, strict headers (CSP, HSTS). • Store client IDs and secrets in
environment variables, not code. • Keep firebase-admin credentials scoped and rotated. • Use
verifyIdToken(..., true) (already used) to enforce revocation. • Consider role■based claims; validate them
inside guards. • Rate■limit public endpoints like /auth/social-login. • Log audit trails carefully (avoid logging
raw tokens in production).

Testing the Flow


1) Open /auth/login-ui and sign in with Google. 2) The page will call /auth/social-login and then
signInWithCustomToken(). 3) Copy the displayed ID token and call any protected API with Authorization:
Bearer . 4) Try calling the same API without the header to observe 401 from FirebaseAuthGuard.

Common Edge Cases


• Expired/Revoked Tokens: verifyIdToken(..., true) will reject; client should re-auth. • Partially missing
profile fields from providers: code defensively assigns empty strings. • Race on first login: ensure Firestore
upsert completes before issuing custom token (this flow already does).
API Quick Reference
POST /auth/social-login
{
"type": "FIREBASE" | "GOOGLE",
"token": "<id_token_from_provider_or_firebase>"
}

Response:
{
"firebaseToken": "<custom_token>",
"user": {
"uid": "...",
"email": "...",
"profile": {"firstName": "...", "lastName": "...", "avatar": "..."},
"createdAt": 1710000000000,
"updatedAt": 1710000000000
}
}

GET /auth/test-user-login
Returns a custom token for a fixed user (for debugging).

DELETE /auth/delete-me
Protected. Requires Authorization: Bearer . Soft■deletes & anonymizes Firestore user.

Guarded Routes
Any route without @PublicApi() is protected by FirebaseAuthGuard. The guard reads Authorization
header, verifies the ID token, and sets [Link] { uid, email, name }.

What Makes This Design Solid


• Strong Boundary: Only the backend can mint custom tokens; clients must present a valid
provider/Firebase token first. • Server■Side Source of Truth: Firestore upsert guarantees the user record
exists before issuing a session. • Simple Extensibility: Add Apple or other providers by implementing
verify*Token() and reusing the same flow. • Observability: Strategic logs around verification and upserts
(mindful of PII/tokens in production).

Next Steps & Enhancements


• Add roles/permissions to custom claims and enforce them in guards. • Add refresh logic and token
listeners on the client for more granular UX. • Implement hard delete/disable in Firebase Auth on account
deletion. • Move IDs/keys to environment variables, and add input validation on /auth/social-login.

You might also like