Files
auth-kit/README.md
2026-02-02 14:30:53 +08:00

125 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# auth-kit
`auth-kit` 是一个可复用的认证/多租户中间件库Rust + Axum用于在多个微服务中统一实现
- JWT 认证:从 `Authorization: Bearer <token>` 解析并验证 token注入 `AuthContext`
- 租户隔离:从 `X-Tenant-ID` 解析租户并注入 `TenantId`,并在同时存在 token 与 header 时强制一致性
该 crate 不包含任何业务逻辑、数据库访问或 RBAC 聚合,仅提供“请求上下文注入 + 类型提取器 + JWT 验证能力”。
## 依赖与约定
- Web 框架Axum
- 统一错误类型:`common_telemetry::AppError`
- 头部约定:
- `Authorization: Bearer <access_token>`
- `X-Tenant-ID: <tenant_uuid>`
## 快速开始(在 Axum 中挂载)
推荐链路顺序:
1. `authenticate_with_config`(注入 `AuthContext`
2. `resolve_tenant_with_config`(注入 `TenantId`,并校验 header tenant 与 token tenant 一致)
示例:
```rust
use axum::{Router, middleware::from_fn_with_state};
use auth_kit::middleware::{
auth::{self, AuthMiddlewareConfig},
tenant::{self, TenantMiddlewareConfig},
};
let auth_cfg = AuthMiddlewareConfig {
skip_exact_paths: vec!["/healthz".to_string()],
skip_path_prefixes: vec!["/scalar".to_string()],
jwt: auth_kit::jwt::JwtVerifyConfig::rs256_from_jwks(
"iam-service",
"http://127.0.0.1:3000/.well-known/jwks.json",
)?,
};
let tenant_cfg = TenantMiddlewareConfig {
skip_exact_paths: vec!["/healthz".to_string()],
skip_path_prefixes: vec!["/scalar".to_string()],
};
let app = Router::new()
.layer(from_fn_with_state(tenant_cfg, tenant::resolve_tenant_with_config))
.layer(from_fn_with_state(auth_cfg, auth::authenticate_with_config));
```
## Handler 中如何使用(类型注入)
### AuthContext
`AuthContext` 会从 request extensions 中提取,如果中间件未运行或缺失认证信息,会返回 `AppError::MissingAuthHeader`
```rust
use auth_kit::middleware::auth::AuthContext;
pub async fn handler(AuthContext { user_id, tenant_id, .. }: AuthContext) {
// ...
}
```
### TenantId
`TenantId` 可从 request extensions 中提取;若不存在,会尝试从 `X-Tenant-ID` 解析;缺失则返回 `AppError::BadRequest("Missing X-Tenant-ID header")`
```rust
use auth_kit::middleware::tenant::TenantId;
pub async fn handler(TenantId(tenant_id): TenantId) {
// ...
}
```
## JWT 验证配置JwtVerifyConfig
`JwtVerifyConfig` 定义在 [jwt.rs](file:///home/shay/project/backend/auth-kit/src/jwt.rs)。
- **静态公钥**`rs256_from_pem(issuer, public_key_pem)`
- **JWKS 拉取**`rs256_from_jwks(issuer, jwks_url)`(带缓存与降级)
- **对称密钥(调试/兼容)**`hs256_from_secret(issuer, secret)`
注意点:
- RS256 模式要求 token header 中包含 `kid`(用于从 JWKS 中选 key
- issuer 必须与 token 中 `iss` 一致
- JWKS 目前只支持 RSA + `use=sig` + `alg=RS256`
### JWKS 缓存策略(当前实现)
- HTTP 超时1500ms
- 缓存 TTL300s
- stale-if-error3600sJWKS 拉取失败时可在窗口内使用缓存 key 继续验签)
## Skip 规则(免鉴权路径)
`AuthMiddlewareConfig` / `TenantMiddlewareConfig` 都支持:
- `skip_exact_paths`:精确路径匹配
- `skip_path_prefixes`:前缀匹配
用于跳过如 `/healthz``/scalar``/.well-known/jwks.json` 等公开端点。
## 端到端验证(推荐)
本库自带一个集成测试,用于验证 RS256 + JWKS 的验签路径:
- 测试文件: [jwks_verify.rs](file:///home/shay/project/backend/auth-kit/tests/jwks_verify.rs)
- 运行:
```bash
cd /home/shay/project/backend/auth-kit
cargo test
```
## 已知限制
- 暂未提供“从环境变量自动组装配置”的辅助函数(建议业务服务自行装配 `AuthMiddlewareConfig`
- 暂未实现 ECDSAES256/EdDSAEd25519JWKS 解析