Skip to content
Docs
Usage guide
Using Client-Side APIs

Using Client-Side APIs

The starter example uses the inMemoryPersistence (opens in a new tab) strategy, relying entirely on server-side tokens. This avoids consistency issues on the client side.

While this approach is recommended, it can lead to a few challenges:

  1. Stale tokens: In long-running client sessions, server-side tokens may expire, requiring the user to refresh the page to get a valid token. This typically happens if the user reopens a tab after about an hour.
  2. Unauthenticated Firebase Client SDK environment: With inMemoryPersistence, currentUser will often be null when using client-side APIs (opens in a new tab), preventing the use of Firebase’s client-side SDKs.

However, next-firebase-auth-edge includes several features that address these issues:

Enable Refresh Token API Endpoint in Auth Middleware

In long-running client sessions (e.g., when a user reopens a tab after an hour), the server-side token may expire. This can cause problems when validating external API calls or when using the customToken with Firebase's signInWithCustomToken.

To resolve this, you can expose an endpoint via authMiddleware to refresh client-side tokens when the server-side token has expired.

To enable this endpoint, define the refreshTokenPath option in the middleware.

export async function middleware(request: NextRequest) {
  return authMiddleware(request, {
    loginPath: '/api/login',
    logoutPath: '/api/logout',
    refreshTokenPath: '/api/refresh-token'
    // other options...
  });
}
 
export const config = {
  // Make sure to include the path in `matcher`
  matcher: [
    '/api/login',
    '/api/logout',
    '/api/refresh-token',
    '/',
    '/((?!_next|favicon.ico|api|.*\\.).*)'
  ]
};

Calling /api/refresh-token will:

  1. Check if the current token has expired. If it has, it regenerates the token and updates the cookies with a Set-Cookie header containing the fresh token.
  2. Return JSON with a valid idToken. It can also return customToken, if enableCustomToken is set to true in authMiddleware.

getValidIdToken

The getValidIdToken function works in conjunction with the refresh token endpoint to ensure you have the latest valid ID token. This is helpful if you use tokens to authorize external API calls.

It requires serverIdToken, which is the token returned by the getTokens function in server components.

The function is optimized to be fast and safe for repeated calls. The /api/refresh-token endpoint will only be called if the token has expired.

Example usage:

import {getValidIdToken} from 'next-firebase-auth-edge/lib/next/client';
 
export async function fetchSomethingFromExternalApi(serverIdToken: string) {
  const idToken = await getValidIdToken({
    serverIdToken,
    refreshTokenUrl: '/api/refresh-token'
  });
 
  return fetch('https://some-external-api.com/api/example', {
    method: 'GET',
    headers: {
      Authorization: `Bearer ${idToken}`
    }
  });
}

getValidCustomToken

Please note that since v1.8 custom token is disabled by default. In order to enable custom cookies, pass enableCustomToken: true option to authMiddleware.

Custom token introduces significant footprint on authentication cookie and is not required for most use-cases.

If you want to avoid cookie size issues, learn how to split session into multiple cookies

Similar to getValidIdToken, the getValidCustomToken function works with the refresh token endpoint to provide a valid custom token. This is useful when using the custom token with Firebase’s signInWithCustomToken (opens in a new tab) method.

It requires serverCustomToken, which is the customToken returned by the getTokens function in server components.

Like getValidIdToken, this function is designed to be efficient and only calls the /api/refresh-token endpoint if necessary.

Example usage:

export async function signInWithServerCustomToken(serverCustomToken: string) {
  const auth = getAuth(getFirebaseApp());
 
  const customToken = await getValidCustomToken({
    serverCustomToken,
    refreshTokenUrl: '/api/refresh-token'
  });
 
  if (!customToken) {
    throw new Error('Invalid custom token');
  }
 
  return signInWithCustomToken(auth, customToken);
}

Using Firebase Client SDKs

The Firebase Client SDK exposes the signInWithCustomToken (opens in a new tab) method, which allows you to access the current user using a custom token.

You can obtain a custom token by calling the getTokens function in server components.

import {signInWithCustomToken} from 'firebase/auth';
import {getValidCustomToken} from 'next-firebase-auth-edge/lib/next/client';
 
import {doc, getDoc, getFirestore, updateDoc, setDoc} from 'firebase/firestore';
 
export async function doSomethingWithFirestoreClient(
  serverCustomToken: string
) {
  const auth = getAuth(getFirebaseApp());
 
  // See https://next-firebase-auth-edge-docs.vercel.app/docs/usage/client-side-apis#getvalidcustomtoken
  const customToken = await getValidCustomToken({
    serverCustomToken,
    refreshTokenUrl: '/api/refresh-token'
  });
 
  if (!customToken) {
    throw new Error('Invalid custom token');
  }
 
  const {user: firebaseUser} = await signInWithCustomToken(auth, customToken);
 
  // Use client-side firestore instance
  const db = getFirestore(getApp());
}