Skip to main content

Module auth

Module auth 

Source
Expand description

Identity for isb serve: users, org memberships and roles, browser sessions, invitations, API tokens and password resets, in SQLite at <state>/isb.db.

  • Orgs are the trust boundary. A user is a member of an org with a Role; what a role may do is the table in Role::permissions, so roles can be refined without touching the callers. A platform admin spans orgs.
  • Every bearer secret (session, API token, invitation, reset) is 32 random bytes shown once; only its SHA-256 is stored (secret).
  • Passwords are argon2id. Login failures never say which half was wrong, cost the same either way, and are rate-limited per email and per IP.
  • The HTTP endpoints are in http; the CLI uses this API directly on the same file (SQLite in WAL mode handles the daemon and the CLI at once).

External sign-in (oauth) attaches rows to user_identities; passkeys (webauthn) live in passkeys; external manages both.

Re-exports§

pub use superadmin::Superadmin;
pub use superadmin::SuperadminSource;
pub use superadmin::SuperadminToken;

Modules§

agent_identities
Agent identities: tailnet and Cloudflare Access callers an org lets in as its agents, each mapped to a role in that one org.
cbor
A minimal CBOR (RFC 8949) decoder for WebAuthn: attestation objects and COSE keys. Definite lengths only (CTAP2 canonical encoding never uses indefinite ones), nesting capped, every length checked against the input before anything is allocated. Floats are skipped over, not interpreted.
db
The identity database: SQLite in WAL mode, schema migrations recorded in schema_version.
edge
Edge identities: the person a front door already verified. On a tailnet listener that is tailscaled’s whois of the real socket peer; behind Cloudflare Access it is a verified Cf-Access-Jwt-Assertion. Who resolves a request to one is the daemon’s gate; this module is what the identity endpoints make of it.
external
Ways in besides a password: external identities (OAuth/OIDC) and passkeys, and the rules that tie them to users.
http
The identity endpoints under /api/v1/auth/, JSON in and out, as a router isb serve mounts on its TCP listener next to /mcp and /healthz.
limit
An in-memory token bucket per key (an email, an IP), to blunt password guessing. It resets when the daemon restarts, which is fine: the point is to make online guessing slow, and a restart is rare and visible.
oauth
External sign-in providers: GitHub (OAuth 2.0), Google and generic OpenID Connect, all with the authorization code flow, PKCE (S256), and a state value bound to the browser that started the flow (see super::http).
oidc
OpenID Connect pieces: the discovery document, JWKS parsing, and ID token verification (RS256 and ES256 with ring).
ops
Account operations judged against a Principal: who is in an org, invitations, API tokens, SSH keys, sessions and users. The identity endpoints (super::http) and the daemon’s account tools (member_list, token_create, …) both call these, so a rule holds the same on every surface. Answers are the JSON the endpoints return.
secret
Secrets: bearer tokens, their hashes, constant-time comparison, and argon2id password hashes.
ssh_keys
SSH public keys on isb accounts: what isb ssh-proxy lets into an instance (docs/guides/ssh.md).
superadmin
Superadmins: the unix socket’s reach (every tool, no remote-spec policy, any instance) for an HTTP caller. Three sources grant it, and nothing else:
webauthn
WebAuthn (passkeys), verified directly: CBOR from super::cbor, signatures from ring. Implemented here rather than with a crate because the common Rust WebAuthn crate is MPL-2.0.

Structs§

Accepted
What accepting an invitation did.
ApiToken
An API token’s metadata.
AuthConfig
Lifetimes, cost and rate limits.
AuthStore
The identity store. Cheap to share behind an Arc; one connection behind a mutex (requests are short, and argon2 runs outside the lock).
Invitation
LoginMeta
Where a login came from, kept on the session for the user to review.
Membership
NewApiToken
NewInvitation
NewSession
A session just created: the token is in hand only now.
Principal
An authenticated caller: who, how, and what they may reach. For an org-scoped token, orgs is that one org and platform_admin is false whatever the user is.
Session
A browser session. expires_at is the absolute limit; it also ends when unused for the configured idle time (Session::idle_expires_at).
User
A user, without the password hash (which never leaves the store).

Enums§

AuthError
What the identity store can fail with. AuthError::InvalidCredentials is deliberately vague: it is the answer to every failed login.
Permission
Something a role allows within its org.
PrincipalKind
How a principal authenticated.
Role
A role in an org. Ordered by reach: an actor may grant roles up to its own.
Scope
What an API token may do on top of its role. A token with no scopes has the role’s whole reach (agents administer their org by default); scopes only ever narrow it.

Constants§

WORKSPACE_ACTOR
How audit rows, history and isb.owner labels name a workspace.

Functions§

db_path
The identity database under a daemon state directory.
normalize_email
Trimmed, lowercased, and plausibly an address. Not RFC 5322: the address is a login name and an invitation target, not something isb parses.

Type Aliases§

AuthResult
Clock