anomalyco/sst · error · Error
Missing token parameter
Error message
Missing token parameter
What it means
The LinkAdapter's /callback route reads a signed JWT from the `token` query parameter. The token is generated by the /authorize route and passed to your `onLink` handler (e.g. embedded in a magic link you email the user). If the callback URL is hit without a `token` query param, the adapter throws this error instead of trying to verify undefined with jose.
Source
Thrown at sdk/js/src/auth/adapter/link.ts:29
.setExpirationTime("10m")
.sign(await ctx.signing.privateKey());
const url = new URL(new URL(c.req.url).origin);
url.pathname = `/${ctx.name}/callback`;
for (const key of url.searchParams.keys()) {
url.searchParams.delete(key);
}
url.searchParams.set("token", token);
const resp = ctx.forward(
c,
await config.onLink(url.toString(), c.req.query()),
);
return resp;
});
routes.get("/callback", async (c) => {
const token = c.req.query("token");
if (!token) throw new Error("Missing token parameter");
const verified = await jwtVerify(token, await ctx.signing.publicKey());
const resp = await ctx.success(c, { claims: verified.payload as any });
return resp;
});
} satisfies Adapter<{ claims: Record<string, string> }>;
}
View on GitHub (pinned to a0bd20f762)
Solutions
- Ensure your `onLink` handler delivers the full `link` URL verbatim, including the `token` query parameter.
- Check whether your email/link provider rewrites or truncates URLs; use their mechanisms for preserving query strings.
- Confirm the user is reaching the callback via the link generated by /authorize, not by navigating to the callback URL directly.
- Add a redirect or friendly error page for missing-token callbacks by catching this error in your auth handler.
Example fix
// before: onLink rebuilds the URL and loses the token
async (link) => Response.redirect(link.split('?')[0], 302)
// after: keep the full link including ?token=...
async (link) => Response.redirect(link, 302) Defensive patterns
Strategy: validation
Validate before calling
const url = new URL(request.url);
if (!url.searchParams.get("token")) {
return new Response("Redirecting...", { status: 302, headers: { Location: "/login" } });
} Type guard
function hasToken(req: Request): req is Request & { token: string } {
return new URL(req.url).searchParams.has("token");
} Prevention
- Never rewrite or strip query strings from the link produced by /authorize in onLink.
- Test the magic-link flow with email providers known to rewrite URLs.
- Handle missing-token callbacks with a friendly redirect instead of a 500.
When it happens
Trigger: A GET request to `/<auth-name>/callback` with no `token` query parameter. Typical causes: the user's link provider stripped the query string, the user visited the callback URL directly, the `onLink` implementation truncated the URL, or a redirect dropped `url.searchParams`.
Common situations: Email providers (e.g. Outlook SafeLinks, some spam scanners) rewriting links and dropping query strings; a custom `onLink` that re-parses and rebuilds the URL losing searchParams; users clicking a partially copied link; bookmarking/expiring pages so only the base callback URL is visited.
Related errors
- Missing code
- error
- No auth resource found. Make sure to link the auth resource
- Unsupported response_type: ${response_type}
- Invalid grant_type
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/fd831b24f36b0875.
Report an issue: GitHub.