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. No Auth0 account, no per-user bill.
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.
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/auth/me | Current identity, plan, organizations (Bearer or cookie) |
| GET | /api/v1/audit-logs | Plan-gated audit history (Business+) |
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.
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.