The policy service returns shipping and refund rules on `GET /policies`. This example uses the Axum adapter. Actix Web, Rocket, Warp, and Poem share the same session core.

Clone [starters/rust](https://github.com/authdog/samples/tree/main/starters/rust). SDK reference: [Rust](/docs/backend/rust).

`require_auth` is the identity gate. A signed-in session is not a permission grant. Apply [authorization](/docs/concepts/authorization) after the gate.

## What you need

| Requirement | Detail |
| --- | --- |
| Public key | `pk_...` from the [console](https://console.authdog.com). Export `PK_AUTHDOG` |
| Secret key | Never put `sk_...` in the service |
| Package | `authdog-axum` is source-only. Clone [authdog/web-sdk](https://github.com/authdog/web-sdk) next to `authdog/samples` so `../../../web-sdk/packages/rust/axum` resolves. Do not `cargo add authdog-axum` from crates.io until a release exists. Rust 1.75+ |
| Request | Hosted sign-in stays in a browser. Call `/policies` with the `authdog-session` cookie or `Authorization: Bearer` |

## Run

```bash
export PK_AUTHDOG=pk_...
cargo run
```

Open http://127.0.0.1:3000. `curl -i http://127.0.0.1:3000/policies` with no session returns 401. With a valid session the body includes `pol_ship` (allow) and `pol_refund` (deny).

## Policies

```rust
// src/main.rs
let app = Router::new()
    .route(
        "/policies",
        get(|ctx: AuthContext| async move {
            Json(json!({
                "caller": ctx.user,
                "policies": [
                    {"id": "pol_ship", "name": "Shipping cutoff", "effect": "allow"},
                    {"id": "pol_refund", "name": "Refund window", "effect": "deny"},
                ]
            }))
        })
        .layer(middleware::from_fn(require_auth)),
    )
    .layer(middleware::from_fn_with_state(authdog.clone(), attach_session))
    .with_state(authdog);
```
