Authdog

Rust

Last updated Jul 19, 2026CI passing
View as Markdown

Authdog's Rust source provides a shared session core and adapters for axum, actix-web, Rocket, warp, and Poem.

Availability

Unreleased: authdog-core, authdog-axum, authdog-actix, authdog-rocket, authdog-warp, and authdog-poem are not available on crates.io. Commands such as cargo add authdog-axum will fail.

Current code is source-only in the `packages/rust` workspace, versioned 0.1.0. Vendor or pin a repository commit and use Cargo path dependencies from that checkout. Do not rely on the unshipped crates.io version declarations in its manifests.

The workspace targets Rust 1.75+ and edition 2021. Current manifests integrate axum 0.8, actix-web 4, Rocket 0.5, warp 0.3, and Poem 3. Published compatibility and semver stability are not yet guaranteed.

Configure

Every adapter exports Authdog. Create one instance from your environment's public key (pk_...):

let authdog = Authdog::new(&std::env::var("PK_AUTHDOG")?)?;

The key is safe to expose. Construction rejects malformed keys and identity hosts outside the trusted HTTPS allowlist. A custom reqwest::Client can supply timeout, transport, and observability policy:

let authdog = Authdog::builder(&pk).http_client(client).build()?;

Each adapter resolves:

AuthContext {
    token: Option<String>,
    user: Option<serde_json::Value>,
    is_authenticated: bool,
    user_info: Option<UserInfoResponse>,
}

Resolution prefers the authdog-session cookie, then reads Authorization: Bearer <token>. Missing, invalid, or failed OIDC userinfo requests produce anonymous context. Only meta.code == 200 with a user sets is_authenticated.

Authdog::builder(&pk).fetch_user(false).build() only exposes the unverified token. user and user_info remain None, and is_authenticated remains false. Every built-in guard therefore rejects it; use this mode only when separate server-side validation and enforcement replace Authdog's gate.

Framework integration

Framework Optional session Authentication boundary Setup
axum AuthContext extractor after attach_session require_auth middleware Add state and from_fn_with_state(..., attach_session); layer guard on protected routes
actix-web AuthContext extractor RequireAuth extractor Register web::Data<Authdog>
Rocket AuthContext request guard RequireAuth guard Manage Authdog; register unauthorized catcher for JSON 401
warp with_session(authdog) filter require_auth(authdog) filter Recover Unauthorized with recover_unauthorized
Poem AuthContext extractor RequireAuth extractor Attach Authdog with .data(authdog)

Example axum wiring:

use authdog_axum::{attach_session, require_auth, AuthContext, Authdog};
use axum::{middleware, routing::get, Router};

let authdog = Authdog::new(&std::env::var("PK_AUTHDOG")?)?;
let app = Router::new()
    .route("/me", get(|ctx: AuthContext| async move { format!("{:?}", ctx.user) })
        .layer(middleware::from_fn(require_auth)))
    .layer(middleware::from_fn_with_state(authdog.clone(), attach_session))
    .with_state(authdog);

Security boundaries

  • Optional context is informational; each framework's guard above is the authentication boundary.
  • Authentication does not grant application permissions. Apply authorization separately.
  • Bearer tokens are sent only to a trusted HTTPS identity host. Self-hosted hosts require explicit AUTHDOG_ALLOWED_IDENTITY_HOSTS entries.
  • Logout handlers clear the local cookie and sanitize redirect_uri; they do not revoke bearer tokens or end an upstream provider session.

Next steps

Learn more