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_HOSTSentries. - Logout handlers clear the local cookie and sanitize
redirect_uri; they do not revoke bearer tokens or end an upstream provider session.