OAuth 2.1 server implementation in Rust

Efren Yevale Varela 74cb5b38fa Updated documentation пре 4 дана
.cargo bbb5878e7d Cleared RUSTSEC пре 1 недеља
.clusterfuzzlite 923681da88 Changed memory-safety for fuzz пре 2 недеља
.config 7f3db91ac6 Hardened test пре 3 недеља
.github 74cb5b38fa Updated documentation пре 4 дана
.sqlx 35345f1021 Fixed bugs пре 2 недеља
.well-known 3e8f4d32d1 Security hardening пре 3 недеља
deploy 232be93493 Removed pin-digest пре 3 недеља
docs 74cb5b38fa Updated documentation пре 4 дана
fuzz 0aad5b36ee Added tests пре 1 недеља
migrations 9478660260 Added optionals пре 2 недеља
scripts 74cb5b38fa Updated documentation пре 4 дана
src 74cb5b38fa Updated documentation пре 4 дана
templates 7c50a23515 Initial commit пре 1 месец
tests b4b95f18a4 Fixed bugs and tests пре 1 недеља
.dockerignore 81769a4f70 Change cache handling пре 3 недеља
.gitignore e56c8c9010 Removed link пре 2 недеља
AGENTS.md 74cb5b38fa Updated documentation пре 4 дана
Cargo.lock bbb5878e7d Cleared RUSTSEC пре 1 недеља
Cargo.toml 35345f1021 Fixed bugs пре 2 недеља
Dockerfile 3ad38f73cc Updated components пре 3 недеља
LICENSE.md 7c50a23515 Initial commit пре 1 месец
README.md 74cb5b38fa Updated documentation пре 4 дана
SECURITY.md 3e8f4d32d1 Security hardening пре 3 недеља
compose.test.yaml 0d522a39e8 Migrated unit tests from per-test containers to shared test services пре 3 недеља
compose.yaml 35d12e87ee Updated database versions пре 3 недеља
deny.toml bbb5878e7d Cleared RUSTSEC пре 1 недеља
docker-bake.hcl 4197d93e0b Fixed image publishing пре 3 недеља
rust-toolchain.toml 7c50a23515 Initial commit пре 1 месец
rustfmt.toml 7c50a23515 Initial commit пре 1 месец

README.md

d-OAuth-Server

An OAuth 2.1-only authorization server written in Rust. It is deliberately not backwards compatible with OAuth 2.0: PKCE is mandatory, the implicit and resource-owner-password grants do not exist, bearer-in-query is rejected, and redirect URIs match exactly (with the RFC 8252 §7.3 loopback exception, which includes the host localhost only when allow_localhost_redirect is set).

It implements the authorization-code, refresh-token, client-credentials, device-code, and token-exchange grants, with DPoP, mTLS, PAR, JAR, dynamic client registration, client ID metadata documents, introspection, and revocation. Tokens are opaque and hashed at rest by default; a global enable switch plus a per-client jwt access-token format mints RFC 9068 at+jwt tokens verified against the AS JWKS. All durable domain state is in PostgreSQL and all ephemeral state is in Redis, so replicas are interchangeable. Administration is CLI plus declarative configuration: there is no HTTP admin API and no default credential.

Run it

A self-contained local stack, from the repository root. compose.yaml generates a throwaway TLS certificate and dev-only key files, applies migrations exactly once, and starts one replica against its own Postgres and Redis:

docker compose -f compose.yaml up --build
docker compose -f compose.yaml port app 8080   # host port of the TLS listener

The listener uses that self-signed certificate, so probe it with -k. The discovery document advertises the configured issuer (https://localhost:8080), independent of the random host port:

curl -sk https://127.0.0.1:<host-port>/.well-known/oauth-authorization-server | jq .

From a checkout, against a Postgres and a Redis of your own, with the development environment exported as in QUICKSTART.md:

cargo build --locked
cargo run --bin d-oauth-server -- config check
cargo run --bin d-oauth-server -- migrate
cargo run --bin d-oauth-server -- admin bootstrap --email admin@example.com
cargo run --bin d-oauth-server -- serve
curl -s http://127.0.0.1:8081/health/live
curl -s http://127.0.0.1:8081/health/ready

That is the short version. The full first-run path, including creating a client and minting an access token with PKCE, is QUICKSTART.md.

Documentation

Comprehensive guides live in docs/, whose index maps every guide by audience and reading order.

I want to... Start with
Run it, end to end, with a token QUICKSTART.md
Look up a configuration key CONFIGURATION.md
Administer a live install OPERATIONS.md, RUNBOOK.md
Deploy it to a cluster DEPLOYMENT.md
Integrate an OAuth client OAUTH.md
Protect an API (resource server) RS-CONTRACT.md
Understand or change the code ARCHITECTURE.md, CONTRIBUTING.md
Review the security properties SECURITY.md
Inspect the schema or the Redis keys DATABASE.md, REDIS.md
See what changed in a release CHANGELOG.md

To report a vulnerability, use the reporting policy, not a guide.

Before production

  • There is no default credential and no HTTP admin API. Provision through the CLI or a migration Job (RUNBOOK.md).
  • The token pepper, TOTP encryption key, and PII field-encryption key are required, must each be at least 32 bytes (WeakKeyMaterial otherwise), and are live secrets: losing the pepper invalidates every opaque token, and losing the PII key makes the sealed directory unreadable. Mount them as files, not environment values (DEPLOYMENT.md).
  • Production requires an https issuer and, unless database.require_verify_full is set false, a database URL with sslmode=verify-full.
  • Redis must run with noeviction and persistence; the server asserts both at startup and refuses to start otherwise (REDIS.md).
  • Security endpoints fail closed: when Postgres or Redis is unavailable they return 503 rather than failing open. CORS is empty by default, so browser clients need an explicit origin allowlist.

The threat model and the full invariant list are in SECURITY.md.

Tests

cargo nextest run --all-targets is the authoritative suite, backed by the shared Postgres and Redis from compose.test.yaml; cargo test --doc covers the doctests. The quality gates, the coverage floors, the fuzzing targets, and the exact commands are in CONTRIBUTING.md, with the measured baseline in TEST-COVERAGE.md.

License

ISC. See LICENSE.md.