
Passwords, handled
Modern password protection you never have to configure or second-guess. A copy of your database is not a copy of your customers’ accounts.
Everything behind a login. Sign-up, sign-in, email verification, password reset, as a library you embed rather than a service you rent. Secure by default, sessions you can end instantly, one account id the whole family shares. It already runs this site.


Modern password protection you never have to configure or second-guess. A copy of your database is not a copy of your customers’ accounts.

Sessions live on your side, so ending one actually ends it, not a token you hope expires before anyone notices.

Sign-up, sign-in and reset answer the same way whether or not an account exists, so nobody can fish for who your customers are.

A single account id the rest of the family keys on, so a person is the same person across billing, teams and email.

Available per account and off by default. A security upgrade you can offer, not a wall you make everyone climb on day one.

Social sign-in with a clear rule for when two logins are the same person. An extra front door, not a back one.
A password, a second factor, a scoped key: layered, and each one optional.
Check the password or the social sign-in, without ever revealing whether that account exists.
Start a session for that account, stepping up to a second factor if you have asked for one.
End any session on demand. Because it lives in your database, it is over immediately.
import { signup, login, sessions } from '@quxkit/identity-kit';
// the flow answers the same way whether or not the account exists
const user = await signup(sql, { email, password, pepper });
// sessions live on your side, so ending one actually ends it
const session = await login(sql, { email, password, pepper });
await sessions.revoke(sql, session.id);A session you cannot end is a promise you cannot keep.