Sign In

@authon/nextjs

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@authon/nextjs

Authon Next.js SDK — middleware, server helpers, and React components

latest
Source
npmnpm
Version
0.3.0
Version published
Weekly downloads
24
Maintainers
1
Weekly downloads
 
Created
Source

English | 한국어

@authon/nextjs

Next.js integration for Authon. Includes edge middleware, server-side helpers, and all React components and hooks.

Install

npm install @authon/nextjs @authon/js
# or
pnpm add @authon/nextjs @authon/js

Requires next >= 14.0.0.

Setup

1. Middleware

Create middleware.ts at your project root to protect routes at the edge:

// middleware.ts
import { authonMiddleware } from '@authon/nextjs';

export default authonMiddleware({
  publicRoutes: ['/', '/about', '/pricing', '/sign-in', '/sign-up'],
  signInUrl: '/sign-in',
});

export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico|.*\\..*).*)'],
};

Any route not listed in publicRoutes will redirect unauthenticated users to signInUrl. The original destination is preserved as a redirect_url query parameter.

2. AuthonProvider in layout

Wrap your root layout with <AuthonProvider>:

// app/layout.tsx
import { AuthonProvider } from '@authon/nextjs';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <AuthonProvider publishableKey={process.env.NEXT_PUBLIC_AUTHON_KEY!}>
          {children}
        </AuthonProvider>
      </body>
    </html>
  );
}

Middleware

authonMiddleware(options)

import { authonMiddleware } from '@authon/nextjs';

export default authonMiddleware({
  publicRoutes: ['/', '/blog*', '/sign-in'],
  signInUrl: '/sign-in',
  secretKey: process.env.AUTHON_SECRET_KEY,
  apiUrl: 'https://api.authon.dev',
});
OptionTypeDefaultDescription
publicRoutesstring[]['/']Routes that do not require authentication. Supports trailing * wildcard (e.g. '/blog*')
signInUrlstring'/sign-in'Redirect destination for unauthenticated users
secretKeystring (optional)process.env.AUTHON_SECRET_KEYSecret key for token verification
apiUrlstring (optional)'https://api.authon.dev'Authon API base URL

