2 releases

Uses new Rust 2024

0.0.2 Nov 2, 2025
0.0.1 Apr 9, 2019

#311 in HTTP server

Custom license

36KB
690 lines

OAuth Adapter for Rust Web Frameworks

A universal OAuth 2.0 adapter for Rust web frameworks, providing a single configuration model and framework-specific glue so you can expose compliant token endpoints without duplicating logic.

Status: This crate is still in active development. The API described below represents the intended shape of the crate and may change before the first stable release.

Highlights

  • Framework agnostic support for Axum, Warp, Actix-web, and Rocket
  • Shared OAuthConfig builder for consistent client credentials and token settings
  • Pluggable token store interface for Redis, SQL, or in-memory implementations
  • Opinionated defaults with escape hatches for custom validation and token generation

Notice

⚠️ This crate is in early development. For production use, consider oauth2 as a mature alternative solution.

Installation

Add the crate to your Cargo.toml, enabling the integration you need:

[dependencies]
oauth = { version = "0.1.0", default-features = false, features = ["axum"] }

Available feature flags: axum, warp, actix, rocket. Combine them if you support multiple frameworks in the same binary.

Configuration At A Glance

Create an OAuthConfig once and share it across the adapters you enable:

use oauth::OAuthConfig;

let config = OAuthConfig::builder()
    .client_id("your-client-id")
    .client_secret("your-client-secret")
    .issuer("https://auth.example.com")
    .access_token_ttl(std::time::Duration::from_secs(3600))
    .refresh_token_ttl(std::time::Duration::from_secs(7 * 24 * 3600))
    .enable_refresh_tokens(true)
    .build()
    .expect("valid OAuth configuration");

The builder validates required fields and returns a Result<OAuthConfig, ConfigError>. Keep the resulting value in an Arc if you need to clone it between routes or filters.

Custom Token Storage

To persist tokens outside the default in-memory store, implement TokenStore and attach it to the configuration:

use oauth::{OAuthConfig, TokenStore, TokenRecord};

struct CustomTokenStore;

impl TokenStore for CustomTokenStore {
    fn save(&self, token: TokenRecord) -> oauth::Result<()> {
        // Write to Redis, PostgreSQL, or another backend
        todo!("store token: {token:?}");
    }

    fn revoke(&self, token_id: &str) -> oauth::Result<()> {
        // Remove the token from your backend
        todo!("revoke token: {token_id}");
    }
}

let config = OAuthConfig::builder()
    .client_id("your-client-id")
    .client_secret("your-client-secret")
    .token_store(CustomTokenStore)
    .build()
    .expect("valid OAuth configuration with custom store");

Framework Quick Starts

Each framework-specific integration exposes a thin wrapper that turns an OAuthConfig into the appropriate route handler.

Axum

use std::sync::Arc;
use axum::{routing::post, Router};
use oauth::axum::OAuthHandler;
use oauth::OAuthConfig;

#[tokio::main]
async fn main() {
    let config = Arc::new(
        OAuthConfig::builder()
            .client_id("your-client-id")
            .client_secret("your-client-secret")
            .build()
            .expect("valid OAuth configuration"),
    );

    let oauth = OAuthHandler::from_config(config.clone());

    let app = Router::new().route("/oauth/token", post(oauth.token_endpoint()));

    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

Warp

use std::sync::Arc;
use oauth::warp::oauth_filter;
use oauth::OAuthConfig;
use warp::Filter;

#[tokio::main]
async fn main() {
    let config = Arc::new(
        OAuthConfig::builder()
            .client_id("your-client-id")
            .client_secret("your-client-secret")
            .build()
            .expect("valid OAuth configuration"),
    );

    let oauth_route = warp::path!("oauth" / "token")
        .and(oauth_filter(config.clone()));

    warp::serve(oauth_route)
        .run(([0, 0, 0, 0], 3000))
        .await;
}

Actix-web

use std::sync::Arc;
use actix_web::{App, HttpServer};
use oauth::actix::configure_oauth;
use oauth::OAuthConfig;

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let config = Arc::new(
        OAuthConfig::builder()
            .client_id("your-client-id")
            .client_secret("your-client-secret")
            .build()
            .expect("valid OAuth configuration"),
    );

    HttpServer::new(move || {
        App::new().configure(|cfg| configure_oauth(cfg, config.clone()))
    })
    .bind(("0.0.0.0", 3000))?
    .run()
    .await
}

Rocket

use std::sync::Arc;
use oauth::rocket::oauth_routes;
use oauth::OAuthConfig;
use rocket::launch;

#[launch]
fn rocket() -> _ {
    let config = Arc::new(
        OAuthConfig::builder()
            .client_id("your-client-id")
            .client_secret("your-client-secret")
            .build()
            .expect("valid OAuth configuration"),
    );

    rocket::build().mount("/", oauth_routes(config))
}

Supported OAuth 2.0 Grants

The adapter aims to cover the following grant types out of the box:

  • Client Credentials
  • Authorization Code (with PKCE support)
  • Refresh Token

Additional flows (Device Code, Resource Owner Password) are planned once the core API stabilizes.

Token Endpoint Contract

All integrations expose a standardized token endpoint that accepts JSON requests:

{
  "grant_type": "client_credentials",
  "client_id": "your-client-id",
  "client_secret": "your-client-secret",
  "scope": "read:payments write:payments"
}

Successful responses return RFC 6749-compliant JSON:

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "optional-refresh-token"
}

Contributing

We welcome pull requests and issues that help shape the API.

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit (git commit -m "feat: add amazing feature")
  4. Push (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

Distributed under the MIT License. See the LICENSE file for details.

Acknowledgements

  • Inspired by the need for a unified OAuth solution across Rust web frameworks
  • Built with ❤️ for the Rust community

Dependencies

~26–64MB
~1M SLoC