authvault 0.1.0

Authentication and authorization vault with multi-provider support
Documentation
---
title: Middleware Adapter Integration
---

# Middleware Adapter Integration

`AuthvaultMiddlewareAdapter` is the Axum/Tower layer that turns an incoming `Authorization: Bearer ...`
header into request-scoped `Claims`.

The adapter:

- extracts the bearer token from `Authorization`
- validates the token with `Authenticator::validate_bearer_token`
- inserts `Claims` into the request extensions on success
- returns a `401` JSON response when validation fails

## Tracera Wiring

Use the layer directly on the router or service stack and extract `Claims` from request extensions.

```rust
use axum::{extract::Extension, routing::get, Router};
use authvault::{AuthvaultMiddlewareAdapter, Authenticator, Claims, UserId};
use std::sync::Arc;

async fn whoami(Extension(claims): Extension<Claims>) -> String {
    claims.user_id().to_string()
}

let authenticator = Arc::new(Authenticator::new("tracera-secret"));
let auth_layer = AuthvaultMiddlewareAdapter::from_shared(Arc::clone(&authenticator));

let app = Router::new()
    .route("/whoami", get(whoami))
    .layer(auth_layer);
```

For a protected route, the handler can trust that `Claims` is present because the middleware returns
`401` before the request reaches the handler.

## AgilePlus Wiring

AgilePlus can use the same adapter in front of internal API routes without duplicating validation code.

```rust
use axum::{extract::Extension, response::IntoResponse, routing::post, Router};
use authvault::{AuthvaultMiddlewareAdapter, Authenticator, Claims};
use std::sync::Arc;

async fn create_task(Extension(claims): Extension<Claims>) -> impl IntoResponse {
    format!("task created for {}", claims.sub)
}

let authenticator = Authenticator::new("agileplus-secret");
let app = Router::new()
    .route("/tasks", post(create_task))
    .layer(AuthvaultMiddlewareAdapter::new(authenticator));
```

If the consumer prefers to build layered stacks, the adapter also works with `tower::ServiceBuilder`.

```rust
use authvault::{AuthvaultMiddlewareAdapter, Authenticator};
use tower::ServiceBuilder;

let auth_layer = AuthvaultMiddlewareAdapter::new(Authenticator::new("shared-secret"));
let stack = ServiceBuilder::new().layer(auth_layer);
```

## Error Shape

Invalid or missing credentials return a `401` JSON body such as:

```json
{
  "error": "unauthorized",
  "message": "invalid bearer token"
}
```

That response shape is intentionally minimal so consumer repos can map it into their own error
handling or observability pipeline.