How to fix INVALID_ARGUMENT: Invalid claim in auth token in Firebase

FirebaseINTERMEDIATEHIGHUpdated Dec 22, 2025· 146 views

This error occurs when a Firebase ID token contains invalid claim values, typically a mismatched "aud" (audience) or "iss" (issuer) claim. Fix it by ensuring tokens come from the same Firebase project and that your service account configuration matches your client configuration.

Quick fix

Fixes INVALID_ARGUMENT: Invalid claim in auth token

import { initializeApp, cert } from 'firebase-admin/app';

// This service account MUST be from the correct Firebase project
const serviceAccount = require('./path/to/serviceAccountKey.json');

// Verify the project_id in the service account
console.log('Service Account Project ID:', serviceAccount.project_id);

initializeApp({
  credential: cert(serviceAccount),
  projectId: serviceAccount.project_id  // Explicit project ID
});
  1. Verify your Firebase project ID matches everywhere
  2. Verify the token comes from the correct Firebase project
  3. Clear cached tokens and re-authenticate
  4. Ensure Admin SDK uses the correct service account
firebase — error
import { initializeApp, cert } from 'firebase-admin/app';
// This service account MUST be from the correct Firebase project
const serviceAccount = require('./path/to/serviceAccountKey.json');
// Verify the project_id in the service account
console.log('Service Account Project ID:', serviceAccount.project_id);
initializeApp({
credential: cert(serviceAccount),
projectId: serviceAccount.project_id // Explicit project ID
});
INVALID_ARGUMENT: Invalid claim in auth token

What this error means

