Skip to main content

Overview

MechZie uses Firebase Phone Authentication for identity verification and issues its own JWT access + refresh token pair for API authorization. The frontend never sends Firebase tokens after the initial exchange.

Auth Flow

1

Send OTP via Firebase

Use the Firebase Auth SDK in your Flutter app to send an OTP to the user’s phone number. The MechZie API is not involved in this step.
2

Verify OTP and get Firebase ID Token

After the user enters the OTP code, verify it and extract the Firebase ID token.
3

Exchange for MechZie tokens

Send the Firebase ID token to the MechZie API to get your JWT pair.
Response (200):
The role field must be customer or mechanic. If the user already exists with a different role, the API returns 403 ROLE_CONFLICT. Users cannot switch roles.
4

Store tokens securely

Store both tokens in secure storage (e.g. flutter_secure_storage). Never store in SharedPreferences or local storage.

Using the Access Token

Include the access token in all authenticated API requests:
For Socket.io connections, pass it in the handshake:

Token Refresh

Access tokens expire after 15 minutes. Refresh tokens are valid for 30 days. When the access token expires, use the refresh token to get a new pair:
Response (200):
Token rotation is enforced. The old refresh token is revoked immediately. You must store the new refresh token from each response. Using a revoked refresh token returns 401 and requires full re-authentication via Firebase.

Logout

Revoke a specific refresh token. The client should discard both tokens.
This only revokes the single refresh token sent. Other devices remain logged in. Suspension (by admin) revokes all refresh tokens for the user.

JWT Access Token Payload

The access token is an HS256 JWT with this payload:

Admin Invite Flow

Admin accounts are invite-only. They cannot be created via verify-otp.
  1. A super_admin creates an invite → POST /api/v1/super-admin/invites with { email, role }
  2. An invite link is sent to the email
  3. The invitee signs up with Firebase (email must match) and calls:
The role is always taken from the invite, never from the request body.

Admin Login

After completing the invite flow, admins log in to the admin panel using Firebase email/password:
Response (200):
No role field in the request body. The role is resolved server-side from the database. The endpoint rejects non-admin accounts with 403.
Requirements for admin login:
  • Firebase email must be verified (email_verified: true in the token)
  • User must exist in the database with role admin or super_admin
  • Account must be active (not suspended)

User Roles

A user registered as customer cannot later authenticate as mechanic (or vice versa). The API returns 403 ROLE_CONFLICT. Each phone number is locked to one role.

Error Responses