Passkeys Are the New Norm. We Built the Package to Prove It.
There's a version of authentication that requires no password, no email link, no TOTP code, no "forgot password" flow, no credential breach risk, and no phishing surface.
It ships in every modern device. It runs on biometrics — Face ID, Touch ID, Windows Hello. The protocol is a W3C standard. The support is near-universal.
And almost no apps use it.
That's a strange situation. The answer to "how do we fix authentication?" has been in production hardware for years. The problem is that the implementation — wiring WebAuthn correctly, managing challenges server-side, handling the ceremony across registration and authentication, issuing session tokens — is tedious enough that most teams just reach for next-auth and call it done.
We got tired of that. So we built @hyperdrift/auth.
What Passkeys Actually Are
A passkey is a public/private key pair where the private key never leaves your device.
When you register:
- Your device generates a key pair in the Secure Enclave (hardware-level isolation)
- The public key is sent to and stored by the server
- The private key stays locked in hardware — sealed by biometrics or device PIN
When you authenticate:
- The server sends a random challenge
- Your device signs it with the private key (gated behind Face ID / Touch ID / Windows Hello)
- The server verifies the signature with the stored public key
No password ever exists. No secret ever travels. Nothing to steal. Nothing to phish.
The Web3 Connection
This matters doubly in crypto.
The single biggest user experience failure in web3 is the seed phrase. Twelve words that represent your entire financial life. Written on paper. Stored somewhere. Lost sometimes. Phished constantly.
At web3.capital, we eliminated it entirely. The app uses Porto — an EIP-7702 smart wallet connector that uses a device passkey as the authentication layer. No seed phrase. No browser extension. No gas confusion. Just Face ID.
That's not a UX trick. It's the actual capability of the WebAuthn standard applied to wallet signing. The key that signs your DeFi transactions is stored in the same Secure Enclave that protects your iPhone's payment data.
When we built that, we extracted the server-side auth logic into a reusable package — because if we needed it here, every app in the HyperDrift ecosystem needed it.
The @hyperdrift/auth Package
The package covers the full WebAuthn ceremony for a Next.js App Router application.
Server Side
import { verifyRegistration, verifyAuthentication } from '@hyperdrift/auth/server'
import { challengeStore } from '@hyperdrift/auth/server'
import { createSessionCookie, SESSION_COOKIE_NAME } from '@hyperdrift/auth/server'
import { signJwt, verifyJwt } from '@hyperdrift/auth/server'
ChallengeStore — an in-memory TTL store (60s default) that manages the server-side challenge for each in-flight ceremony. Cleans itself up every 5 minutes. One singleton per Node.js process.
createSessionCookie / verifyJwt — signs a short-lived JWT after a successful ceremony and sets it as an HttpOnly cookie. The cookie is SameSite=Strict, never readable by JavaScript.
Client Side
import { usePasskeyLogin } from '@hyperdrift/auth/client'
import { AuthProvider, useAuth } from '@hyperdrift/auth/client'
usePasskeyLogin — a headless React hook that manages the full WebAuthn state machine. It handles startRegistration / startAuthentication from @simplewebauthn/browser, drives the server round-trips, and returns a clean { step, error, user, register, authenticate } interface.
const { step, error, register, authenticate, isSupported } = usePasskeyLogin()
// Register a new passkey
await register('user@example.com', 'Display Name')
// Authenticate with an existing passkey
await authenticate('user@example.com')
AuthProvider / useAuth — React context layer. Wrap your app once; call useAuth() anywhere to get the current user or trigger sign-out.
The State Machine
idle → loading → success
↘ error → idle (via reset())
No manual loading flags. No try/catch in your component. The hook owns the ceremony; your UI observes the state.
Why Not next-auth?
next-auth (Auth.js) is excellent for OAuth flows — "Sign in with Google", GitHub, etc. If that's your model, use it.
But passkeys require you to own the ceremony. You're generating challenges, verifying signatures, managing the credential store. That ceremony doesn't map cleanly onto OAuth adapter abstractions.
@hyperdrift/auth is narrower by design: it does WebAuthn registration and authentication, session management via HttpOnly cookies, and nothing else. No OAuth. No magic. Just the protocol, wired correctly.
Phishing Resistance by Design
This is the part that doesn't get enough emphasis.
Passkeys are origin-bound. The credential created for web3.hyperdrift.io can only be used on web3.hyperdrift.io. A phishing page at web3-hyperdrift.io (note the hyphen) will never receive a valid signature from the user's device — the browser checks the origin, the credential doesn't match, the ceremony fails.
Passwords don't have this property. Neither do TOTP codes. Email magic links are marginal. Passkeys make the phishing vector structurally impossible.
For a DeFi app like web3.capital — where a phishing attack means drained funds — this isn't a nice-to-have. It's the baseline.
The Path Forward
The ecosystem is moving. Apple, Google, and Microsoft have all shipped passkey support in their platforms. The FIDO Alliance is pushing hard. Browser support is excellent. The remaining gap is implementation — teams that know it's better but haven't done the migration.
@hyperdrift/auth is our bet that the Next.js ecosystem needs a simple, un-abstracted path to WebAuthn. Not another OAuth adapter. The actual protocol.
Passwords aren't going away immediately. But every new app we build — web3.capital, HyperCV, whatever comes next — ships passwordless from day one.
That's the norm now. The package is how we enforce it.
@hyperdrift/auth is part of the HyperDrift package ecosystem. Open-source, built for the apps we run. Questions, contributions, or just want to talk passkeys? Find us here.
Get weekly intel — courtesy of intel.hyperdrift.io