Exchange Custom Token for ID Token in Firebase or GCP Identity Platform

Recently I was trying to figure out how to generate an ID Token using the Firebase Admin SDK but it seems like there’s no direct function exposed by the SDK that allows that. Instead, we can use the GCP Identity Platform REST API, which Firebase Auth is also based on, to exchange a custom token for an ID token.

When using the Firebase web SDK on the client side, we can quickly generate an ID token using the getIdToken() method, but to do the same server-side, either we can use the same web SDK in Node (since it is also JS) or call the REST API. If the preference is to not use the same client-side SDK in Node or if you are working with a different language (like Python), then the REST API has to be used. Here’s what the steps would look like:

  1. Generate a custom token in the backend.
  2. Call the REST API and exchange the custom token for an ID Token and its corresponding refresh token.

Here is a sample Node snippet that illustrates the steps above:

const { initializeApp } = require('firebase-admin/app');
const { getAuth } = require('firebase-admin/auth');

initializeApp({ ... });

// 1. Create a custom token
const uid = ...;
const customToken = await getAuth().createCustomToken(uid);

// 2. Call the REST API to exchange the custom token for an ID Token
const resp = await fetch(
    `https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken?key=[YOUR_API_KEY]`,
    // or https://identitytoolkit.googleapis.com/v1/accounts:signInWithCustomToken?key=[YOUR_API_KEY]
    {
        method: 'POST',
        body: JSON.stringify({
            token: customToken,
            returnSecureToken: true,
        }),
        headers: {
            // Set this if your API key has referrer restrictions
            Referer: 'https://yoursite.com',
        },
    },
);

const idTokenResp = await resp.json();
/*
idTokenResp will look something like the following:
{
    kind: 'identitytoolkit#VerifyCustomTokenResponse',
    idToken: '...',
    refreshToken: '...',
    expiresIn: '3600',
    isNewUser: false
}
*/
console.log(idTokenResp);

// Decode ID Token (if needed)
const decodedIDToken = await getAuth().verifyIdToken(idTokenResp.idToken);
console.log(decodedIDToken);

Leave a Reply

Your email address will not be published. Required fields are marked *