AuthForge user guide
Everything you need to run your own identity engine — written for two audiences. If you just want to understand what AuthForge does, start with the Overview. If you run a website and want login today, start with Set up for your website or the setup wizard.
Configuring AuthForge? Enter your domain names and get copy-paste settings — no account required, no coding required.
Website owner
Follow Set up for your website or the setup wizard — plain language, step by step.
Developer
Go to the Quickstart, then JavaScript SDK and the API reference.
Overview
AuthForge answers one question for your application: "who is this user, and what are they allowed to do?" — and it answers it without sending your users' data to anyone else.
Most teams reach for a hosted service like Auth0 or Clerk. Those work, but they bill per user, they keep your identity data on their servers, and every login check makes a round trip to their cloud. AuthForge is the opposite: it is a single program you run on your own server. Your users' accounts, passwords, and sessions stay inside your infrastructure, and verification happens locally — in well under a millisecond.
In one sentence: AuthForge is self-hosted login and access control that you own outright, with bank-grade cryptography built in and no per-user fees.
Set up for your website
This section is for anyone who runs a website and wants login — you do not need to write Rust or read source code.
- Choose where AuthForge runs. The easiest path is Ratel (push the repo, attach a domain like
auth.yourdomain.com). On your own server, rundocker compose up --build. - Open the setup wizard. Type your domain names. Copy the generated environment variables into Ratel or your server.
- Test login. Visit
https://auth.yourdomain.com/login.html. Create an account or sign in with your workspace credentials. - Add sign-in to your site. Either link to AuthForge (
<a href="https://auth.yourdomain.com/login.html">Sign in</a>) or paste the one-line SDK snippet from the wizard into your site header. - Done. Your users sign in through AuthForge; their data stays on your infrastructure. Open the setup wizard → What's next tab for a printable go-live checklist.
Key concepts
A short glossary so the rest of the guide makes sense — useful whether or not you have a security background.
| Term | What it means |
|---|---|
| Identity | A user account — the person signing in. |
| Session | Proof that someone signed in successfully, valid for a limited time. |
| Session token (JWT) | A signed, tamper-evident string that carries the session. Your app reads it to know who the user is without asking the database again. |
| JWKS | The public keys AuthForge publishes so anything can verify a token's signature offline. Served at /api/v1/jwks.json. |
| Argon2id | The password-hashing algorithm AuthForge uses. Even if your database were stolen, passwords stay protected. |
| Ed25519 | The signature algorithm that proves a token came from your server and was not altered. |
| Organization / tenant | A customer workspace. Users belong to one or more organizations with roles and permissions. |
| Permission / role | What a user can do inside an organization (for example billing:read). These travel inside the session token. |
Quickstart
You need Docker installed. One command starts Postgres, the identity engine, and the login UI on port 8080.
- Start the stack.
terminal
git clone https://github.com/techmaster25/AuthForge cd AuthForge export AUTHFORGE_PASSWORD_PEPPER="$(openssl rand -base64 32)" docker compose up --build
- Open the login page. Visit
http://localhost:8080/login.htmland sign in or create an account. - Confirm public keys.
terminal
curl http://localhost:8080/api/v1/jwks.json # → { "keys": [{ "kty": "OKP", "crv": "Ed25519", ... }] } - Configure for production. Use the setup wizard to generate env vars for your domain.
Configuration
Everything is configured with environment variables. Every value has a safe default, so you can start with none and tune later. The most common settings:
| Variable | Default | Purpose |
|---|---|---|
AUTHFORGE_ISSUER | https://auth.authforge.dev | The URL stamped into every token; your edges expect to fetch keys from here. |
AUTHFORGE_AUDIENCE | authforge | The intended consumer of the tokens. |
AUTHFORGE_KEY_DIR | ./secrets/keys | Where signing keys are stored (mount a volume here). |
AUTHFORGE_SESSION_TTL_SECS | 3600 | How long a session token is valid, in seconds. |
AUTHFORGE_PASSWORD_PEPPER | (unset) | An optional server-held secret mixed into every password hash. Strongly recommended. |
AUTHFORGE_ARGON_M_COST | 19456 | Argon2 memory cost in KiB (≈19 MiB, the OWASP floor). |
AUTHFORGE_MAX_LOGIN_ATTEMPTS | 10 | Failed logins before a temporary lockout kicks in. |
AUTHFORGE_LOCKOUT_SECS | 300 | How long that lockout lasts. |
AUTHFORGE_STATIC_DIR | ./web (auto) | Login UI, docs, and SDK files served by the same process. |
AUTHFORGE_CORS_ORIGINS | (unset = dev) | Comma-separated front-end origins allowed to call the API. |
AUTHFORGE_DATABASE_URL | (unset = memory) | PostgreSQL connection string for production persistence. |
The full list ships in .env.example in the repository. Use the setup wizard to generate values for your domain.
Verify it works
Three quick checks confirm a healthy deployment:
- Liveness:
curl http://localhost:8080/healthzreturnsok. - Readiness:
curl http://localhost:8080/readyzreturnsready. - Keys:
/api/v1/jwks.jsonreturns one or more Ed25519 keys.
A successful AuthenticateUser call returns a session token plus the user's identity, organizations, and permissions. Passing that token to ValidateSession returns valid: true with the same identity — proof the round trip works end to end.
Integrate your app
The fastest path: add the zero-dependency SDK from your AuthForge host (same origin recommended):
<script src="https://auth.yourdomain.com/sdk/authforge.js"></script>
<script>
AuthForge.init({ authority: 'https://auth.yourdomain.com' });
AuthForge.login('user@example.com', 'password').then(function (s) {
console.log('Signed in as', s.identity.email);
});
</script>See the full setup wizard for copy-paste env vars and verification steps.
React apps can wrap the provider when the npm package ships; until then, call the SDK directly:
import { AuthForgeProvider, useAuth } from '@authforge/react';
export function App() {
return (
<AuthForgeProvider authority="https://auth.authforge.dev">
<Dashboard />
</AuthForgeProvider>
);
}
function Dashboard() {
const { user, status } = useAuth();
if (status === 'authenticating') return <Spinner />;
return <p>Signed in as {user?.email}</p>;
}On the back end, you do not need to call AuthForge to check a token — fetch the JWKS once, cache it, and verify the Ed25519 signature locally with any standard JWT library. That is what keeps verification under a millisecond with zero network round trips.
JavaScript SDK
Load /sdk/authforge.js from your AuthForge host. Zero dependencies, works in any HTML page, PHP site, WordPress theme, or SPA.
| Method | Description |
|---|---|
AuthForge.init({ authority }) | Point at your AuthForge URL (defaults to same origin). |
AuthForge.login(email, password, org?) | Sign in; stores session token; returns session payload. |
AuthForge.signup(email, password, org?) | Create account and sign in. |
AuthForge.me() | Current session, or null if signed out. |
AuthForge.logout() | End session locally and on the server. |
AuthForge.getToken() | Read the session token (for cross-origin Bearer auth). |
AuthForge.jwks() | Fetch the public signing keys. |
Ready-made login UI: copy login.html and signup.html from the repo, or link directly to them on your AuthForge host. See Brand your login for full white-label options.
Brand your login
AuthForge is headless-first — unlike Clerk or Auth0, there is no hosted dashboard where you drag sliders to recolor a vendor iframe. You own the login experience. That is intentional: your users never see a third-party auth wall, and you are never locked into our UI.
There are three practical paths, from fastest to most control:
| Approach | Best for | Your branding | AuthForge attribution |
|---|---|---|---|
1. Link out — send users to https://auth.yourdomain.com/login.html | Fastest setup; no front-end code | Replace the logo and colors in the shipped HTML files on your server | Default templates show a Secured by AuthForge badge at the bottom of the card (similar to Clerk). Remove it when you fork the templates. |
2. Fork the templates — copy login.html, signup.html, and assets/site.css into your site or CDN | Full white-label on your domain | Swap the logo, wordmark, accent color (--accent in CSS), and page title | Delete the .auth-secured block for a fully unbranded form |
| 3. Build your own UI — use the JavaScript SDK or REST API inside your existing sign-in page | React, PHP, WordPress, mobile apps | 100% your design system — AuthForge is invisible to end users | None — you control every pixel |
AUTHFORGE_BRAND_NAME, AUTHFORGE_BRAND_LOGO_URL, AUTHFORGE_BRAND_ACCENT, and AUTHFORGE_BRAND_HIDE_SECURED on your server — login pages fetch GET /api/v1/public/branding and apply them automatically. Per-org overrides live in the dashboard theme editor (owners only).Dashboard theme editor
After sign-in, organization owners on Pro or Enterprise open Login branding on the dashboard. Upload a logo from your computer (PNG, JPEG, WebP, or GIF up to 512 KB) or paste an image URL, set accent color, and optionally hide the Secured by AuthForge badge. Changes are stored per organization and merged over env defaults. Preview with login.html?org=your-slug.
Logo upload API: POST /api/v1/orgs/:slug/theme/logo with { "data_url": "data:image/png;base64,..." }. Uploaded files are served at GET /api/v1/public/org-assets/:slug/logo.
SSO connectors (Google & GitHub)
Login branding (name, logo, colors) is instant — set env vars or use the dashboard theme editor. No Google verification, no multi-day approval like Clerk.
Social sign-in buttons are optional. Paste OAuth client IDs from the setup wizard. Signup OAuth works immediately; login OAuth requires Pro.
OAuth callback URLs (register these in Google Cloud / GitHub):
https://auth.yourdomain.com/api/v1/auth/oauth/google/callbackhttps://auth.yourdomain.com/api/v1/auth/oauth/github/callback
Plans & billing
AuthForge uses infrastructure-first pricing. The identity engine itself is free to self-host with unlimited users. You pay us only when you want a commercial relationship — not a per-user tax.
Why would I pay if I self-host?
Self-hosted does not mean unsupported. When you subscribe, you are paying AuthForge (the company) for things the open engine cannot provide on its own:
- Human support — priority email, guided migrations, and (on higher tiers) SLA-backed response times.
- Legal & procurement — signed DPA, custom SLA, compliance evidence packs for security reviews.
- Entitlements in your deployment — your subscription syncs to your account via Stripe. Paid features (for example audit logs) are enforced server-side when your plan qualifies.
- Roadmap acceleration — SSO connectors, SAML/SCIM, and outbound webhooks are entitlement-gated on paid tiers and ship to subscribers first.
Your end users' credentials and sessions never pass through our servers. We bill for expertise and assurance, not for hosting your identity data.
| Plan | Price | What you get today |
|---|---|---|
| Community | Free | Full engine, unlimited users, login UI, SDK, JWKS, org RBAC, signup OAuth, community support. |
| Pro | From $79/mo | Login SSO, audit logs API, priority email support (48h SLA), guided onboarding. SAML/SCIM and webhooks on roadmap for Pro subscribers. |
| Enterprise | $500/mo or $4,980/yr | Dedicated architect, signed DPA, air-gapped options, 24/7 SLA, security review support. |
Upgrade from the dashboard (Stripe Checkout) or see pricing. Entitlements appear on GET /api/v1/auth/me after checkout completes.
What's live today
We publish this list so marketing and documentation stay honest. If it is not here, it is on the roadmap — not a hidden upsell.
| Capability | Status |
|---|---|
| Email + password signup, login, logout, forgot/reset password | Live |
| Argon2id password hashing, Ed25519-signed session JWTs | Live |
| JWKS publication and local token verification (<1 ms, no outbound call) | Live |
| Organizations, roles, and permissions inside session tokens | Live |
| Hosted login/signup pages, setup wizard, JavaScript SDK | Live |
| Admin console, plan-gated audit logs API | Live |
| Stripe subscription checkout and webhook entitlement sync | Live |
gRPC AuthService for trusted internal callers | Live |
| Env-based branding + dashboard theme editor | Live |
| Google / GitHub OAuth (signup free; login SSO requires Pro) | Live when OAuth env vars are set |
| SAML / SCIM provisioning | Roadmap — entitlement reserved for Pro+ |
| Outbound lifecycle webhooks to your app | Roadmap |
| WASM edge sidecar, Elixir/Phoenix realtime mesh | Roadmap |
| WebAuthn / passkeys | Roadmap |
Deploy on Ratel
Ratel is the recommended way to put AuthForge online. Push the repo to GitHub, connect Ratel's GitHub App, and create a backend project with internal_port = 8080 and persistent = true.
The server ships the login UI, docs, and API from one process — after deploy, open /login.html on your domain for a live demo. Required secrets:
AUTHFORGE_PASSWORD_PEPPER— generate once withopenssl rand -base64 32AUTHFORGE_DATABASE_URL— Ratel managed Postgres +?sslmode=disableAUTHFORGE_CORS_ORIGINS— your front-end domain(s)
Full checklist: Configure AuthForge or RATEL_DEPLOY.md in the repository.
API reference
HTTP — auth (browser-facing)
| Method | Path | Description |
|---|---|---|
| POST | /api/v1/auth/signup | Create account → session token + entitlements |
| POST | /api/v1/auth/login | Authenticate → session token + entitlements |
| POST | /api/v1/auth/logout | Clear session cookie / revoke refresh token |
| POST | /api/v1/auth/forgot-password | Request password reset email (always 200) |
| POST | /api/v1/auth/reset-password | Set new password with reset token |
| GET | /api/v1/public/branding | Merged login branding (?org=slug optional) |
| GET | /api/v1/public/auth-config | Enabled OAuth providers + defaults |
| GET | /api/v1/auth/oauth/:provider/start | Redirect to Google/GitHub (?mode=login|signup) |
| GET | /api/v1/auth/oauth/:provider/callback | OAuth callback → session cookie → dashboard |
| GET/PATCH | /api/v1/orgs/:slug/theme | Per-org login theme (owner to PATCH) |
| GET | /api/v1/auth/me | Current identity, plan, organizations (Bearer or cookie) |
| GET | /api/v1/audit-logs | Plan-gated audit history (Pro+) |
HTTP — public
| Method | Path | Returns |
|---|---|---|
| GET | /api/v1/jwks.json | The JWKS (public signing keys). |
| GET | /healthz | Liveness probe. |
| GET | /readyz | Readiness probe. |
| POST | /api/v1/billing/webhook | Stripe webhook (signature verified) |
HTTP — admin (superadmin only)
| Method | Path | Description |
|---|---|---|
| GET·POST | /api/v1/admin/users | List / create users (paginated) |
| PATCH·DELETE | /api/v1/admin/users/:email | Update plan, admin flag, status, or delete |
| GET | /api/v1/admin/audit | Platform audit log (paginated) |
gRPC — trusted (local mesh)
Service authforge.auth.v1.AuthService exposes two routes:
AuthenticateUser(email, password, organization_context)→ a signed session token, a refresh token, expiry, and the resolved identity (user id, organizations, roles, permissions).ValidateSession(session_token)→valid, the resolved identity, and expiry. Pure cryptography — no database touch.
The full contract is the auth_service.proto file in the repository; generate a client in any language with your usual gRPC tooling.
Security & rotation
AuthForge is secure by default. Highlights:
- Passwords are hashed with Argon2id (tuned to OWASP) and an optional pepper, so a stolen database is not enough to recover them.
- Sessions are Ed25519-signed and carry expiry, not-before, issuer, and audience — all enforced on validation.
- Refresh tokens are 256-bit random secrets, stored only as digests and compared in constant time.
- Brute force is throttled per identity, and unknown-user and bad-password responses are identical to prevent account enumeration.
Key rotation is zero-downtime: drop a new key file into AUTHFORGE_KEY_DIR and point the primary marker at it. The previous key stays in the JWKS until its tokens expire, so nothing signed before the switch breaks.
Testing & hardening
Security claims are only worth what verifies them. AuthForge ships with an automated test suite and a continuous-integration gate:
- Cryptographic tests — sign/verify round trips, rejection of foreign keys, tampered tokens, expired tokens, wrong audience/issuer, and algorithm-confusion attempts.
- Credential tests — Argon2id round trips and pepper isolation.
- Handshake tests — end-to-end authenticate → validate, enumeration resistance, organization-scope enforcement, and brute-force lockout.
- Supply-chain gate — every change runs
cargo‑deny(advisories, licenses, banned and duplicate dependencies, source provenance) andclippywith warnings treated as errors.
See SECURITY.md in the repository for the full threat model and the disclosure process. Found a vulnerability? Follow our responsible-disclosure policy.
FAQ
Do I need a database to try it?
No. The quickstart runs with an in-memory demo store so you can exercise the full flow immediately. For production, connect PostgreSQL.
Where do my users' passwords go?
They are hashed with Argon2id inside your deployment and never leave it. We never see them — there is no AuthForge cloud in the path.
What happens if AuthForge restarts?
Signing keys are persisted to the key volume, so the same keys load on restart and existing sessions keep validating.
Is it really free?
The self-hosted Community tier is free forever, with no per-user fees. Paid tiers add support and enterprise controls — see Pricing.
How do I configure AuthForge for my website?
Open the setup wizard, enter your domain names, and copy the generated settings. The plain-language guide is at Set up for your website.
Can I customize the login page like Clerk?
Yes — three layers: environment variables for deployment-wide defaults, a dashboard theme editor for per-org overrides, or fork login.html / use the SDK for full white-label. See Brand your login.
Why pay for a self-hosted product?
The engine is free. Subscriptions buy support, legal documents, SLA-backed response, and server-side entitlements (like audit logs). See Plans & billing.
Do I need a separate server for the login page?
No. AuthForge serves the login UI, docs, and API from one process on port 8080 — including on Ratel.