CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-next-auth

Authentication library for Next.js applications with support for OAuth, email, and credentials authentication

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

jwt-management.mddocs/

JWT Token Management

JWT utilities for encoding, decoding, and extracting tokens from requests. Essential for API authentication, custom session handling, and implementing stateless authentication patterns in Next.js applications.

Capabilities

JWT Encoding

Creates encrypted JWT tokens using NextAuth.js encryption standards with "A256GCM" encryption by default.

/**
 * Issues a JWT token encrypted using "A256GCM" by default
 * @param params - Token encoding parameters
 * @returns Promise resolving to encrypted JWT string
 */
function encode(params: JWTEncodeParams): Promise<string>;

interface JWTEncodeParams {
  /** JWT payload to encode (default: empty object) */
  token?: JWT;
  /** Secret used for encryption */
  secret: string;
  /** Maximum age in seconds (default: 2592000 - 30 days) */
  maxAge?: number;
  /** Salt for key derivation (empty string means session token) */
  salt?: string;
}

Usage Examples:

import { encode } from "next-auth/jwt";

// Basic JWT encoding
const jwt = await encode({
  token: { userId: "123", role: "user" },
  secret: process.env.NEXTAUTH_SECRET!,
});

// Custom expiration
const shortLivedJwt = await encode({
  token: { action: "email-verification" },
  secret: process.env.NEXTAUTH_SECRET!,
  maxAge: 3600, // 1 hour
});

// Custom salt for different token types
const apiToken = await encode({
  token: { userId: "123", scopes: ["read", "write"] },
  secret: process.env.NEXTAUTH_SECRET!,
  salt: "api-token",
});

JWT Decoding

Decodes and verifies NextAuth.js issued JWT tokens with automatic expiration checking.

/**
 * Decodes a NextAuth.js issued JWT token
 * @param params - Token decoding parameters
 * @returns Promise resolving to JWT payload or null if invalid/expired
 */
function decode(params: JWTDecodeParams): Promise<JWT | null>;

interface JWTDecodeParams {
  /** JWT token string to decode */
  token?: string;
  /** Secret used for decryption */
  secret: string;
  /** Salt for key derivation (must match encoding salt) */
  salt?: string;
}

Usage Examples:

import { decode } from "next-auth/jwt";

// Basic JWT decoding
const payload = await decode({
  token: "eyJhbGciOiJkaXIi...",
  secret: process.env.NEXTAUTH_SECRET!,
});

if (payload) {
  console.log("User ID:", payload.sub);
  console.log("Token expires:", new Date(payload.exp! * 1000));
}

// Decode API token with custom salt
const apiPayload = await decode({
  token: apiTokenString,
  secret: process.env.NEXTAUTH_SECRET!,
  salt: "api-token",
});

Token Extraction

Extracts JWT tokens from NextAuth.js requests, checking both cookies and Authorization headers.

/**
 * Extracts JWT from NextAuth.js request (cookies or Authorization header)
 * @param params - Token extraction parameters
 * @returns Promise resolving to JWT payload, raw token string, or null
 */
function getToken<R extends boolean = false>(
  params: GetTokenParams<R>
): Promise<R extends true ? string : JWT | null>;

interface GetTokenParams<R extends boolean = false> {
  /** Request containing the JWT */
  req: GetServerSidePropsContext["req"] | NextRequest | NextApiRequest;
  /** Use secure prefix for cookie name (auto-detected from NEXTAUTH_URL) */
  secureCookie?: boolean;
  /** Custom cookie name to look for JWT */
  cookieName?: string;
  /** Return raw JWT string instead of decoded payload */
  raw?: R;
  /** Secret for decryption (defaults to NEXTAUTH_SECRET) */
  secret?: string;
  /** Custom decode function */
  decode?: JWTOptions["decode"];
  /** Custom logger instance */
  logger?: LoggerInstance | Console;
}

Usage Examples:

import { getToken } from "next-auth/jwt";

// API Route - get decoded token
export default async function handler(req, res) {
  const token = await getToken({ req });
  
  if (!token) {
    return res.status(401).json({ error: "No valid token" });
  }
  
  console.log("User ID:", token.sub);
  console.log("User email:", token.email);
  
  res.json({ message: `Hello ${token.name}` });
}

