Skip to main content
Was this helpful?

Authentication API

Identity and Session Management

Register users, issue sessions, complete onboarding, and manage API keys

This page documents the non-admin authentication surface from the backend code. It covers the real /api/auth routes plus user-owned /api/api-keys management.

JWT bearerRefresh cookiesCSRF for browser mutationsMFA and OAuth

Source

  • Controller: backend-nestjs/src/auth/auth.controller.ts
  • DTOs: backend-nestjs/src/dto/auth.dto.ts, backend-nestjs/src/dto/onboarding.dto.ts
  • User API keys controller: backend-nestjs/src/api-security/controllers/api-key.controller.ts
  • User API key DTOs: backend-nestjs/src/api-security/dto/api-key.dto.ts
  • JWT guard: backend-nestjs/src/auth/guards/jwt-auth.guard.ts
  • CSRF middleware: backend-nestjs/src/common/middleware/csrf-protection.middleware.ts

Authentication Model

ModeWhere it appliesNotes
Publicregistration, login, availability checks, refresh, OAuth callbacksNo bearer token required
JWT bearermost signed-in routesAuthorization: Bearer <token>
Refresh cookiebrowser refresh/logout flowPOST requests still need CSRF when cookie-authenticated
User API keyselected routes protected by JwtAuthGuardSend x-api-key or Authorization: ApiKey <token>
JWT only/api/api-keys management endpointsThese use AuthGuard('jwt'), not the broader JwtAuthGuard

Important implementation notes:

  • JwtAuthGuard also supports user API keys when ApiKeyService is wired in.
  • Incomplete-onboarding users are blocked from most non-/auth routes until onboarding is finished.
  • Browser-based mutating requests use CSRF protection and must include x-csrf-token.

Endpoint Reference

Auth Controller

MethodPathPurposeRequest or queryAuthSource
GET/api/auth/csrfIssue or return the active CSRF token.NonePublicauth/auth.controller.ts
POST/api/auth/registerCreate a new user and issue session tokens.Body: username,email,password,firstName,lastName,rolePublicauth/auth.controller.ts
POST/api/auth/loginCreate a session for an existing user.Body: username,password,captchaToken,honeypot,mfaCode,mfaRecoveryCodePublicauth/auth.controller.ts
GET/api/auth/username-availabilityCheck whether a username is free.Query: usernamePublicauth/auth.controller.ts
GET/api/auth/email-availabilityCheck whether an email is free.Query: emailPublicauth/auth.controller.ts
GET/api/auth/profileRead the authenticated user profile snapshot.NoneJWT or user API keyauth/auth.controller.ts
POST/api/auth/complete-onboardingFinish the onboarding wizard for the current user.Body: onboarding fieldsJWT or user API keyauth/auth.controller.ts
POST/api/auth/refreshRotate the refresh token and issue a new access token.Body: refreshToken or refresh cookiePublic session flowauth/auth.controller.ts
POST/api/auth/logoutRevoke the current refresh token family and clear browser cookies.Body: optional refreshTokenJWT or user API keyauth/auth.controller.ts
POST/api/auth/widget-tokenIssue the Android widget token.NoneJWT or user API keyauth/auth.controller.ts
GET/api/auth/mfa/statusRead MFA setup or enabled status.NoneJWT or user API keyauth/auth.controller.ts
POST/api/auth/mfa/setupStart TOTP setup and return provisioning material.NoneJWT or user API keyauth/auth.controller.ts
POST/api/auth/mfa/enableVerify a TOTP code and enable MFA.Body: codeJWT or user API keyauth/auth.controller.ts
POST/api/auth/mfa/disableDisable MFA with a current code or recovery code.Body: code,recoveryCodeJWT or user API keyauth/auth.controller.ts
GET/api/auth/googleStart Google OAuth.NonePublic redirectauth/auth.controller.ts
GET/api/auth/google/callbackGoogle OAuth callback.Provider query paramsPublic callbackauth/auth.controller.ts
GET/api/auth/microsoftStart Microsoft OAuth.NonePublic redirectauth/auth.controller.ts
GET/api/auth/microsoft/callbackMicrosoft OAuth callback.Provider query paramsPublic callbackauth/auth.controller.ts

User API Keys

MethodPathPurposeRequest or queryAuthSource
GET/api/api-keysList the current user's API keys.NoneJWT bearer onlyapi-security/controllers/api-key.controller.ts
POST/api/api-keysCreate a new API key.Body: name,scopes,tier,expiresInDays,rotateInDaysJWT bearer onlyapi-security/controllers/api-key.controller.ts
POST/api/api-keys/:id/rotateRotate an API key and return the new plaintext secret once.Path: idJWT bearer onlyapi-security/controllers/api-key.controller.ts
DELETE/api/api-keys/:idRevoke an API key.Path: idJWT bearer onlyapi-security/controllers/api-key.controller.ts

