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](https://github.com/authdog/web-sdk/tree/main/packages/rust), 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_...`):

```rust
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:

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

Each adapter resolves:

```rust
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:

```rust
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](/docs/concepts/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

- [Backend requests](/docs/backend)
- [Calling the REST API](/docs/api)
