中文文档 · Documentation · Quick start · Security
Nazo Auth Server is a self-hosted OAuth 2.x / OAuth 2.1-aligned and OpenID Connect authorization server written in Rust. It is built for same-origin deployments where the issuer, browser UI, passkeys, CORS, cookies, and protocol endpoints share one public origin.
The project includes the authorization server, a compact identity/admin surface, local signing key management, WebAuthn/passkeys, MFA, SCIM, and Rust resource-server verification libraries. Modular external-provider login is tracked in the future roadmap rather than advertised as a current default capability. It uses PostgreSQL for durable state and Valkey for short-lived protocol state.
NazoAuth predates OpenAI Build Week. The hackathon submission covers only the
work completed after the submission period opened at
2026-07-13T16:00:00Z. The last pre-period commit is
ef7df3e,
and the complete review range is
ef7df3e..main.
During the submission period, Codex with GPT-5.6 helped turn the existing server into a modular Rust workspace, implement OpenID4VC Final issuer and verifier roles, add FAPI-CIBA mTLS/ping and RFC 9967 SCIM security-event delivery, and harden the browser client and onboarding flow. Codex accelerated repository audits, implementation, tests, specification cross-checks, CI diagnosis, and deployment verification. The maintainer chose the product and security boundaries, required standards-first behavior instead of suite-specific shortcuts, reviewed the changes, and controlled deployment and merge decisions.
See the Build Week engineering record for the before/after boundary, dated pull requests, measured change volume, Codex collaboration details, setup instructions, and a no-rebuild public test path. The live demo is available at https://auth.nazo.run/ui/auth.
| Item | Value |
|---|---|
| Package | nazo-oauth-server |
| Workspace version | 0.1.9 release candidate |
| License | AGPL-3.0-or-later |
| Language | Rust 2024 |
| Runtime services | PostgreSQL, Valkey |
| Conformance test issuer | operator-provided public HTTPS origin |
| Default deployment model | same-origin |
Project quality is tracked through direct, auditable checks rather than a composite score:
| Signal | Evidence |
|---|---|
| Rust quality gate | cargo fmt --check, cargo check --workspace --all-targets --all-features --locked, cargo clippy -D warnings, migrations, and the complete workspace test suite in code-quality. |
| Static security analysis | CodeQL Rust analysis with the security-extended query suite. |
| Dependency policy | GitHub dependency review, cargo audit, and cargo deny over advisories, bans, licenses, and sources. |
| Runtime security behavior | Real HTTP E2E, load/race gate, and Valkey outage injection in conformance-security. |
| External protocol conformance | NazoAuthCtl owns signed Suite artifacts, external execution, evidence, and cleanup. The server is exercised only through its public protocol and tenant-resource interfaces. |
| Coverage trend | Codecov LCOV upload from the dedicated coverage workflow. |
| Release provenance | CycloneDX SBOM, Trivy image scan, Sigstore signing, and GitHub artifact attestations. |
📚 Standards and profile support
🏅 External Suite conformance is orchestrated by NazoAuthCtl.
- Authorization code + PKCE, refresh tokens, client credentials, bounded JWT bearer grant, bounded Token Exchange, revocation, introspection, signed/encrypted introspection, discovery, protected resource metadata, JWKS, JSON/signed/encrypted UserInfo, signed/encrypted JARM, PAR, JAR, DPoP, and mTLS.
- Runtime profiles:
oauth2-baseline,fapi2-security,fapi2-message-signing-authz-request,fapi2-message-signing-jarm, andfapi2-message-signing-introspection. - Local users, profiles, OAuth clients, grants, access requests, TOTP MFA, backup codes, remembered MFA, WebAuthn/passkeys, and SCIM provisioning.
- Local signing key lifecycle with prepublish, active, grace, and retired states. External-command signing is available for KMS/HSM integrations.
- Framework-independent Rust resource-server verifier plus the project's Actix HTTP integration. Historical Axum/Tower and tonic adapters are not shipped.
- Release security workflows for CodeQL, dependency review, cargo audit, cargo deny, SBOM generation, Trivy image scanning, keyless signing, and provenance attestations.
Install the independently signed nazoauthctl from
nazozero/NazoAuthCtl. Controller
source, CI, installation, and Releases now live only in that repository; the
NazoAuth v0.1.20 tag retains the pre-removal source as a review and rollback
point. See the repository split boundary,
then run:
sudo nazoauthctl install --runtime auto
sudo nazoauthctl bootstrap-admin
sudo nazoauthctl status
sudo nazoauthctl doctorauto selects Podman first and Docker second. The controller generates private
PostgreSQL and Valkey credentials, starts both services, runs a signed one-shot
migration task, and starts NazoAuth. There are no published default passwords.
Open http://127.0.0.1:8000/health or
http://127.0.0.1:8000/.well-known/openid-configuration. Data, signing keys,
generated application secrets, and avatars are persistent.
On a database without an administrator, nazoauthctl bootstrap-admin reads the
runtime-owned one-time claim without printing it. Interactive use prompts on a
TTY; automation supplies the closed credential document through stdin or a
dedicated file descriptor. The token, credentials, and any token-bearing URL
never enter argv, ordinary environment variables, logs, or audit records.
For a public issuer, pass --public-url https://auth.example.com; see the
deployment guide for TLS ingress requirements.
compose.yml remains a source-tree development sandbox and uses a development
operator identity; it is not the production lifecycle boundary.
For a direct binary run, server creates a local .env.yaml when absent,
generates persistent application secrets, creates signing keys when needed,
and continues starting. Schema changes are deliberately owned by the host-side
controller and are never attempted by the managed server runtime:
nazoauth serverExplicit YAML and environment values still take precedence. Managed deployments
run schema changes only through sudo nazoauthctl migrate --yes, which issues a
short-lived signed task to the exact verified release target.
Configuration is intentionally small for new deployments:
BIND: "0.0.0.0:8000"
PUBLIC_BASE_URL: "https://auth.example.com"
TRANSPORT_MODE: "trusted-proxy"
TRUSTED_PROXY_CIDRS: "127.0.0.1/32"
MTLS_CERTIFICATE_SOURCE: "disabled"
DATABASE_URL: "postgresql://nazo_oauth:<password>@postgres:5432/oauth"
VALKEY_URL: "redis://valkey:6379/0"
DATA_DIR: "/var/lib/nazo_oauth"
RUST_LOG: "info"For standalone HTTPS without a reverse proxy, select TRANSPORT_MODE: "direct-tls" and configure the server certificate, private key, mTLS client CA,
and dedicated mTLS listener described in
docs/operations/configuration.md.
CLIENT_SECRET_PEPPER, the DCR initial-access token, and a pairwise-subject
secret when required are generated under DATA_DIR/secrets if absent.
Back up that directory with the database. A missing or malformed persisted
secret fails startup instead of being silently replaced.
New deployments use composable server capabilities and explicit per-client
policy. AUTHORIZATION_SERVER_PROFILE is retained only as a compatibility
preset for clients that predate stored client policy.
PUBLIC_BASE_URL drives the same-origin defaults:
| Value | Default rule |
|---|---|
ISSUER |
PUBLIC_BASE_URL |
FRONTEND_BASE_URL |
PUBLIC_BASE_URL + "/ui/" |
CORS_ALLOWED_ORIGINS |
origin of PUBLIC_BASE_URL |
COOKIE_SECURE |
true for HTTPS issuers |
PASSKEY_ORIGIN and PASSKEY_RP_ID |
derived from issuer |
PROTECTED_RESOURCE_IDENTIFIER |
ISSUER + "/fapi/resource" |
DATA_DIR drives persistent local file paths:
| Value | Default rule |
|---|---|
JWK_KEYS_DIR |
DATA_DIR + "/keys" |
AVATAR_STORAGE_DIR |
DATA_DIR + "/avatars" |
Advanced settings cover specialized deployments. They are documented in docs/operations/configuration.md.
Stable, non-conflicting server handlers are active together on new databases.
This includes signed Request Objects, JARM, Device Grant, CIBA poll/ping, the
bounded Token Exchange and JWT Bearer Grant profiles, SCIM, Front-Channel
Logout, and Session Management. Server support does not grant a client access:
grant allowlists, registered metadata, sender constraints, and the versioned
per-client security_policy still fail closed.
The following capabilities remain conditional or excluded:
- Dynamic Client Registration / RFC 7591 and Client Configuration Management
/ RFC 7592 require a configured
DYNAMIC_CLIENT_REGISTRATION_INITIAL_ACCESS_TOKEN. - OpenID4VCI, OpenID4VP, SCIM Security Events, Native SSO, RAR, and experimental HTTP Signatures require their complete role-specific prerequisites.
- External-token, refresh-token, or ID-token Token Exchange profiles.
- Modular third-party login providers such as QQ, WeChat, Google, Microsoft, or enterprise SAML; these are roadmap items until provider-specific adapters, configuration gates, account linking, and E2E/negative tests exist.
- Request-level dynamic tenant or issuer routing.
- RFC 9701 encrypted introspection responses outside the signed-introspection profile, or without per-client JWE response metadata.
- UserInfo or JARM encryption without supported per-client JWE metadata and a unique matching public encryption key.
See docs/project/roadmap.md for the current scope record.
cargo fmt --check
cargo check --workspace --all-targets --all-features --locked
cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
cargo test --workspace --all-features --lockedHTTP and concurrency checks:
python scripts/full_real_request_e2e.py
python scripts/full_real_request_load.pyCoverage runs are documented in docs/coverage/codecov-docker-runbook.md.
The public source code is licensed under AGPL-3.0-or-later. This applies equally to individuals and organizations. A separate commercial license may be available for qualifying closed-source use, but is granted only by a signed agreement with the applicable copyright holders. See COMMERCIAL-LICENSE.md and CONTRIBUTING.md.
