You can add passkey sign-in to a Next.js application without implementing WebAuthn ceremonies in your application. Sudomimus hosts the passkey challenge. Your Next.js server starts a Connect login, handles the callback, and keeps the resulting session on the server.
The application sign-in page shows what this looks like for the user.
This guide uses the official @sudomimus/nextjs integration and Next.js App Router. It assumes your users sign in through a browser. For a standard OIDC library instead, read OIDC or Connect: which path fits?.
1. Configure the application
Create an organization and application in the With portal. Save the applicationAnchor and the client-auth private key. The key is shown once and belongs in protected server storage.
Add these rules before you test login:
- Layer 1: Add
PASSKEY_USERNAMELESSfor a passkey button before the email field,PASSKEY_REASONEDfor an email-first passkey option, or both. Each rule has an empty{}payload. - Layer 2: Add a realize rule that admits your intended accounts. For example, an
EMAILrule can allow your test address. Layer 1 alone does not grant entry. - Layer 3: Add a
CALLBACKreturn rule that permits the hostname of your Next.js callback URL. Configure that exact callback URL in the SDK options.
For example, the standalone passkey entry uses this Layer 1 rule shape:
{ "method": "PASSKEY_USERNAMELESS", "payload": {}}New applications start in DRAFT. Take the application live when the rules and callback are ready. Users must already have a passkey registered with Sudomimus. The application rule controls sign-in choices; it does not enroll a passkey for them.
2. Wire the server routes
Install @sudomimus/nextjs and create one server-only module. Supply the Connect options and a shared, durable WebAuthStore described in the Next.js SDK guide. Do not put the client-auth private key or pending login state in a Client Component.
import { createNextHandlers } from "@sudomimus/nextjs";
export const { start, callback, logout, current, currentFromCookieHeader,} = createNextHandlers(options);Export the handlers from App Router route files:
export { start as POST } from "@/lib/sudomimus";
// app/auth/callback/route.tsexport { callback as GET } from "@/lib/sudomimus";
// app/api/logout/route.tsexport { logout as POST } from "@/lib/sudomimus";Start and logout are POST routes. The SDK validates their Origin against the callback origin. Keep CSRF protection enabled. Do not change these handlers to GET links.
3. Read the session on the server
Use current(request) inside a Route Handler. In a Server Component, pass the request cookie header to currentFromCookieHeader. Render only the user information your page needs. Keep returned tokens out of Client Components, browser storage, and logs.
The browser visits Sudomimus for the passkey prompt, then returns to your callback. Your application does not call the browser’s WebAuthn API directly. If you enabled both passkey methods, users can choose the standalone button or enter an email first; both methods use the same registered credential.
4. Test the boundary
Try a registered passkey, a user without a passkey, a cancelled browser prompt, and an unapproved callback hostname. Confirm that an application with no matching Layer 2 rule refuses entry even when the passkey proof succeeds. Test logout and a new login after the session ends.
For rule details, see passkey authentication rules. For the complete Connect lifecycle, see your first login.