next-firebase-auth-edge

repository·main·Indexed 20 days ago

https://github.com/awinogrodzki/next-firebase-auth-edge

Firebase Authentication for Next.js Edge and server runtimes. It uses the Web Crypto API to bypass firebase-admin limitations, ensuring compatibility with App Router, Server Components, and Edge Runtime. Key features include zero bundle size, middleware-based authentication, support for Firebase App Check and the Firebase Authentication Emulator, and JWT validation via jose.

Tokens
45.7K
Snippets
105
Records
134
Agent score
65%

What's inside next-firebase-auth-edge

  1. Available usage patterns in next-firebase-auth-edge

    main

    The library provides specific implementations for various Next.js environments and authentication tasks. Key usage areas include:

    Next.js Integration Patterns

    • Authentication Middleware: Protecting routes at the edge.
    • Server Components: Accessing auth state in the App Router.
    • App Router API Route Handlers: Using auth in route.ts files.
    • Pages Router API Routes: Using auth in api/ directory files.
    • getServerSideProps: Accessing auth state in the Pages Router.
    • Client-Side APIs: Using auth state within React components.

    Authentication Lifecycle & Management

    • Redirect Helper Functions: Managing user flow based on auth state.
    • Refreshing credentials: Updating session tokens.
    • Removing credentials: Logging users out.

    Deployment & Advanced Configuration

    • Google Cloud Run: Specific considerations for Cloud Run environments.
    • Firebase Hosting: Specific considerations for Firebase Hosting.
    • Debug mode: Enabling detailed logging for troubleshooting.
    • Firebase API Key domain restriction: Configuring security for restricted API keys.
    • Advanced usage: For complex implementation requirements.
  2. Key features of next-firebase-auth-edge

    main

    The library is designed for modern Next.js development with the following characteristics:

    • Runtime Compatibility: Works in both Edge and Node.js runtimes.
    • Next.js Support: Supports App Router, Server Components, getServerSideProps, and legacy API Routes.
    • Zero Bundle Size: Optimized for performance.
    • Minimal Setup: Uses middleware to handle authentication, eliminating the need for custom API routes or next.config.js modifications.
    • Security: Uses jose for JWT validation and signs user cookies with rotating keys to prevent cryptanalysis attacks.
  3. Manage authentication state with AuthContext

    main
    The next-firebase-auth-edge library does not provide built-in client-side authentication state or a React Context. Developers are responsible for implementing their own mechanism to manage and distribute user data throughout the application. A common pattern is to use React's createContext and useContext to create a custom AuthContext that holds the user's information.
  4. Store and Access Custom Metadata in Cookies

    main

    Starting from v1.10.0, you can store custom, signed, and verified data within the authentication cookies using the getMetadata option. This is useful for storing user permissions or roles to avoid database lookups on every request.

    1. Define Metadata in Middleware

    Use the getMetadata callback to return an object containing your custom data.

    2. Access Metadata in Server Components

    Retrieve the data using the getTokens function and destructure the metadata property.

    Warning: Keep metadata compact, as cookie size is limited by browsers (typically ~4096 bytes).

    // In proxy.ts (Middleware)
    getMetadata: async (tokens: TokenSet) => {
      const roles = await loadRolesFromDb();
      return { roles };
    }
    
    // In a Server Component
    const { metadata: { roles } } = await getTokens(await cookies(), authConfig);
  5. Use Multiple Cookies to Avoid Size Limits

    main

    By default, all session data is stored in a single cookie. To prevent issues with browser cookie size limits (typically 4096 bytes) when using large custom claims or metadata, enable enableMultipleCookies: true.

    When enabled, the session is split into four distinct cookies:

    • ${cookieName}.id: stores the idToken
    • ${cookieName}.refresh: stores the refreshToken
    • ${cookieName}.custom: stores the customToken
    • ${cookieName}.sig: stores the signature used for validation

    Important: If you are using Firebase Hosting, you must set enableMultipleCookies: false because Firebase Hosting does not support multiple cookies for authentication.

  6. Getting Started with next-firebase-auth-edge

    main

    To integrate Firebase Authentication into a Next.js application using next-firebase-auth-edge, follow these sequential setup steps:

    1. Setup Next.js Middleware: Configure middleware to handle session validation and edge-compatible authentication.
    2. Setup custom AuthContext: Create a React Context to provide authentication state throughout your application.
    3. Setup custom AuthProvider: Implement a provider component to wrap your application and manage the authentication lifecycle.
    4. Setup App Router Layout: Integrate the authentication provider into your Next.js App Router layout.
    5. Usage with Firebase Auth: Implement the client-side login logic using Firebase Authentication.
    6. Sign in with Server Action: Use Next.js Server Actions to handle authentication flows on the server.
  7. Remove credentials in Middleware or API routes

    main

    To explicitly log a user out or clear authentication state within Middleware or API routes, use the removeCookies function from next-firebase-auth-edge/next/cookies. This function attaches expired Set-Cookie headers to the NextResponse object, instructing the browser to delete the specified cookies.

    When using removeCookies, you must provide the cookieName and cookieSerializeOptions to match the configuration of your existing authentication cookies.

    import {NextRequest, NextResponse} from 'next/server';
    import {removeCookies} from 'next-firebase-auth-edge/next/cookies';
    
    //...
    function forceLogout(request: NextRequest) {
      const response = NextResponse.redirect(new URL('/login', request.url));
    
      removeCookies(request.headers, response, {
        cookieName: 'AuthToken',
        cookieSerializeOptions: {
          path: '/',
          httpOnly: true,
          secure: false,
          sameSite: 'lax' as const,
          maxAge: 12 * 60 * 60 * 24
        }
      });
    
      return response;
    }
  8. Next.js Version Compatibility for Middleware

    main

    The implementation of your middleware file depends on your Next.js version:

    Next.js 16+

    • File Name: Rename middleware.ts to proxy.ts.
    • Export: Export an async function proxy(request: NextRequest).
    • Runtime: Runs on the Node.js runtime (not Edge).
    • Cookies/Headers: You must use await cookies() and await headers() as they are strictly asynchronous.

    Next.js 14 or 15

    • File Name: Use middleware.ts.
    • Export: Export an async function middleware(request: NextRequest).
    • Cookies/Headers: In Next.js 14, cookies() and headers() are synchronous; do not use await before them. In Next.js 15, they are async but have a synchronous fallback.
  9. Implement an AuthProvider to share user data

    main

    To share user data between server and client components in Next.js, you can implement a custom AuthProvider component. This component uses a React Context (typically AuthContext) to wrap your application, allowing client components to access the current user state.

    This pattern requires the AuthProvider to be a Client Component ('use client'). You pass the user data (retrieved on the server) as a prop to the provider, which then populates the context for all descendant client components.

    'use client';
    
    import * as React from 'react';
    import {AuthContext, User} from './AuthContext';
    
    export interface AuthProviderProps {
      user: User | null;
      children: React.ReactNode;
    }
    
    export const AuthProvider: React.FunctionComponent<AuthProviderProps> = ({
      user,
      children
    }) => {
      return (
        <AuthContext.Provider
          value={{
            user
          }}
        >
          {children}
        </AuthContext.Provider>
      );
    };
  10. Refresh auth cookies in Server Actions

    main

    To refresh authentication cookies within Next.js Server Actions, use refreshServerCookies from next-firebase-auth-edge/next/cookies.

    Important: When using headers() in a Server Action, you must wrap it in new Headers() to satisfy the function signature.

    'use server';
    
    import {cookies, headers} from 'next/headers';
    import {getTokens} from 'next-firebase-auth-edge';
    import {refreshServerCookies} from 'next-firebase-auth-edge/next/cookies';
    
    export async function performServerAction() {
      const cookieStore = await cookies();
      const tokens = await getTokens(cookieStore, commonOptions);
    
      if (!tokens) {
        throw new Error('Unauthenticated');
      }
    
      // Wrap headers() in new Headers() for Server Actions compatibility
      await refreshServerCookies(
        cookieStore,
        new Headers(await headers()),
        commonOptions
      );
    }