oauth2-rs

An extensible, strongly-typed Rust implementation of the OAuth2 protocol (RFC 6749) with PKCE, introspection, revocation, and device flow support.

Library
Cargo
v5.0.0
1,203stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
47/100Fair
Development Activity4
Maintenance32
Community64
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
78/100Good
Architecture82
Code Quality80
Innovation85
Learning Curve65

oauth2 is a Rust crate that implements OAuth2 (RFC 6749) with strong typing throughout: client IDs, secrets, tokens, scopes, and CSRF values are each distinct wrapper types instead of interchangeable strings, so mixing up parameters becomes a compile-time error rather than a runtime bug. It supports every major grant type — Authorization Code with PKCE, Implicit, Resource Owner Password Credentials, Client Credentials, and Device Authorization Flow — plus token introspection (RFC 7662) and revocation (RFC 7009).

The HTTP transport layer is pluggable: reqwest (sync and async) is enabled by default, with optional curl and ureq backends, or a fully custom client via the SyncHttpClient/AsyncHttpClient traits. It compiles to wasm32 for browser use and is battle-tested as the foundation of the openidconnect crate for OIDC/SSO flows.

What You Get

  • Authorization Code Grant with PKCE, Implicit, Resource Owner Password Credentials, Client Credentials, and Device Authorization Flow grant types
  • Strongly-typed protocol values (ClientId, ClientSecret, CsrfToken, PkceCodeChallenge, RedirectUrl, Scope, AccessToken) that prevent parameter mixups at compile time
  • Pluggable HTTP client backends — reqwest (sync/async, default), curl, ureq, or a custom sync/async client via trait implementation
  • Token introspection (RFC 7662) and token revocation (RFC 7009) support built in
  • Optional constant-time secret comparison via the timing-resistant-secret-traits feature to avoid timing side-channels
  • wasm32-unknown-unknown target support for browser-based OAuth2 flows

Common Use Cases

  • Implementing “Login with GitHub/Google/Microsoft” authorization-code-with-PKCE flows in a Rust web application
  • Building CLI tools that authenticate via the Device Authorization Flow (no local browser redirect needed)
  • Machine-to-machine service authentication using the Client Credentials grant
  • Building an OpenID Connect / SSO layer on top, as the openidconnect crate does

Under The Hood

Architecture The crate centers on a generic Client<TE, TR, TIR, RT, TRE> type in client.rs (~1,280 lines) parameterized over token, error, and revocation response types, built with a type-state/builder pattern so a client configured for one grant flow can’t be misused for another. Protocol values live in types.rs (~665 lines) as distinct newtypes (ClientId, ClientSecret, CsrfToken, PkceCodeChallenge, etc.), each with its own Serialize/Deserialize implementation. Transport is abstracted through SyncHttpClient/AsyncHttpClient traits in endpoint.rs, with concrete adapters in separate feature-gated modules (reqwest_client.rs, curl_client.rs, ureq_client.rs). This layering means the core Client generics, the protocol newtypes, and the transport adapters can evolve somewhat independently, though changing the core generic signature ripples through every backend adapter and the basic:: convenience module.

Tech Stack A Rust 2021-edition crate with MSRV 1.71, built on serde/serde_json for (de)serialization (with serde_path_to_error for precise JSON error locations), url and http for protocol types, sha2 and rand for PKCE challenge/verifier generation, thiserror for typed errors, and chrono for token expiry timestamps. HTTP backends are all optional/feature-gated (reqwest default, curl, ureq), with a getrandom/js feature for the wasm32 target. A sibling workspace crate, oauth2-reqwest, adds support for reqwest 0.13. CI runs the full matrix against Rust 1.71 (MSRV, pinned via a committed Cargo-1.71.lock), stable, beta, and nightly, plus a wasm32-unknown-unknown cross-compile.

Code Quality Tests live inline as src/tests.rs and src/token/tests.rs following the standard Rust #[cfg(test)] convention; error handling is centralized in a thiserror-derived RequestTokenError enum (error.rs) rather than panics. CI runs cargo test --tests --examples plus doc tests across all four Rust channels and installs clippy/rustfmt components. The crate enforces #![warn(missing_docs)] on every public item, and its extensive doc comments include runnable doctest examples for each grant type — an unusually high documentation bar for a Rust library of this size.

API Design The standout design choice is exhaustive type-state and newtype typing: every protocol parameter (client id, secret, CSRF token, PKCE verifier, redirect URL, scope) is its own type, and the Client itself is generic over sync-vs-async transport chosen at compile time via marker traits. This turns classic OAuth2 client bugs — passing a CSRF token where a PKCE verifier belongs, or mixing sync and async calls — into compile errors instead of runtime failures, which is unusually rigorous compared to the loosely-typed OAuth2 clients common in other language ecosystems. The opt-in timing-resistant-secret-traits feature is a deliberate, documented security/ergonomics tradeoff exposed directly in the public API.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search