This error is thrown by Firebase Admin SDK when verifying an ID token that contains invalid or mismatched claims. Specifically, it most commonly occurs when the "aud" (audience) claim in the token doesn't match the expected Firebase project ID, or the "iss" (issuer) claim doesn't match the expected token issuer. Firebase ID tokens are JWT tokens that contain standard OpenID Connect (OIDC) claims including: - `aud`: The audience (your Firebase project ID) - `iss`: The issuer (Firebase's secure token server) - `sub`: The subject (the user ID) - `iat`: Issued at time - `exp`: Expiration time When any of these claims are invalid, malformed, or don't match expectations, Firebase rejects the token.

Typical symptoms

  • Error "INVALID_ARGUMENT: Invalid claim in auth token" when calling verifyIdToken()
  • Cloud Functions rejecting authentication tokens from your app
  • Admin SDK failing to verify tokens issued by your Firebase project
  • Authentication working in one environment but not another (e.g., production vs staging)
  • Token verification working for some users but not others
  • Cached tokens from a previous project causing failures after migration

Common causes

  1. Token comes from a different Firebase project than the one your Admin SDK is configured for
  2. Using tokens from multiple Firebase projects in the same application
  3. Service account configuration in Admin SDK doesn't match the Firebase project that issued the token
  4. Changing your Firebase project configuration without clearing cached tokens
  5. Token issuer URL is undefined due to missing or incorrect project ID configuration
  6. Using tokens generated in the Firebase Emulator with production Admin SDK credentials
  7. Mismatched configuration between web app and backend server
  8. Stale tokens cached in mobile app keychain after switching to a different Firebase project
  9. Attempting to verify tokens across different Firebase tenants without proper configuration

How to fix "INVALID_ARGUMENT: Invalid claim in auth token"

1Verify your Firebase project ID matches everywhere

Ensure your Admin SDK, client SDK, and service account are all configured for the same Firebase project.

Check your Admin SDK initialization:

typescript
import { initializeApp, cert } from 'firebase-admin/app';

// This service account MUST be from the correct Firebase project
const serviceAccount = require('./path/to/serviceAccountKey.json');

// Verify the project_id in the service account
console.log('Service Account Project ID:', serviceAccount.project_id);

initializeApp({
  credential: cert(serviceAccount),
  projectId: serviceAccount.project_id  // Explicit project ID
});

Check your client SDK configuration (web):

typescript
import { initializeApp } from 'firebase/app';

const firebaseConfig = {
  apiKey: "YOUR_API_KEY",
  authDomain: "YOUR_PROJECT.firebaseapp.com",
  projectId: "YOUR_PROJECT_ID",  // Must match Admin SDK
  storageBucket: "YOUR_PROJECT.appspot.com",
  messagingSenderId: "YOUR_SENDER_ID",
  appId: "YOUR_APP_ID"
};

const app = initializeApp(firebaseConfig);

// Verify the project ID matches
console.log('Client Project ID:', firebaseConfig.projectId);

Confirm they match:

bash
# Service account project_id
grep project_id serviceAccountKey.json

# Client config projectId
grep projectId src/firebase-config.ts

Both should show the same project ID (e.g., "my-app-12345").

2Verify the token comes from the correct Firebase project

Decode and inspect the token to see which project issued it.

Inspect token claims:

typescript
import { getAuth } from 'firebase-admin/auth';
import jwt_decode from 'jwt-decode';

// Get token from client
const idToken = await user.getIdToken();

// Decode token (don't verify yet)
const decoded = jwt_decode<any>(idToken);

console.log('Token Claims:');
console.log('  aud (audience/project):', decoded.aud);
console.log('  iss (issuer):', decoded.iss);
console.log('  sub (user):', decoded.sub);
console.log('  iat (issued at):', new Date(decoded.iat * 1000));
console.log('  exp (expires):', new Date(decoded.exp * 1000));

Expected values for project "my-app-12345":

typescript
{
  aud: "my-app-12345",  // Audience should be your project ID
  iss: "https://securetoken.google.com/my-app-12345",  // Issuer should be Google's token server for your project
  sub: "user_uid_here",
  iat: 1672531200,
  exp: 1672534800
}

If the `aud` or `iss` don't match your project, the token is from the wrong Firebase project.

3Clear cached tokens and re-authenticate

If the token comes from a different project, clear cached credentials and sign in again.

Web/JavaScript:

typescript
import { getAuth, signOut } from 'firebase/auth';

const auth = getAuth();

// Sign out to clear cached tokens
await signOut(auth);

// User must sign in again with correct project
console.log('User signed out. They must sign in again.');

iOS (Swift):

swift
import FirebaseAuth

// Check current app configuration
if let app = FirebaseApp.app() {
  print("Current Firebase App Name:", app.name)
}

// Clear keychain by signing out
do {
  try Auth.auth().signOut()
  print("User signed out and token cleared")
} catch let signOutError as NSError {
  print("Error signing out:", signOutError.code)
}

Android (Kotlin):

kotlin
import com.google.firebase.auth.FirebaseAuth

val auth = FirebaseAuth.getInstance()
auth.signOut()

// Clear credential cache
FirebaseAuth.getInstance().currentUser = null

After clearing tokens, users will be asked to authenticate again, and new tokens from the correct project will be generated.

4Ensure Admin SDK uses the correct service account

The service account you use for Admin SDK initialization must be from the same Firebase project.

Verify service account source:

bash
# Download service account from Firebase Console
# Firebase Console > Project Settings > Service Accounts > Generate New Private Key

# Check the project_id in the downloaded file
cat serviceAccountKey.json | jq '.project_id'

# Should output: "my-app-12345"

Proper Admin SDK initialization:

typescript
import { initializeApp, cert } from 'firebase-admin/app';
import { getAuth } from 'firebase-admin/auth';

// Load the correct service account
const serviceAccountKey = JSON.parse(
  process.env.FIREBASE_SERVICE_ACCOUNT_KEY || '{}'
);

// Initialize with explicit project ID
const app = initializeApp({
  credential: cert(serviceAccountKey),
  projectId: serviceAccountKey.project_id,
  databaseURL: `https://${serviceAccountKey.project_id}.firebaseio.com`
});

const auth = getAuth(app);

export { auth };

Never use the wrong service account:

typescript
// ❌ WRONG - Using service account from different project
const wrongServiceAccount = require('./staging-serviceAccountKey.json');
initializeApp({
  credential: cert(wrongServiceAccount)  // This is from staging, not production
});

// ✅ CORRECT - Using service account from same project
const correctServiceAccount = require('./production-serviceAccountKey.json');
initializeApp({
  credential: cert(correctServiceAccount)  // This is from production
});
5Check for environment-specific mismatches

If you have multiple Firebase projects (staging, production), ensure tokens and credentials match the same environment.

Typical multi-environment setup:

typescript
// Environment-specific configuration
const firebaseConfig = process.env.NODE_ENV === 'production'
  ? {
      projectId: 'my-app-production',
      databaseURL: 'https://my-app-production.firebaseio.com'
    }
  : {
      projectId: 'my-app-staging',
      databaseURL: 'https://my-app-staging.firebaseio.com'
    };

// Load matching service account
const serviceAccountPath = process.env.NODE_ENV === 'production'
  ? './serviceAccounts/production.json'
  : './serviceAccounts/staging.json';

const serviceAccount = require(serviceAccountPath);

initializeApp({
  credential: cert(serviceAccount),
  projectId: firebaseConfig.projectId
});

Client-side configuration should also match:

typescript
// src/firebase-config.ts
const firebaseConfig = process.env.REACT_APP_FIREBASE_PROJECT_ID === 'my-app-production'
  ? {
      apiKey: process.env.REACT_APP_FIREBASE_API_KEY_PROD,
      authDomain: "my-app-production.firebaseapp.com",
      projectId: "my-app-production",
      storageBucket: "my-app-production.appspot.com"
    }
  : {
      apiKey: process.env.REACT_APP_FIREBASE_API_KEY_STAGING,
      authDomain: "my-app-staging.firebaseapp.com",
      projectId: "my-app-staging",
      storageBucket: "my-app-staging.appspot.com"
    };

export default firebaseConfig;

Never mix service accounts and client configs from different projects.

6Verify token before calling Admin SDK

Add error handling to diagnose claim mismatches and provide clearer error messages.

Implement token validation:

typescript
import { getAuth } from 'firebase-admin/auth';
import jwt_decode from 'jwt-decode';

async function verifyAndDecodedToken(idToken: string) {
  try {
    // Decode without verification first to inspect claims
    const unverified = jwt_decode<any>(idToken);

    console.log('Token Claims:');
    console.log('  Project ID (aud):', unverified.aud);
    console.log('  Issuer (iss):', unverified.iss);
    console.log('  Expected Project:', process.env.FIREBASE_PROJECT_ID);

    // Check if project matches
    if (unverified.aud !== process.env.FIREBASE_PROJECT_ID) {
      throw new Error(
        `Token from wrong project. Expected "${process.env.FIREBASE_PROJECT_ID}" but got "${unverified.aud}"`
      );
    }

    // Now verify with Admin SDK
    const decodedToken = await getAuth().verifyIdToken(idToken);
    return decodedToken;

  } catch (error: any) {
    if (error.code === 'auth/invalid-argument') {
      console.error('Invalid token claim - project mismatch');
      console.error('Error details:', error.message);
      // Log for debugging
      throw new Error('Authentication failed: token from different Firebase project');
    }
    throw error;
  }
}

// Usage
const uid = await verifyAndDecodedToken(clientToken)
  .catch(error => {
    console.error('Verification failed:', error.message);
    return null;
  });

Better error messages for users:

typescript
async function authenticateRequest(req: Request) {
  const idToken = extractTokenFromHeader(req);

  try {
    const decodedToken = await getAuth().verifyIdToken(idToken);
    return { success: true, uid: decodedToken.uid };
  } catch (error: any) {
    if (error.code === 'auth/invalid-argument') {
      return {
        success: false,
        error: 'Your authentication token is not valid for this service. Please sign in again.',
        debug: error.message
      };
    }
    throw error;
  }
}

Advanced notes

Firebase Project Migration:

If you're migrating from one Firebase project to another, this error is common during the transition. Best practice:

1. Keep both projects running in parallel
2. On the client, gradually redirect users to authenticate with the new project
3. Invalidate old tokens from the old project
4. Migrate user data from old to new project
5. Once all users are on the new project, decommission the old project

typescript
async function migrateUserToken(oldToken: string) {
  try {
    // Try to verify with old project
    const oldAuth = getAuth(oldFirebaseApp);
    const oldDecoded = await oldAuth.verifyIdToken(oldToken);

    // Get fresh token from new project
    const user = await getAuth(newFirebaseApp).getUser(oldDecoded.uid);
    const newToken = await user.getIdToken();

    return newToken;
  } catch (error) {
    // If verification fails, user must re-authenticate
    console.error('Token migration failed, user must sign in again');
    return null;
  }
}

Testing with Firebase Emulator:

When using Firebase Emulator Suite locally, the issuer claim is different. Configure your Admin SDK to use the emulator:

typescript
import { initializeApp, cert } from 'firebase-admin/app';
import { getAuth } from 'firebase-admin/auth';

if (process.env.NODE_ENV === 'development') {
  // Point to emulator
  process.env.FIREBASE_AUTH_EMULATOR_HOST = 'localhost:9099';
}

const app = initializeApp({
  projectId: 'demo-project'
});

Cross-tenant authentication:

Firebase Auth supports multi-tenancy. If using tenants, ensure tenant configuration is correct:

typescript
import { getTenant } from 'firebase-admin/auth';

// Verify token for specific tenant
const tenantAuth = getTenant('tenant_id');
const decodedToken = await tenantAuth.verifyIdToken(idToken);

Common claim values:

Understanding what valid claims look like helps diagnose issues:

- aud: Always a Firebase project ID (e.g., "my-app-12345")
- iss: Always "https://securetoken.google.com/{project_id}"
- auth_time: Seconds since epoch when user authenticated
- user_id: Same as sub for Firebase Auth
- firebase.identities: Which sign-in providers were used
- firebase.sign_in_provider: The primary sign-in method

Frequently asked questions

What does "INVALID_ARGUMENT: Invalid claim in auth token" mean?
This error is thrown by Firebase Admin SDK when verifying an ID token that contains invalid or mismatched claims. Specifically, it most commonly occurs when the "aud" (audience) claim in the token doesn't match the expected Firebase project ID, or the "iss" (issuer) claim doesn't match the expected token issuer. Firebase ID tokens are JWT tokens that contain standard OpenID Connect (OIDC) claims including: - aud: The audience (your Firebase project ID) - iss: The issuer (Firebase's secure token server) - sub: The subject (the user ID) - iat: Issued at time - exp: Expiration time When any of these claims are invalid, malformed, or don't match expectations, Firebase rejects the token.
How do I fix "INVALID_ARGUMENT: Invalid claim in auth token"?
This error occurs when a Firebase ID token contains invalid claim values, typically a mismatched "aud" (audience) or "iss" (issuer) claim. Fix it by ensuring tokens come from the same Firebase project and that your service account configuration matches your client configuration.
What causes "INVALID_ARGUMENT: Invalid claim in auth token"?
Token comes from a different Firebase project than the one your Admin SDK is configured for Using tokens from multiple Firebase projects in the same application Service account configuration in Admin SDK doesn't match the Firebase project that issued the token
Is the "INVALID_ARGUMENT: Invalid claim in auth token" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading