How the Omi Backend Handles Authentication with Firebase and API Keys

Omi’s backend authenticates users by initializing the Firebase Admin SDK at startup, exchanging OAuth codes or email credentials for Firebase ID tokens via REST endpoints protected by API keys, and verifying every token with firebase_admin.auth.verify_id_token before serving protected resources.

The Omi open-source AI wearable platform uses Firebase Authentication as its identity backbone for both the core mobile app and third-party integrations. The backend implements a hybrid authentication model that combines server-side Firebase Admin SDK operations with client-facing REST API calls secured by Firebase API keys. This architecture supports multiple login methods—including Google, Apple, and email/password—while ensuring that all protected routes validate JWTs against Firebase’s certificate chain.

Firebase Admin SDK Initialization

The authentication stack begins with a singleton Firebase Admin instance initialized at application startup. In backend/main.py, the system checks for a SERVICE_ACCOUNT_JSON environment variable containing service account credentials.

If present, the backend loads the JSON and creates a certificate-based credential:


# backend/main.py

if os.environ.get('SERVICE_ACCOUNT_JSON'):
    service_account_info = json.loads(os.environ["SERVICE_ACCOUNT_JSON"])
    credentials = firebase_admin.credentials.Certificate(service_account_info)
    firebase_admin.initialize_app(credentials)
else:
    firebase_admin.initialize_app()

This singleton instance handles server-side operations like auth.create_user and auth.verify_id_token throughout the application lifecycle. When SERVICE_ACCOUNT_JSON is omitted, the SDK falls back to Google’s default credentials mechanism, useful for local development or GCP environments.

OAuth Authentication Flow for Google and Apple

The Omi backend implements a complete OAuth 2.0 server-side flow for social providers, culminating in Firebase token generation via the signInWithIdp REST endpoint.

Starting the Authorization Flow

When a client requests authentication via GET /v1/auth/authorize, the backend generates a unique session ID and stores the requested provider (google or apple) in Redis using set_auth_session. The user is then redirected to the provider’s OAuth URL with the session ID embedded in the state parameter.

This logic resides in auth_authorize within backend/routers/auth.py (lines 31-58).

Handling Provider Callbacks

After the user authenticates with the provider, the backend handles callbacks at /v1/auth/callback/google or /v1/auth/callback/apple. The system retrieves the original session using the state value, then exchanges the authorization code for provider tokens:

  • Google: _exchange_google_code_for_oauth_credentials exchanges the code for an ID token and access token using the GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET environment variables (lines 62-104).
  • Apple: _exchange_apple_code_for_oauth_credentials performs the same operation using Apple’s JWT-based client secret generation with APPLE_CLIENT_ID, APPLE_TEAM_ID, APPLE_KEY_ID, and APPLE_PRIVATE_KEY (lines 107-165).

The raw OAuth credentials are temporarily stored in Redis as an auth code via set_auth_code for the final token exchange step.

Exchanging Tokens with Firebase

The client completes authentication by posting to /v1/auth/token with the temporary auth code. If use_custom_token=true, the backend calls _generate_custom_token (lines 74-101), which invokes Firebase’s signInWithIdp REST endpoint:

sign_in_url = f"https://identitytoolkit.googleapis.com/v1/accounts:signInWithIdp?key={firebase_api_key}"
post_body = f"id_token={id_token}&providerId=google.com"

# ... includes access_token if present

The FIREBASE_API_KEY environment variable authorizes this REST call. Firebase returns a JWT idToken that the client can use for subsequent authenticated requests to Omi’s backend.

Email and Password Authentication

For traditional credential-based access, Omi provides /v1/signup and /v1/signin endpoints in backend/routers/custom_auth.py.

Sign-up calls firebase_admin.auth.create_user directly to provision a Firebase user with the provided email and password.

Sign-in uses the Firebase Auth REST API’s signInWithPassword endpoint:


# Endpoint construction

sign_in_url = f"https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key={api_key}"

This call uses the CUSTOM_AUTH_FIREBASE_API_KEY environment variable (which may differ from the standard FIREBASE_API_KEY). After receiving the idToken from Firebase, the backend immediately validates it using firebase_admin.auth.verify_id_token before returning the UID and token details to the client (lines 20-60).

Third-Party App Authentication via OAuth

Omi supports third-party app integration through a dedicated OAuth flow defined in backend/routers/oauth.py.

The authorization page (/v1/oauth/authorize) renders an HTML page embedding the Firebase configuration (API key, auth domain, and project ID) required by the client-side JavaScript SDK. After the user authenticates with Firebase on the client side, the app posts the resulting ID token to /v1/oauth/token.

The backend verifies this token using firebase_admin.auth.verify_id_token, optionally enables the requested app for the user, and returns a redirect URL to the third-party application (lines 12-78).

Token Verification and Security Model

All authentication paths converge on firebase_admin.auth.verify_id_token. Whether the token originates from Google OAuth, Apple OAuth, or email/password sign-in, protected routes extract the Bearer token from the Authorization header and validate it against Firebase’s public certificates.

The verification process guarantees three security properties:

  • Authenticity: The token was signed by Firebase’s private keys.
  • Integrity: The token payload has not been tampered with.
  • Validity: The token has not expired and matches the Omi Firebase project.

Upon successful verification, the backend extracts the Firebase UID (uid) and uses it as the primary key for user-specific data in Redis, Firestore, and other data stores.

Summary

  • Firebase Admin SDK initializes as a singleton in backend/main.py using either service account JSON or default credentials.
  • OAuth flows for Google and Apple exchange provider codes for Firebase ID tokens via the signInWithIdp REST endpoint, protected by the FIREBASE_API_KEY.
  • Email/password auth uses the signInWithPassword REST endpoint with a separate CUSTOM_AUTH_FIREBASE_API_KEY, followed by server-side token verification.
  • Third-party apps authenticate through a browser-based OAuth flow that validates client-side Firebase JWTs at the /v1/oauth/token endpoint.
  • Universal verification via firebase_admin.auth.verify_id_token ensures only valid Firebase UIDs access protected resources.

Frequently Asked Questions

How does Omi verify that a Firebase ID token is legitimate?

The backend calls firebase_admin.auth.verify_id_token on every protected request. This function checks the JWT signature against Firebase’s public certificates, validates the issuer and audience claims, and ensures the token has not expired. Only tokens issued by the specific Omi Firebase project are accepted.

What is the difference between FIREBASE_API_KEY and CUSTOM_AUTH_FIREBASE_API_KEY?

FIREBASE_API_KEY is the standard Web API key used for OAuth provider sign-ins via the signInWithIdp endpoint. CUSTOM_AUTH_FIREBASE_API_KEY is an optional separate key used specifically for the email/password signInWithPassword endpoint in backend/routers/custom_auth.py. This separation allows different rate limits or security policies for custom authentication versus social login.

Where are temporary OAuth sessions stored during the authentication flow?

Temporary sessions and authorization codes are stored in Redis using functions defined in backend/database/redis_db.py. The set_auth_session function stores the provider choice associated with a session ID, while set_auth_code temporarily caches OAuth credentials before they are exchanged for Firebase tokens. These entries have short TTL values to prevent replay attacks.

Can the Omi backend work without a service account JSON file?

Yes. If the SERVICE_ACCOUNT_JSON environment variable is not set, the backend calls firebase_admin.initialize_app() without arguments in backend/main.py. This triggers the Firebase Admin SDK’s default credentials discovery, which works automatically when running on Google Cloud Platform or when the GOOGLE_APPLICATION_CREDENTIALS environment variable points to a valid service account file.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →