Skip to main content

Authentication

Version stamp

Applies to: renvor 0.0.0 · framework source 7d0816a · MSRV 1.94.0 · documentation set pre-release

This stamp is a single shared partial (docs/_stamp.mdx) imported by every prose page and the API reference. It binds this documentation snapshot to the immutable framework commit it describes. The framework remains unpublished and no release compatibility promise applies.

Not exposed through the facade

renvor-auth and renvor-auth-http are implemented and tested, but renvor does not depend on either crate. There is no published or supported installation path while the crates remain unpublished.

Domain first, transport second

renvor-auth names no router or status code. It owns subjects, credentials, sessions, tokens, authorization policies, abuse limits, and audit events. renvor-auth-http is the adapter that joins those operations to renvor-http; it implements no second copy of the policy decisions.

The HTTP adapter registers these routes:

RoutePurpose
POST /auth/registerRegister a credential without overwriting an existing account
POST /auth/loginEstablish an opaque cookie session
POST /auth/logoutRevoke the presented session
GET /auth/meRead the authenticated subject
POST /auth/verification/resendRequest another verification message
POST /auth/verification/confirmConsume a verification token
POST /auth/password/forgotAcknowledge recovery without revealing account existence
POST /auth/password/resetConsume a recovery token and replace the credential
POST /auth/token/refreshRotate a refresh token; present only with the tokens feature

Password and account guarantees

  • Password length is measured in Unicode code points after NFC normalization. The default range is 15–256, with no composition rule and no truncation.
  • Passwords are hashed with Argon2id using RFC 9106's second recommended parameter set.
  • Unknown-account and wrong-password login paths perform equal credential work; the contract does not claim constant execution time.
  • Duplicate registration cannot replace the existing credential.
  • Verification and recovery tokens are single-use and stored only as digests.
  • A delivery failure is visible to the operator without changing the response that could reveal whether an address has an account.

The session cookie is named __Host-rv_session and is emitted with Secure, HttpOnly, Path=/, and either SameSite=Lax or SameSite=Strict. SameSite=None is not representable. The server stores only a digest of the opaque identifier.

The default session policy is 30 minutes idle, 12 hours absolute, and a target bound of five live sessions. That last bound is enforced per login rather than atomically: two simultaneous logins can briefly leave six live sessions, and the next login corrects it. The configuration API refuses time windows outside its NIST AAL2 ceilings rather than silently clamping them. Cookie-authenticated unsafe requests require a CSRF token bound to the session; among the routes above, that currently means POST /auth/logout.

Policy, abuse control, and audit

Authorization is deny-by-default and enforced inside application operations. Anonymous callers, missing resources, insufficient scopes, and policy refusals all return one NotPermitted result, so the decision does not reveal whether a resource exists. Token scopes are checked before the policy at the same operation boundary.

Seven state-changing flows are abuse-bounded: registration, login, both verification operations, both password-recovery operations, and token refresh. The counter space has a finite row bound; logout and GET /auth/me are intentionally outside it because they only revoke or read the caller's own state.

Permit and refuse paths both write the same closed audit-event shape. The vocabulary contains no arbitrary text field, and a sink failure refuses the operation on either path. The included sink only records events for tests; Phase 010 owns production observability adapters.

Optional access and refresh tokens

The tokens feature enables signed JWT access tokens and opaque refresh tokens. The verifier owns the accepted algorithm; a token's header cannot select it. Keys come from a bounded local ring, and remote key URLs and critical extensions are refused.

Refresh rotation is one database transaction. A replay revokes the complete token family, and the family owns an immutable scope grant. The SQLx and SeaORM implementations run the same concurrency contract on PostgreSQL and MySQL.

Deliberate limits

  • A password reset revokes neither existing sessions nor refresh-token families.
  • Password rehash-on-login is not wired: needs_rehash has no production caller.
  • Signing keys have no rotation path; the Phase 009 threat model records this as unmitigated.
  • There is no route that issues the first access/refresh pair.
  • The included mail and audit sinks are deterministic recording sinks, not SMTP or production telemetry adapters.
  • No authentication UI or generator integration exists.
  • Persistence and authentication are not yet wired through the renvor facade.

These are retained limits, not hidden capabilities. The complete list is in the Phase 009 limitations record.