Sign-in
How people sign in (single sign-on, a directory password, or an e-mailed code), the first owner, the admin token and break-glass, who may sign in, passwords for one person, setting up e-mail, sessions.
| Way | For | Set up in |
|---|---|---|
| Single sign-on (OIDC) | Your identity provider: Entra ID, Okta, Ping, Keycloak, ADFS | Settings → How people sign in (SSO) |
| Directory password (LDAP) | LDAP or Active Directory, where no identity provider is reachable | The same |
| E-mailed code | Everyone else, and people added by hand | A mail provider: Resend or SMTP |
| A password | One person who can't receive a code | Team → Password (owners) |
Every tier has all of them. The admin token is not a way to sign in.
The first owner
A new install's sign-in page asks for the admin token (printed by the installer) and the first owner's e-mail, plus optionally a Resend key and the sender. That creates the owner, once:
curl -s -X POST -H "Authorization: Bearer $ADMIN_TOKEN" -H 'Content-Type: application/json' \
-d '{"email":"[email protected]","name":"Ana"}' $URL/v1/auth/bootstrapE-mailed codes
- The person enters their e-mail; 3AM sends a 6-digit code through the mail provider.
- They enter the code and get a session.
| Rule | |
|---|---|
| Codes | Valid 10 minutes, used once, 5 tries, at most 3 per address per 10 minutes; only a hash is stored |
| Unknown addresses | The same answer whether or not the address has access, and nothing is sent |
| Rate limits | 3 codes per address, 20 requests per client address, per 10 minutes |
The admin token
After the first owner, it has two uses:
- Automation:
Authorization: Bearer <admin token>works on the API (scripts, CI), attributed toadmin-token, with owner rights. - Break-glass: if codes can't be sent (no mail provider, or it refuses or is unreachable), the sign-in page offers
the token. Each use is logged (
identity.break_glass, with the reason), the console shows a banner until e-mail works, and the path closes when a send succeeds again.
Otherwise POST /v1/login with the token answers 403 use_email.
| Install | Where the token is |
|---|---|
| Single server | Printed by the installer once; in the data volume at admin-token |
| Kubernetes | kubectl -n bank-ops get secret threeam-admin -o jsonpath='{.data.token}' | base64 -d |
| Your own | THREEAM_ADMIN_TOKEN, or Helm adminToken.existingSecret |
Who may sign in
Only people an admin has added (or your directory's mapped groups) get in. On top of that, Team → Who may sign in
(PUT /v1/settings/access):
| Rule | Effect |
|---|---|
| Allowed domains | Only these domains (and subdomains). A new install starts with the first owner's domain, unless that's public webmail |
| Known disposable domains | 85 throwaway services (mailinator, yopmail, 10minutemail, …): always refused |
| Blocked domains / addresses | Whatever an admin adds |
| Block public webmail | Optional: Gmail, Outlook, Yahoo, iCloud, Proton and similar |
Enforced when someone is added, when a code is asked for and checked, and on every request of an open session: tightening the policy signs people now outside it out at once. A policy that would shut out every owner is refused.
A password, for one person
For a reviewer, an auditor or a guest with no mailbox on your domain:
- Who: anyone but an owner, and nobody from the directory. Only an owner gives, replaces or removes one.
- The password: 12+ characters (the console proposes one), shown once, kept as an scrypt hash, never in the log.
- An end: 7, 30 (default) or 90 days, or none. A session opened with it ends with it.
- Guessing: five wrong tries lock an address for 15 minutes; 30 tries from one client in 10 minutes are refused; every failure gets the same answer.
- Signing in: I was given a password on the sign-in page (
POST /v1/auth/password). Off when the install is single sign-on only.
Setting up e-mail
The sender must be on a domain the provider has verified (default 3AM <[email protected]>; set yours in Settings →
E-mail sign-in, Helm mail.from or THREEAM_MAIL_FROM). Resend's sandbox sender delivers only to the Resend account's
own address.
| Provider | Configure with |
|---|---|
| Resend | Installer --resend-key-file FILE; Helm mail.resendKeySecret; THREEAM_RESEND_KEY_FILE; or the console (first owner, or Settings). Saved to secrets/resend.key (0600), never returned |
| SMTP (SES, Postmark, SendGrid, Workspace, Microsoft 365, your relay) | Installer --smtp-host H [--smtp-port 587] [--smtp-user U --smtp-password-file F] [--smtp-security starttls|ssl|none]; Helm mail.smtp.*; THREEAM_SMTP_*; or the console. THREEAM_SMTP_HOST alone selects SMTP |
Send me a test e-mail (Settings) proves it before anyone needs a code. When the provider fails, nobody is locked out: break-glass opens until a send succeeds.
Sessions
A random 256-bit token, only its hash stored, kept in the browser tab's sessionStorage (gone when the tab closes). A
session ends after 12 hours idle or 7 days, at sign-out, or when the person is disabled or their role changes.
Every change is recorded under the signed-in person's e-mail; a by a page sends is ignored.
API
| Call | Who | Purpose |
|---|---|---|
POST /v1/auth/request {email} | anyone | Send a code |
POST /v1/auth/verify {email, code} | anyone | → {token, user} |
POST /v1/auth/password {email, password} | anyone | Sign in with a password |
POST /v1/auth/logout | signed in | End this session |
POST /v1/login {token} | anyone | The admin token: {bootstrap: true} on a new install, {break_glass: true} when mail fails, else 403 |
POST /v1/auth/bootstrap {email, name, resend_key?, mail_from?} | admin token | Create the first owner (once) |
GET/PUT /v1/settings/mail, POST /v1/settings/mail/test | viewer / admin | The provider and sender; test |
GET/PUT /v1/settings/access | viewer / admin | Who may sign in |
Audit events: identity.signed_in, identity.code_sent, identity.code_failed, identity.code_wrong,
identity.code_ignored, identity.code_refused, identity.code_rate_limited, identity.access_changed,
identity.break_glass, identity.token_sign_in_refused, identity.password_set, identity.password_removed,
identity.password_wrong, config.mail_saved, config.mail_tested.
Keyboard shortcuts
Every console shortcut. The command bar, search, going to any page with g, moving through lists, and the rules (Tab, Enter, Escape, arrows) every page follows.
Single sign-on
Sign in with your identity provider (OIDC, PKCE) or your directory (LDAP, Active Directory); group mappings to roles and teams; staying in step; mixed mode; how 3AM finds out your directory by itself.