Request Shapes

Register

RegisterDto in backend-nestjs/src/dto/auth.dto.ts

  • username: required, sanitized, safe text, 3 to 64 chars
  • email: required, lowercased, valid email, max 254 chars
  • password: required, 6 to 128 chars, strong-password validator
  • firstName: optional, safe text, max 80 chars
  • lastName: optional, safe text, max 80 chars
  • role: optional enum UserRole

Login

LoginDto in backend-nestjs/src/dto/auth.dto.ts

  • username: required, 1 to 254 chars, username or email
  • password: required, 1 to 128 chars
  • captchaToken: optional, max 2048 chars
  • honeypot: optional, max 120 chars, should stay empty
  • mfaCode: optional, must match ^\d{6}$
  • mfaRecoveryCode: optional, max 32 chars

Complete onboarding

CompleteOnboardingDto in backend-nestjs/src/dto/onboarding.dto.ts

  • username: optional, 3 to 64 chars, [a-zA-Z0-9_.]+
  • firstName: optional, max 80 chars
  • lastName: optional, max 80 chars
  • profilePictureUrl: optional URL, max 2048 chars
  • language: required enum en|de|fr|hu
  • timezone: required IANA timezone, max 100 chars
  • timeFormat: required 12h|24h
  • weekStartDay: required integer 0..6
  • defaultCalendarView: required month|week
  • themeColor: required, one of the allowed onboarding palette colors
  • privacyPolicyAccepted: required, must be true
  • termsOfServiceAccepted: required, must be true
  • productUpdatesEmailConsent: optional boolean
  • privacyPolicyVersion: optional, max 64 chars
  • termsOfServiceVersion: optional, max 64 chars
  • calendarUseCase: optional enum personal|business|team|other
  • setupGoogleCalendarSync: optional boolean
  • setupMicrosoftCalendarSync: optional boolean

MFA

  • EnableMfaDto.code: required 6-digit string
  • DisableMfaDto.code: optional 6-digit string
  • DisableMfaDto.recoveryCode: optional, max 32 chars

User API keys

CreateApiKeyDto in backend-nestjs/src/api-security/dto/api-key.dto.ts

  • name: required, safe text, max 120 chars
  • scopes: optional enum array read|write|admin
  • tier: optional enum guest|user|premium
  • expiresInDays: optional integer, minimum 1
  • rotateInDays: optional integer, minimum 1

Example Calls

Bootstrap a browser session

curl "$PRIMECAL_API/api/auth/csrf" -c cookies.txt
curl -X POST "$PRIMECAL_API/api/auth/login" \
-b cookies.txt \
-c cookies.txt \
-H "Content-Type: application/json" \
-H "x-csrf-token: $CSRF_TOKEN" \
-d '{
"username": "mayblate",
"password": "StrongPassword123!"
}'

Complete onboarding

curl -X POST "$PRIMECAL_API/api/auth/complete-onboarding" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"language": "en",
"timezone": "Europe/Budapest",
"timeFormat": "24h",
"weekStartDay": 1,
"defaultCalendarView": "week",
"themeColor": "#3b82f6",
"privacyPolicyAccepted": true,
"termsOfServiceAccepted": true,
"calendarUseCase": "personal"
}'

Create a user API key

curl -X POST "$PRIMECAL_API/api/api-keys" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "calendar-sync-job",
"scopes": ["read", "write"],
"tier": "user",
"expiresInDays": 90,
"rotateInDays": 30
}'

Response Notes

  • AuthResponseDto returns access_token, token_type, expires_in, refresh_expires_at, issued_at, optional refresh_token, and a user block.
  • Native clients can receive a plaintext refresh_token; browser flows rely on the refresh cookie.
  • API key creation and rotation return the plaintext API key only once.

Best Practices

  • Use GET /api/auth/csrf before any cookie-backed POST, PATCH, PUT, or DELETE call from a browser client.
  • Treat /api/auth/refresh as a session-maintenance endpoint, not a primary login path.
  • Keep MFA prompts conditional. Only send mfaCode or mfaRecoveryCode when the login flow requires it.
  • Use user API keys for server-to-server user automation, but use JWT bearer auth for /api/api-keys management itself.
  • Prefer provider redirects from /api/auth/google and /api/auth/microsoft instead of building your own OAuth URLs.