Skip to main content
When Quick Auth is called:
  • The user authenticates with a signature
  • The SDK returns a JWT that your backend verifies to confirm the user’s identity
  • The backend returns trusted data that can be used for sensitive actions
This differs from the Context API, which provides instant access to user information without authentication but cannot be trusted for sensitive operations.

Implementation

Step 1: Frontend Authentication

This code authenticates the user with Quick Auth, stores the JWT in memory, and uses it to verify the user’s identity with your backend.
App.tsx
import { useState } from "react";
import { sdk } from "@farcaster/miniapp-sdk";

export function App() {
 const [token, setToken] = useState<string | null>(null);
 const [userData, setUserData] = useState<{ fid: number} | null>(null);

 async function signIn() {
   try {
     const { token } = await sdk.quickAuth.getToken();
     setToken(token);
     
     // Use the token to authenticate the user and fetch authenticated user data
     const response = await sdk.quickAuth.fetch(`${BACKEND_ORIGIN}/auth`, {
       headers: { "Authorization": `Bearer ${token}` }
     });
     
     const data = await response.json();
     setUserData(data);
   } catch (error) {
     console.error("Authentication failed:", error);
   }
 }

 function signOut() {
   setToken(null);
   setUserData(null);
 }

 if (!token) {
   return <button onClick={signIn}>Sign In</button>;
 }

 return (
   <div>
     <p>Authenticated as FID: {userData?.fid}</p>
     <button onClick={signOut}>Sign Out</button>
   </div>
 );
}

Step 2: Backend Verification

Install the Quick Auth client:
npm install @farcaster/quick-auth
Quick Auth Client is the SDK that initiates the authentication flow in your application. Quick Auth Server is Farcaster’s service that handles signature verification and issues JWTs. When a user authenticates, the Quick Auth Server verifies their signature and issues a JWT. Your backend verifies this JWT using the @farcaster/quick-auth package.
route.tsx
// app/api/auth/route.ts
import { createClient, Errors } from '@farcaster/quick-auth';
import { NextRequest, NextResponse } from 'next/server';

const domain = 'your-domain.com'; // Must match your mini app's deployment domain
const client = createClient();

// This endpoint returns the authenticated user's FID 
export async function GET(request: NextRequest) {
  const authorization = request.headers.get('Authorization');
  if (!authorization?.startsWith('Bearer ')) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  const token = authorization.split(' ')[1];

  try {
    const payload = await client.verifyJwt({ token, domain });
    
    return NextResponse.json({
      fid: payload.sub,
    });
  } catch (e) {
    if (e instanceof Errors.InvalidTokenError) {
      return NextResponse.json({ error: 'Invalid token' }, { status: 401 });
    }
    throw e;
  }
}

Schema

JWT Payload

{
  "iat": 1747764819,
  "iss": "https://auth.farcaster.xyz",
  "exp": 1747768419,
  "sub": 6841,
  "aud": "your-domain.com" 
}
Payload fields:

iat
number
Issued at timestamp
iss
string
Quick Auth Server that issued the JWT
exp
number
Expiration timestamp (1 hour from issuance)
sub
number
User’s Farcaster ID (FID)
aud
string
Your mini app’s domain
I