Lower-level functions
useJWESession and useJWSSession are the high-level path — they wire up reading, hooks, cookies, and the SessionManager in one call. For the cases where you need explicit control over those steps (custom flows, testing, one-off token minting, external session stores), unjwt exposes the underlying building blocks.
Import:
import {
getJWESession,
getJWESessionToken,
updateJWESession,
sealJWESession,
unsealJWESession,
clearJWESession,
getJWSSession,
updateJWSSession,
signJWSSession,
verifyJWSSession,
clearJWSSession,
} from "unjwt/adapters/h3v2";
Every function takes the H3 event and the matching SessionConfigJWE / SessionConfigJWS (the same one you'd pass to the high-level useX helper).
JWE functions
| Function | Purpose |
|---|---|
getJWESession(event, config) | Read/initialize session from cookie or header |
getJWESessionToken(event, config) | Get raw token string (no decryption) |
updateJWESession(event, config, update?) | Update data, re-encrypt, set cookie |
sealJWESession(event, config) | Encrypt current session to JWE token string |
unsealJWESession(event, config, token) | Decrypt a JWE token to session data |
clearJWESession(event, config) | Delete session from context and expire cookie |
JWS functions
| Function | Purpose |
|---|---|
getJWSSession(event, config) | Read/initialize session from cookie or header |
updateJWSSession(event, config, update?) | Update data, re-sign, set cookie |
signJWSSession(event, config) | Sign current session to JWS token string |
verifyJWSSession(event, config, token) | Verify a JWS token to session data |
clearJWSSession(event, config) | Delete session from context and expire cookie |
Typical uses
Mint a one-off token without cookies
For generating a token to send via email (magic link, password reset), you don't want the cookie side-effects of useJWSSession:
import { signJWSSession } from "unjwt/adapters/h3v2";
app.post("/request-magic-link", async (event) => {
const email = (await event.req.json()).email;
const token = await signJWSSession(event, {
key: magicLinkKey,
maxAge: "15m",
cookie: false, // don't set a cookie
sessionHeader: false, // don't read one either
});
await sendEmail(email, `https://app.example.com/login?token=${token}`);
return { ok: true };
});
Access the refresh token from an access-token hook
The refresh-token example uses this pattern — from inside the access token's onExpire, peek at the refresh session without creating a new SessionManager:
hooks: {
async onExpire({ event, config }) {
const refresh = await getJWESession(event, refreshConfig);
if (!refresh.data.sub) return;
await updateJWSSession(event, config, {
sub: refresh.data.sub,
scope: refresh.data.scope,
});
},
},
getJWESession returns the same shape as the high-level useJWESession, but you're in control of when it runs.
Verify an externally-sourced token
You received a token through some channel other than the default cookie/header — a webhook body, a query parameter, a separate header — and want to verify it using your session config:
import { verifyJWSSession } from "unjwt/adapters/h3v2";
app.post("/webhook", async (event) => {
const payload = await event.req.json();
const token = payload.signedEvent;
const session = await verifyJWSSession(event, config, token);
if (!session.data.userId) {
throw new HTTPError("Invalid signed event", { status: 403 });
}
// process payload...
});
Roll a session over to a different key
For scheduled key rotation, you can clear the session with the old key and re-seal with a new config:
// old config (before rotation)
const old = { key: oldKey, maxAge: "7D" } satisfies SessionConfigJWE;
// new config (after rotation)
const nu = { key: newKey, maxAge: "7D" } satisfies SessionConfigJWE;
app.post("/rotate-keys", async (event) => {
const session = await getJWESession(event, old);
if (!session.data.userId) throw new HTTPError("Not authenticated", { status: 401 });
const data = session.data;
await clearJWESession(event, old);
await updateJWESession(event, nu, data);
return { ok: true };
});
When to stay high-level
Reach for the lower-level functions only when you need the specific behavior they expose. For anything that fits the "one session per request" shape, useJWESession / useJWSSession — plus hooks — will be shorter and less error-prone.