Next JWT Auth

raw JSON →
1.5.0 verified Sat May 09 auth: no javascript

Next JWT Auth is a lightweight React/Next.js library for integrating custom JWT authentication services hosted separately from your Next.js app. Version 1.5.0 provides a simple provider-based pattern to manage JWT access and refresh tokens, using browser cookies for storage and automatically refreshing tokens when they expire. Unlike NextAuth.js, it does not create API routes inside your Next.js app, avoiding an extra hop between frontend and auth service, and focuses solely on JWT auth without support for social login or database adapters. The library requires Next.js ^16.2.4, React >=18, and Axios ^1.6.8 as peer dependencies. It ships with TypeScript types and is actively maintained, with frequent releases (latest v1.5.0 as of April 2025). Key differentiators: direct frontend-to-auth-service calls, automatic token refresh and logout, and minimal boilerplate.

error Uncaught TypeError: Cannot read properties of undefined (reading 'token')
cause The access token property path in response does not match 'accessToken.property' config.
fix
Verify that authConfig.accessToken.property matches the exact nested path in your API response (e.g., 'access.token' for { access: { token: '...' } }).
error next-jwt-auth: Failed to parse token expiry. Please provide a valid date string or timestamp.
cause The 'expiresAt' field in the API response is missing or not a valid date format.
fix
Ensure your auth service returns 'expiresAt' as an ISO 8601 string (e.g., '2025-12-31T23:59:59Z') or a Unix timestamp (number).
error Module not found: Can't resolve 'next-jwt-auth' in '/path/to/project'
cause Library not installed, or installed in wrong directory (e.g., not in same package.json as the importing code).
fix
Run npm install next-jwt-auth from the project root. Ensure your build tool resolves node_modules correctly.
error Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
cause useJWTAuth or useAuth called outside of a React component or before the AuthProvider is mounted.
fix
Wrap your app with <AuthProvider> at the top level (e.g., in _app.tsx) and only call useAuth() inside children of the provider.
error TypeScript error: 'AuthUser' is declared but its value is never read.
cause Importing AuthUser as a value instead of a type (type-only import needed).
fix
Change to 'import type { AuthUser } from 'next-jwt-auth'' or use 'import { type AuthUser } from 'next-jwt-auth''.
breaking Requires Next.js ^16.2.4 (previously supported ^14.1.4). Update Next.js or pin to older version.
fix Upgrade Next.js to >=16.2.4 or use next-jwt-auth@1.3.0 for Next.js 14 support.
deprecated The 'login' method no longer accepts a callback URL; use the 'redirect' config option instead.
fix Set 'redirect.afterLogin' in authConfig instead of passing a second argument to login().
deprecated The 'logout' method no longer logs out automatically on refresh token expiry; you must manually check 'isTokenExpired'.
fix Use the 'onTokenExpired' callback in authConfig to trigger logout.
gotcha Axios peer dependency must be exactly ^1.6.8. Using a different version may cause import errors.
fix Install axios@1.6.8: npm install axios@1.6.8
gotcha Cookies are set with httpOnly: false by default, making them accessible to JavaScript (XSS risk).
fix Set 'cookieOptions.httpOnly: true' if your auth service sets cookies server-side, or use a backend proxy for sensitive tokens.
npm install next-jwt-auth
yarn add next-jwt-auth
pnpm add next-jwt-auth

Demonstrates setup with custom user type, config, provider wrapper, and login/logout using the useAuth hook.

// src/types/Auth.ts
import { AuthUser } from 'next-jwt-auth'

export interface LoggedInUser extends AuthUser {
  email: string
  firstName: string
  lastName: string
  phone: string
}

// src/config/Auth.ts
import { JWTAuthConfig, createJWTAuthProvider, useJWTAuth } from 'next-jwt-auth'

const authConfig: JWTAuthConfig = {
  apiBaseUrl: process.env.NEXT_PUBLIC_API_BASE_URL ?? 'http://localhost:4000',
  user: { property: 'user' },
  accessToken: { property: 'access.token' },
  refreshToken: { property: 'refresh.token' },
  login: {
    url: '/auth/signin',
    method: 'POST',
    body: { email: '', password: '' }
  },
  refresh: { url: '/auth/refresh', method: 'POST' },
  logout: { url: '/auth/logout', method: 'POST' },
  cookieOptions: { httpOnly: false, secure: true, sameSite: 'strict' }
}

export const { AuthProvider, useAuth } = createJWTAuthProvider<LoggedInUser>(authConfig)

// pages/_app.tsx
import { AuthProvider } from '../config/Auth'

function MyApp({ Component, pageProps }) {
  return (
    <AuthProvider>
      <Component {...pageProps} />
    </AuthProvider>
  )
}

export default MyApp

// pages/profile.tsx
import { useAuth } from '../config/Auth'

export default function Profile() {
  const { user, login, logout, isAuthenticated } = useAuth()

  const handleLogin = async () => {
    await login({ email: 'user@example.com', password: 'pass123' })
  }

  return (
    <div>
      {isAuthenticated ? (
        <>
          <p>Welcome, {user?.firstName}</p>
          <button onClick={logout}>Logout</button>
        </>
      ) : (
        <button onClick={handleLogin}>Login</button>
      )}
    </div>
  )
}