// Get raw JWT string
export default async function handler(req, res) {
  const rawToken = await getToken({ req, raw: true });
  
  if (rawToken) {
    // Forward token to external API
    const response = await fetch("https://api.example.com/data", {
      headers: {
        Authorization: `Bearer ${rawToken}`,
      },
    });
  }
}

// Middleware - check token
import { NextRequest } from "next/server";

export async function middleware(request: NextRequest) {
  const token = await getToken({
    req: request,
    secret: process.env.NEXTAUTH_SECRET,
  });
  
  if (!token) {
    return Response.redirect(new URL("/login", request.url));
  }
  
  // Check user role
  if (request.nextUrl.pathname.startsWith("/admin") && token.role !== "admin") {
    return Response.redirect(new URL("/unauthorized", request.url));
  }
}

// Server Component - extract token
import { headers } from "next/headers";

export default async function ServerComponent() {
  const token = await getToken({
    req: {
      headers: Object.fromEntries(headers() as Headers),
      cookies: {}, // Will be populated by getToken
    } as any,
    secret: process.env.NEXTAUTH_SECRET,
  });
  
  return <div>User: {token?.name || "Anonymous"}</div>;
}

JWT Options Configuration

Configuration options for customizing JWT behavior in NextAuth.js.

/**
 * JWT configuration options for NextAuth.js
 */
interface JWTOptions {
  /** Secret used for JWT signing and encryption */
  secret: string;
  /** Maximum JWT age in seconds */
  maxAge: number;
  /** Custom JWT encoding function */
  encode?: (params: JWTEncodeParams) => Awaitable<string>;
  /** Custom JWT decoding function */
  decode?: (params: JWTDecodeParams) => Awaitable<JWT | null>;
}

Usage Example:

// Custom JWT configuration in NextAuth
export default NextAuth({
  providers: [...],
  jwt: {
    secret: process.env.JWT_SECRET,
    maxAge: 24 * 60 * 60, // 24 hours
    encode: async ({ secret, token, maxAge }) => {
      // Custom encoding logic
      return customEncode(token, secret, maxAge);
    },
    decode: async ({ secret, token }) => {
      // Custom decoding logic
      return customDecode(token, secret);
    },
  },
});

JWT Token Structure

Standard JWT payload structure used by NextAuth.js with extensible properties.

/**
 * JWT token payload structure
 */
interface JWT extends Record<string, unknown>, DefaultJWT {
  /** User identifier (subject) */
  sub?: string;
  /** User name */
  name?: string | null;
  /** User email address */
  email?: string | null;
  /** User profile picture URL */
  picture?: string | null;
  /** Token issued at timestamp (seconds since epoch) */
  iat?: number;
  /** Token expiration timestamp (seconds since epoch) */
  exp?: number;
  /** JWT ID (unique identifier) */
  jti?: string;
  /** Additional custom properties can be added via callbacks */
  [key: string]: unknown;
}

interface DefaultJWT extends Record<string, unknown> {
  name?: string | null;
  email?: string | null;
  picture?: string | null;
  sub?: string;
}

JWT Callback Integration

JWT callback for customizing token contents and adding custom claims.

/**
 * JWT callback for customizing token contents
 */
interface JWTCallback {
  jwt: (params: {
    /** Current JWT token */
    token: JWT;
    /** User object (available on sign-in) */
    user: User | AdapterUser;
    /** Account object (available on sign-in) */
    account: Account | null;
    /** OAuth profile (available on sign-in) */  
    profile?: Profile;
    /** Trigger that caused JWT callback */
    trigger?: "signIn" | "signUp" | "update";
    /** Whether this is a new user */
    isNewUser?: boolean;
    /** Session data when trigger is "update" */
    session?: any;
  }) => Awaitable<JWT>;
}

Usage Examples:

// Add custom claims to JWT
export default NextAuth({
  providers: [...],
  callbacks: {
    async jwt({ token, user, account, profile, trigger }) {
      // Add user role on sign-in
      if (account && user) {
        token.role = user.role;
        token.provider = account.provider;
      }
      
      // Add custom data on token update
      if (trigger === "update" && user) {
        token.lastUpdated = Date.now();
      }
      
      return token;
    },
  },
});

// Use JWT data in API routes
export default async function handler(req, res) {
  const token = await getToken({ req });
  
  if (!token) {
    return res.status(401).json({ error: "Unauthorized" });
  }
  
  // Access custom claims
  if (token.role !== "admin") {
    return res.status(403).json({ error: "Insufficient permissions" });
  }
  
  res.json({ 
    message: "Admin access granted",
    provider: token.provider,
    lastUpdated: token.lastUpdated,
  });
}