The middleware automatically allows /_next/*, /api/*, and /favicon.ico through without authentication.

Server-Side Helpers

Import from @authon/nextjs/server for use in Server Components and Route Handlers.

currentUser()

Returns the authenticated user from the session cookie, or null if not signed in.

// app/api/profile/route.ts
import { currentUser } from '@authon/nextjs/server';

export async function GET() {
  const user = await currentUser();

  if (!user) {
    return new Response('Unauthorized', { status: 401 });
  }

  return Response.json({
    id: user.id,
    email: user.email,
    displayName: user.displayName,
  });
}
// app/dashboard/page.tsx (Server Component)
import { currentUser } from '@authon/nextjs/server';
import { redirect } from 'next/navigation';

export default async function DashboardPage() {
  const user = await currentUser();

  if (!user) {
    redirect('/sign-in');
  }

  return <h1>Welcome, {user.displayName}!</h1>;
}

Return type: Promise<AuthonUser | null>

auth()

Returns the full auth state including userId, user, and a getToken() function. Useful when you need to forward the token to a downstream service.

// app/api/data/route.ts
import { auth } from '@authon/nextjs/server';

export async function GET() {
  const { userId, user, getToken } = await auth();

  if (!userId) {
    return new Response('Unauthorized', { status: 401 });
  }

  const token = getToken();

  // Forward token to an internal service
  const response = await fetch('https://internal-api.example.com/data', {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });

  return Response.json(await response.json());
}

Return type:

Promise<{
  userId: string | null;
  user: AuthonUser | null;
  getToken: () => string | null;
}>

Client Components

All components and hooks from @authon/react are re-exported from @authon/nextjs. Add 'use client' to any component that uses them.

Components

'use client';

import {
  SignedIn,
  SignedOut,
  UserButton,
  SignIn,
  SignUp,
  Protect,
  SocialButtons,
} from '@authon/nextjs';

export function Navbar() {
  return (
    <nav>
      <SignedIn>
        <UserButton />
      </SignedIn>
      <SignedOut>
        <a href="/sign-in">Sign In</a>
      </SignedOut>
    </nav>
  );
}

Auth Page Example

// app/sign-in/page.tsx
'use client';

import { SignIn, SocialButtons } from '@authon/nextjs';

export default function SignInPage() {
  return (
    <div style={{ maxWidth: 400, margin: '80px auto', padding: 24 }}>
      <h1>Sign In</h1>
      <SocialButtons
        onSuccess={() => (window.location.href = '/dashboard')}
        onError={(err) => console.error(err)}
      />
      <SignIn mode="embedded" />
    </div>
  );
}

Role-Based Access

'use client';

import { Protect } from '@authon/nextjs';

export function AdminSection() {
  return (
    <Protect
      fallback={<p>You need admin access to view this section.</p>}
      condition={(user) => user.publicMetadata?.role === 'admin'}
    >
      <AdminPanel />
    </Protect>
  );
}

Hooks

All hooks from @authon/react are re-exported. Use them in Client Components.

useAuthon()

'use client';

import { useAuthon } from '@authon/nextjs';

export function SignOutButton() {
  const { signOut, isSignedIn } = useAuthon();

  if (!isSignedIn) return null;

  return <button onClick={() => signOut()}>Sign Out</button>;
}

useUser()

'use client';

import { useUser } from '@authon/nextjs';

export function UserGreeting() {
  const { user, isLoading } = useUser();

  if (isLoading) return <span>Loading...</span>;
  if (!user) return null;

  return <span>Hello, {user.displayName ?? user.email}!</span>;
}

useAuthonMfa()

'use client';

import { useAuthonMfa } from '@authon/nextjs';

export function MfaSettings() {
  const { setupMfa, verifyMfaSetup, disableMfa, getMfaStatus, regenerateBackupCodes, isLoading, error } =
    useAuthonMfa();

  const handleEnable = async () => {
    const result = await setupMfa();
    if (result) {
      // result.qrCodeSvg — SVG string to render QR code
      // result.backupCodes — one-time recovery codes
      // result.secret — raw TOTP secret
    }
  };

  const handleDisable = async (totpCode: string) => {
    const success = await disableMfa(totpCode);
    if (success) console.log('MFA disabled');
  };

  return (
    <div>
      <button onClick={handleEnable} disabled={isLoading}>Enable MFA</button>
      {error && <p>{error.message}</p>}
    </div>
  );
}

useAuthonPasskeys()

'use client';

import { useAuthonPasskeys } from '@authon/nextjs';

export function PasskeyManager() {
  const { registerPasskey, listPasskeys, revokePasskey, isLoading, error } = useAuthonPasskeys();

  const handleRegister = async () => {
    const passkey = await registerPasskey('My Device');
    if (passkey) console.log('Registered:', passkey.id);
  };

  return (
    <button onClick={handleRegister} disabled={isLoading}>
      Add Passkey
    </button>
  );
}

useAuthonPasswordless()

'use client';

import { useAuthonPasswordless } from '@authon/nextjs';
import { useState } from 'react';

export function MagicLinkForm() {
  const { sendMagicLink, isLoading, error } = useAuthonPasswordless();
  const [email, setEmail] = useState('');
  const [sent, setSent] = useState(false);

  const handleSubmit = async () => {
    const success = await sendMagicLink(email);
    if (success) setSent(true);
  };

  if (sent) return <p>Check your email for a sign-in link.</p>;

  return (
    <div>
      <input value={email} onChange={(e) => setEmail(e.target.value)} placeholder="Email" />
      <button onClick={handleSubmit} disabled={isLoading}>Send Link</button>
      {error && <p>{error.message}</p>}
    </div>
  );
}

useAuthonWeb3()

'use client';

import { useAuthonWeb3 } from '@authon/nextjs';

export function WalletLogin() {
  const { getNonce, verify, isLoading, error } = useAuthonWeb3();

  const handleConnect = async () => {
    const address = '0xYourAddress';
    const nonceResponse = await getNonce(address, 'evm', 'metamask', 1);
    if (!nonceResponse) return;

    const signature = await window.ethereum.request({
      method: 'personal_sign',
      params: [nonceResponse.message, address],
    });

    const success = await verify(nonceResponse.message, signature, address, 'evm', 'metamask');
    if (success) console.log('Signed in with wallet!');
  };

  return (
    <button onClick={handleConnect} disabled={isLoading}>
      Connect Wallet
    </button>
  );
}

useAuthonSessions()

'use client';

import { useAuthonSessions } from '@authon/nextjs';
import { useEffect, useState } from 'react';
import type { SessionInfo } from '@authon/shared';

export function ActiveSessions() {
  const { listSessions, revokeSession, isLoading, error } = useAuthonSessions();
  const [sessions, setSessions] = useState<SessionInfo[]>([]);

  useEffect(() => {
    listSessions().then((s) => {
      if (s) setSessions(s);
    });
  }, []);

  const handleRevoke = async (id: string) => {
    const success = await revokeSession(id);
    if (success) setSessions((prev) => prev.filter((s) => s.id !== id));
  };

  if (isLoading) return <p>Loading...</p>;

  return (
    <ul>
      {sessions.map((session) => (
        <li key={session.id}>
          <span>{session.userAgent ?? 'Unknown'}</span>
          <button onClick={() => handleRevoke(session.id)}>Revoke</button>
        </li>
      ))}
      {error && <p>{error.message}</p>}
    </ul>
  );
}

Re-exported API Reference

Everything below is re-exported from @authon/react and available directly from @authon/nextjs.

Components

ComponentDescription
<AuthonProvider>Provides auth context — wrap your root layout
<SignIn>Opens sign-in modal or renders embedded form
<SignUp>Opens sign-up modal or renders embedded form
<UserButton>Avatar dropdown with user info and sign-out
<SignedIn>Renders children only when signed in
<SignedOut>Renders children only when signed out
<Protect>Role-based access guard with optional condition
<SocialButton>Single OAuth provider button
<SocialButtons>Auto-renders enabled OAuth provider buttons

Hooks

HookDescription
useAuthon()Full auth context: user, signOut, openSignIn, getToken, client
useUser()Shorthand for { user, isLoading }
useAuthonMfa()TOTP MFA setup, verification, and management
useAuthonPasskeys()WebAuthn passkey registration and authentication
useAuthonPasswordless()Magic link and email OTP flows
useAuthonWeb3()Web3 wallet sign-in and wallet management
useAuthonSessions()List and revoke active sessions

Server Functions (@authon/nextjs/server)

FunctionReturnsDescription
currentUser()Promise<AuthonUser | null>Get the current user from the session cookie
auth()Promise<{ userId, user, getToken }>Get full auth state for server-side use

Environment Variables

# Required — your project's publishable key (safe to expose to the browser)
NEXT_PUBLIC_AUTHON_KEY=pk_live_...

# Required for server-side verification
AUTHON_SECRET_KEY=sk_live_...

# Optional — defaults to https://api.authon.dev
AUTHON_API_URL=https://api.authon.dev

Documentation

authon.dev/docs

License

MIT

Keywords

authon

FAQs

Package last updated on 09 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts