# auth-kit `auth-kit` 是一个可复用的认证/多租户中间件库(Rust + Axum),用于在多个微服务中统一实现: - JWT 认证:从 `Authorization: Bearer ` 解析并验证 token,注入 `AuthContext` - 租户隔离:从 `X-Tenant-ID` 解析租户并注入 `TenantId`,并在同时存在 token 与 header 时强制一致性 该 crate 不包含任何业务逻辑、数据库访问或 RBAC 聚合,仅提供“请求上下文注入 + 类型提取器 + JWT 验证能力”。 ## 依赖与约定 - Web 框架:Axum - 统一错误类型:`common_telemetry::AppError` - 头部约定: - `Authorization: Bearer ` - `X-Tenant-ID: ` ## 快速开始(在 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 - 缓存 TTL:300s - stale-if-error:3600s(JWKS 拉取失败时可在窗口内使用缓存 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`) - 暂未实现 ECDSA(ES256)/EdDSA(Ed25519)JWKS 解析