Skip to main content

Authentication Flow

End-to-end flows for login, registration, token refresh, and ZITADEL integration.

Services Involved

auth-service, user-service (proxied to user-base-ms), Firebase, ZITADEL, Redis

Login (Firebase)

Steps

  1. Client calls POST /api/v1/iam/exchange on auth-service with email + password
  2. auth-service validates credentials against Firebase (Admin SDK verifyIdToken or signInWithEmailAndPassword)
  3. auth-service calls user-service GET /user/by-email?email= to fetch the user record
  4. user-service proxies to user-base-ms GET /api/v1/users?email=
  5. auth-service generates JWT access token (RS256) and refresh token
  6. Sets accessToken and refreshToken as HTTP-only cookies
  7. Returns user data in response body (tokens are in cookies only)
Client --> auth-service --> Firebase (validate)
--> user-service --> user-base-ms (fetch user)
<-- JWT tokens (cookies + body)

Registration (Firebase)

Steps

  1. Client calls POST /api/v1/iam/register on auth-service with email + password + name
  2. auth-service creates the user in Firebase (Admin SDK createUser)
  3. auth-service calls user-service POST /user to create the user record
  4. user-service proxies to user-base-ms POST /api/v1/users
  5. auth-service generates JWT tokens
  6. Returns tokens

If step 3 fails (user-service creation), auth-service rolls back by deleting the Firebase account.

Client --> auth-service --> Firebase (create account)
--> user-service --> user-base-ms (create user record)
<-- JWT tokens

Login (ZITADEL)

Steps

  1. Client completes ZITADEL OAuth flow and gets ZITADEL access/ID tokens
  2. Client calls POST /api/v1/iam/zitadel/exchange on auth-service with ZITADEL tokens
  3. auth-service validates the ZITADEL access token via token introspection
  4. auth-service validates the ZITADEL ID token via JWKS
  5. auth-service calls user-service GET /user/zitadel/:zitadelUserId to find existing user
  6. If not found, creates the user via POST /user/zitadel
  7. Creates a session in Redis (zitadel/{provider}/{orgId}/{userId})
  8. Generates Jeen JWT tokens
  9. Returns tokens
Client --> auth-service --> ZITADEL (introspect + JWKS)
--> user-service --> user-base-ms (find/create user)
--> Redis (create session)
<-- JWT tokens

Token Refresh

Steps

  1. Client calls POST /api/v1/iam/token/refresh on auth-service
  2. auth-service reads the refreshToken cookie
  3. Validates the refresh token against the in-memory token store
  4. Generates a new access token + refresh token pair
  5. Sets new cookies (accessToken, refreshToken)
  6. Returns user data
Client --> auth-service (validate refresh token)
<-- New JWT tokens (cookies + body)

Logout

Steps

  1. Client calls POST /api/v1/iam/logout on auth-service (with JWT)
  2. auth-service invalidates the refresh token in the token store
  3. Deletes the Redis session (if ZITADEL)
  4. Clears accessToken and refreshToken cookies
  5. Returns success

JWT Token Contents

The access token payload includes:

FieldDescription
subUser ID (UUID)
emailUser email
organizationIdOrganization UUID
rolesArray of role IDs
iatIssued at timestamp
expExpiration timestamp

Signed with RS256 using a private key. Verified by other services using the corresponding public key.