Custom Token Generation

Advanced patterns for creating custom tokens for specific use cases.

/**
 * Custom token generation utilities
 */
interface CustomTokenGeneration {
  /** Generate API access token */
  generateApiToken: (userId: string, scopes: string[]) => Promise<string>;
  /** Generate email verification token */
  generateVerificationToken: (email: string) => Promise<string>;
  /** Generate password reset token */
  generateResetToken: (userId: string) => Promise<string>;
}

Usage Examples:

// Generate custom API token
export async function generateApiToken(userId: string, scopes: string[]) {
  return await encode({
    token: {
      sub: userId,
      type: "api-token",
      scopes,
      iat: Math.floor(Date.now() / 1000),
    },
    secret: process.env.NEXTAUTH_SECRET!,
    salt: "api-token",
    maxAge: 24 * 60 * 60, // 24 hours
  });
}

// Generate email verification token
export async function generateEmailVerificationToken(email: string) {
  return await encode({
    token: {
      email,
      type: "email-verification",
      iat: Math.floor(Date.now() / 1000),
    },
    secret: process.env.NEXTAUTH_SECRET!,
    salt: "email-verification",
    maxAge: 15 * 60, // 15 minutes
  });
}

// Verify custom token
export async function verifyCustomToken(token: string, salt: string) {
  const payload = await decode({
    token,
    secret: process.env.NEXTAUTH_SECRET!,
    salt,
  });
  
  if (!payload) {
    throw new Error("Invalid or expired token");
  }
  
  return payload;
}

Token Security Best Practices

/**
 * Token security utilities and patterns
 */
interface TokenSecurity {
  /** Validate token audience and issuer */
  validateTokenClaims: (token: JWT, requiredClaims: Partial<JWT>) => boolean;
  /** Check token expiration with tolerance */
  isTokenExpired: (token: JWT, toleranceSeconds?: number) => boolean;
  /** Rotate token if near expiration */
  rotateTokenIfNeeded: (token: JWT, thresholdSeconds: number) => Promise<string | null>;
}

Usage Examples:

// Token validation utility
function validateTokenClaims(token: JWT, requiredClaims: Partial<JWT>): boolean {
  for (const [key, value] of Object.entries(requiredClaims)) {
    if (token[key] !== value) {
      return false;
    }
  }
  return true;
}

// Check token expiration
function isTokenExpired(token: JWT, toleranceSeconds = 0): boolean {
  if (!token.exp) return true;
  const now = Math.floor(Date.now() / 1000);
  return now > (token.exp + toleranceSeconds);
}

// API route with token validation
export default async function secureHandler(req, res) {
  const token = await getToken({ req });
  
  if (!token) {
    return res.status(401).json({ error: "No token provided" });
  }
  
  // Validate custom claims
  if (!validateTokenClaims(token, { type: "api-token" })) {
    return res.status(403).json({ error: "Invalid token type" });
  }
  
  // Check if token is close to expiration
  if (isTokenExpired(token, -300)) { // 5 minutes tolerance
    return res.status(401).json({ error: "Token expired or expiring soon" });
  }
  
  res.json({ data: "Secure data" });
}

Types

Request Types

interface GetServerSidePropsContext {
  req: IncomingMessage & {
    cookies: Partial<{ [key: string]: string }>;
  };
}

interface NextApiRequest extends IncomingMessage {
  query: Partial<{ [key: string]: string | string[] }>;
  cookies: Partial<{ [key: string]: string }>;
  body: any;
}

interface NextRequest extends Request {
  cookies: {
    get(name: string): { name: string; value: string } | undefined;
    getAll(): Array<{ name: string; value: string }>;
  };
  nextUrl: {
    pathname: string;
    search: string;
    origin: string;
  };
}

Utility Types

type Awaitable<T> = T | PromiseLike<T>;

interface LoggerInstance {
  error: (code: string, metadata?: any) => void;
  warn: (code: string) => void;
  debug: (code: string, metadata?: any) => void;
}

docs

authentication-providers.md

core-authentication.md

database-integration.md

index.md

jwt-management.md

middleware-protection.md

react-integration.md

server-side-sessions.md

tile.json