Skip to content

Check Sign-In on a Server

Share

Anything that matters is checked on the server, never by the kit. The kit and the data-kt-* attributes only hide things in the browser. If a page, file or API route is private, the server must refuse to send it.

The KT Accounts session cookie (__Host-kt.session_token) is sent by browsers to accounts.aidenkt.com and to nothing else, so a site’s own server never receives it. That means:

  • For a real server check, use OpenID Connect and keep your own session. This works today on any domain.
  • The cookie-based helpers below return “nobody” on a real site, for everyone. They fail closed. They work against the local stand-in, and will work on real sites once KT Accounts can hand a site proof of who is signed in, which is proposed and not built.

Single files with no dependencies, in the integrations/ folder of the KT Accounts repository. Copy them into the site.

File For
kt-accounts.mjs (and kt-accounts.d.mts for TypeScript) Anything with fetch: Workers, Deno, Bun, Node 18+
kt-accounts-middleware.mjs Express and Hono. Needs kt-accounts.mjs next to it
kt-accounts-next.mjs The Next.js app router. Needs kt-accounts.mjs next to it
import { getKtUser, requireKtUser, has, hasBadge } from "./kt-accounts.mjs";
const kt = { origin: env.KT_ACCOUNTS_ORIGIN ?? "https://accounts.aidenkt.com" };
const user = await getKtUser(request, kt); // a person, or null
const r = await requireKtUser(request, { ...kt, permission: "brand.materials" });
if ("response" in r) return r.response; // 401 or 403, ready to send
  • getKtUser(request, { origin }) returns the person or null. request can be a Request, a Headers, a Node request, or the Cookie header string.
  • requireKtUser(request, { origin, permission?, badge? }) returns { user } or { response }: 401 {"error":"sign_in_required"} or 403 {"error":"forbidden"}, both JSON with Cache-Control: no-store and Vary: Cookie.
  • has(user, name) follows the same rule as ktAccounts.can: the owner has every permission. hasBadge(user, "friend") is true only if the person carries that badge.
  • sendKtResponse(res, response) sends such a response through a Node res.
  • Express: ktExpress, requireKtExpress. Hono: ktHono, requireKtHono. Next.js: currentKtUser, ktMiddleware.

getKtUser sends only the KT session cookie to <origin>/api/whoami, gives up after 2 seconds, returns null on any failure, and keeps nothing between requests. origin must be exactly https://accounts.aidenkt.com or the stand-in on http://localhost:<port>; anything else throws a TypeError. The stand-in is refused when NODE_ENV is production.

People with the test badge are refused on an https origin unless you pass allowTest: true.

Never cache a response that depends on who is signed in: send Cache-Control: no-store. The guards do not protect against cross-site form posts; for routes that change something, also check the Origin header or use the framework’s CSRF protection.