That users table with a password_hash is already a separate product.
stwrd gives you the whole entrance — OIDC, passkeys, organizations, roles, SSO and an audit trail — behind six routes and an SDK. You start without a card: the flex plan has no fixed fee and costs CLP 12 per user who comes back.
No card. No tax profile. CLP 10.000 of balance to try it tonight.
import { Stwrd, requirePermission } from "@stwrd/node"; const stwrd = Stwrd.fromEnv(); // resolves the session once per request app.use(stwrd.attach()); // sign-in, callback, sign-out, webhooks… app.use(stwrd.authRouter()); app.get("/billing", requirePermission(stwrd, "billing:read"), (req, res) => res.json(req.stwrd.user)); // The permission came from the organization the // user signed into. You never wrote a roles table.
- Six routes
- The session lives on your server; the token never touches the browser
- Standards
- OIDC with PKCE, refresh rotation, JWKS per tenant
- Three SDKs
- Python, Node and React. Same routes, same responses
- No surprises
- Every row carries its tenant. Not a convention: a constraint
Nobody decides to build an identity provider. You get there anyway, one ticket at a time.
The first version takes two hours: a table, a hash, a cookie. The problem is what comes after — never in the estimate, always in the sprint.
What grows out of the users table
- +Password resetA single-use token, expiring, that cannot be spent twice even when two requests arrive at once.
- +“Does that email exist?”Sign-up and recovery have to answer identically whether the account exists or not. Byte for byte.
- +Second factorTOTP with its drift window, single-use backup codes, and the whole WebAuthn ceremony if you want passkeys.
- +Signing out for realRevoke the session, its refresh family, and tell the other applications. Today you delete a cookie.
- +Organizations and invitationsThe day a customer has two people: members, roles, expiring invites, who is allowed to invite.
- +SAMLMetadata, signatures, ACS, skewed clocks. It shows up in the meeting where you were closing the contract.
- +An audit trail that survives an auditAppend-only for real, not an
INSERTsomeone can forget in the new route.
What you write instead
- ✓Two lines to mount
/auth/*Sign-in, callback, sign-out, session and webhooks. The session resolves once per request. - ✓One guard per route
requirePermission(stwrd, "billing:read"). The permission travels in the token. - ✓Zero auth screens in your repoSign in, sign up, recover, enrol a factor and manage the account are built and translated already.
- ✓Passkeys without touching WebAuthnAnd at no cost: the second factor is free on all three plans, because charging for it hands the entry plan to the attacker.
- ✓SSO lands when they ask for itTurned on per organization the day of the meeting, not the quarter after.
- ✓Middleware writes the audit trailNo route can forget to log: it is not discipline, it is where the code lives.
- ✓And if you regret it, you exportUsers, hashes, organizations, roles and memberships, documented, with what cannot leave said up front.
Prepaid, no card on file, no surprises at the end of the month.
You top up, usage is debited the moment it happens, and no end-of-month invoice ever arrives for something you did not see coming. And if the balance is running low we tell you first — when seven days of runway are left at the rate you are spending, and again at two. If it still reaches zero, new accounts stop being created but everyone who already has one keeps signing in, and you have thirty days to top up before the service is cut off. Topping up reverses everything at once.
| Your brand: logo, colors, and no stwrd footer | CLP 600 / day |
|---|---|
| Your own roles and permissions | CLP 250 / day |
| Require a second factor | CLP 250 / day |
| Configurable sessions | CLP 150 / day |
| 30-day audit retention | CLP 150 / day |
| 90-day audit retention | CLP 400 / day |
| SAML connection, each | CLP 1.500 / day |
The crossover is at 2,000 retained users. We are telling you ourselves.
It is arithmetic, not a sales call: below two thousand, flex costs less than pro; at exactly two thousand they cost the same; above it, pro is cheaper. The pro-to-max crossover sits at six thousand.
Stay on flex. You are paying two thirds of a fixed fee you never signed up for.
The indifference point. From here, pro includes what you were buying by the day on flex.
The second crossover. Max also brings one SAML connection and 90-day retention.
Your first big customer always sends the same six questions.
Never about your product: about whether their IT and compliance people can live with it. And they arrive after the demo went well, when signing is the only thing left. All six ship in the box.
“We sign in with our own identity provider.”
SAML per organization, not per tenant: their connection, their certificate, their metadata. The clinic next door keeps using a password.
“Our admins manage our own people.”
A delegated console at /my-org: members, invitations, roles, domains and their own audit trail. Their admin stops being a ticket in your support queue.
“Show us who accessed what.”
An append-only ledger written by middleware, never by an endpoint someone can forget. Readable by API on all three plans; the plan changes how many days it lasts.
“When we offboard someone, they are out.”
Back-channel logout reaches your application, not just the browser tab. The session and its refresh family die together, in one statement.
“Our roles are not your roles.”
Roles and permissions defined per organization and carried in the token: your code asks requirePermission and never writes a roles table again.
“What happens if we leave?”
A documented export — users, password hashes, organizations, roles, memberships — with an honest list of what cannot leave: passkeys, TOTP secrets, live sessions.
One tenant. As many organizations as you sell to.
If your product is sold to companies, every customer of your customer is an organization: its members, its roles, its branding on the sign-in screen, its SSO if it has one. Unlimited on all three plans — we removed the meter, because charging per organization taxes exactly the growth you want.
A person can belong to several. The token says which one they signed into, and the permissions travel with it.
Three customers, three ways in, one integration. The solo practice does not need SAML, and the hospital will not accept anything else.
Everyone starts on flex. You move when the fixed fee works out cheaper.
Prices in Chilean pesos. No setup fee, no seat minimum, no annual contract required.
- Prepaid balance, debited as it happens
- CLP 10.000 to start, no card, no tax profile
- Unlimited organizations and applications
- Passkeys, TOTP and backup codes
- Your brand, own roles, SAML and longer retention: by the day, from your balance
- Everything in flex, included instead of by the day
- Your brand on the screens, and the stwrd footer switchable
- Your own roles and permissions
- Audit retention: 30 days
- SAML connections at CLP 38.000 each
- Everything in pro
- One SAML connection included
- Audit retention: 90 days
- Priority support with an SLA
- Extra SAML connections at CLP 28.000
Annual, if you want it: pay ten months instead of twelve, take 25% off every retained user and freeze the price list for a year. No exit fee of any kind — not a penalty, not a clawback: if you leave in month three, you simply stop paying.
From the click to your own sign-in screen.
No sales call, no form to request a sandbox, no waiting for an account manager.
Create your tenant
With GitHub, Google or an email address. Your organization's name is what your people will see on the sign-in screen.
Secure the account
A passkey, backup codes shown exactly once, and a recovery address different from the one you signed up with.
Take your credentials
Issuer, client id and secret, plus the snippet for your framework — and instructions your coding agent can follow on its own.
Try the login
Your screen, on your return URL, with the balance already there. You move up from the inside the day the arithmetic says so.
A Thursday at 8pm is enough.
Create the tenant, paste two lines, and your login works. No card, no tax profile, CLP 10.000 of balance: your first retained user costs twelve pesos.