Auth
What it is
Signup, login, and account-recovery for the platform. Supports password-based auth, Google/Apple OAuth, and a gift-link-driven signup path that ties new accounts to a gift/event they arrived from.
Core concepts
- Login identifier is email-or-phone, not username —
identifieris checked for an@to decide which lookup to run (getUserByEmailvs.getUserByPhoneNumberafterformatPhoneNumbernormalization). Username isn't a login credential. - Two separate ban checks on every login attempt: once against the raw
identifier(email/phone) before the user record is even loaded, and again against the resolved user's current email/phone/username/name after lookup. The second check exists specifically to catch someone who changed their contact info after being banned — a ban on the original identifier alone wouldn't survive that. - Phone verification can happen inline with signup —
POST /auth/signupaccepts an optionalotpin the payload; if present, it's verified immediately and the account is created already phone-verified, skipping the separateverify-otpround trip. If omitted, the account is created unverified andPOST /auth/verify-otp/POST /auth/resend-otphandle it afterward.
How it works
Standard signup/login
POST /auth/signup— creates the account (password + phone/email), optionally verifying phone via an inline OTP as above.POST /auth/verify-otp/POST /auth/resend-otp— complete phone verification if it wasn't bundled into signup. Both requireauthMiddleware, so the account must already be created and the client already holding a token — verification is a post-signup step against an authenticated session, not a pre-signup gate.POST /auth/signin—identifier+password, returns a JWT (signToken(user.id, Role.User)).POST /auth/logout— invalidates the current session/token.
OAuth (Google / Apple)
POST /auth/google and POST /auth/apple each verify the provider's token/credential server-side and either log in an existing account or create one, bypassing the password/OTP flow entirely — these are the accounts that never get a password field populated.
Gift-link signup
POST /auth/signup-with-eventid (signupWithGiftLink) — a distinct signup path used when someone arrives via a gift link (Secret Santa / My Birthday — see event types in the Events guide) rather than the general app. Takes the usual profile fields plus slug and sourceEventId, linking the new account back to the gift event that brought them in (eventTypeId is used instead when sourceEventId is 0, for signups not tied to a specific existing gift event).
Account recovery
POST /auth/forgot-password/initiate → POST /auth/forgot-password/verify — a standard initiate/verify OTP pair (Zod-validated, unlike most of this module which is still on validatorjs), separate from the signup-time OTP flow.
Key business rules & edge cases
- Suspended accounts fail login with a distinct error (
AccountStatus.SUSPENDED) before password is even checked in some paths — don't conflate "wrong password" and "account suspended" when building client-side error handling; they're different failure modes with different remediation (contact support vs. retry). - A successful login fires an async, non-blocking Customer.io identify call (creates-or-updates the CRM profile with
login_method: 'password') — a failure here is logged but never fails the login itself. - Because phone verification can be satisfied either inline at signup or via the separate OTP endpoints, don't assume a freshly-created account is unverified — check
isPhoneNumberVerifiedrather than inferring it from which signup path was used.
Related endpoints
POST /v1/auth/signup, POST /v1/auth/signin, POST /v1/auth/google, POST /v1/auth/apple, POST /v1/auth/signup-with-eventid, POST /v1/auth/verify-otp, POST /v1/auth/resend-otp, POST /v1/auth/logout, POST /v1/auth/forgot-password/initiate, POST /v1/auth/forgot-password/verify. Not yet in the generated OpenAPI spec.
Related code
src/modules/auth/auth.route.ts,auth.controller.ts,auth.service.tssrc/modules/user/user.service.ts—createUser(shared by signup)src/models/ban-list.model.ts—BanListModel.checkBannedsrc/shared/utils/jwt.util.ts—signToken