🦀 Rust Axum × Keycloak:30 行代码拿下 OIDC 登录 + 角色权限
Rust Axum 框架中生产级 Keycloak OIDC 集成最佳实践
引言背景
Keycloak 是领先的开源身份与访问管理解决方案,完全支持 OpenID Connect (OIDC),作为 2026 年 1 月的最新版本(Keycloak 26.x 系列),它提供自动 Discovery、PKCE、Nonce 等现代安全特性。
在前文 OIDC 通用集成基础上,本节专注 Keycloak 专用配置,实现:
- 使用 Keycloak 作为 OIDC Provider
- Authorization Code Flow + PKCE + Nonce
- 自动 Discovery(无需手动配置端点)
- ID Token 验证 + UserInfo 获取(email、name 等)
- 登录成功后颁发自家 Access + Refresh Token(统一认证,与前文 Refresh Token 系统兼容)
- 支持角色映射(Keycloak Realm/Client Roles)
- 高可维护性:专用 crate axum-keycloak-auth(推荐,自动 JWKS Discovery + 角色检查)
Keycloak 服务端配置步骤(2026 版,适用于 Keycloak 26+)
-
启动 Keycloak(推荐 Docker):
docker run -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:latest start-dev -
访问 Admin Console:http://localhost:8080 → 创建 Realm(例如
myrealm) -
创建 Client:
- Clients → Create Client
- Client type: OpenID Connect
- Client ID:
axum-app(自定义) - Capability config:
- Client authentication: On(Confidential)
- Standard flow: Enabled
- Login settings:
- Valid redirect URIs:
https://your-axum-app.com/api/oidc/callback(精确匹配,生产禁用通配符) - Valid post logout redirect URIs:
+(允许所有)或指定 - Web origins:
+(CORS 允许)
- Valid redirect URIs:
-
获取 Client Secret:Credentials 标签 → 复制 Secret
-
创建用户与角色(可选):Users → Add user → 设置密码、分配 Realm Roles(如
user、admin) -
Discovery Endpoint:
http://localhost:8080/realms/myrealm/.well-known/openid-configuration
Rust Axum 客户端集成(推荐 axum-keycloak-auth crate)
此 crate 专为 Keycloak 设计,支持自动 JWKS Discovery、角色检查、高性能。
Cargo.toml
[package]
name = "axum-keycloak-oidc"
version = "0.1.0"
edition = "2021"
[dependencies]
axum = "0.8"
axum_server = "0.7"
tokio = { version = "1.48.0", features = ["full"] }
tower-http = { version = "0.6.8", features = ["trace", "cors"] }
axum-keycloak-auth = "0.2" # 最新版,支持自动 Discovery
rustls = "0.23.35"
rustls-pemfile = "2.2.0"
tracing = "0.1.40"
tracing-subscriber = "0.3.18"
src/main.rs
use axum::{
extract::Extension,
response::IntoResponse,
routing::get,
Router,
};
use axum_keycloak_auth::{
decode_token, expect_role, KeycloakAuthInstance, KeycloakAuthLayer, PassthroughMode, Role,
};
use axum_server::tls_rustls::RustlsConfig;
use std::sync::Arc;
use tower_http::{cors::CorsLayer, trace::TraceLayer};
// 定义角色枚举(匹配 Keycloak Realm/Client Roles)
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum AppRole {
User,
Admin,
#[allow(dead_code)]
Unknown(String),
}
impl Role for AppRole {
fn from_str(role: &str) -> Self {
match role {
"user" => AppRole::User,
"admin" => AppRole::Admin,
_ => AppRole::Unknown(role.to_string()),
}
}
}
async fn public() -> impl IntoResponse {
"This is public endpoint"
}
async fn protected(
Extension(token): Extension<axum_keycloak_auth::KeycloakToken<AppRole>>,
) -> impl IntoResponse {
expect_role!(&token, AppRole::User); // 必须有 user 角色
format!("Hello {}! Your subject: {}", token.preferred_username(), token.subject())
}
async fn admin(
Extension(token): Extension<axum_keycloak_auth::KeycloakToken<AppRole>>,
) -> impl IntoResponse {
expect_role!(&token, AppRole::Admin); // 必须有 admin 角色
"Welcome Admin!"
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt::init();
// Keycloak 配置(仅需 Issuer URL,自动 Discovery)
let keycloak_instance = KeycloakAuthInstance::new("http://localhost:8080/realms/myrealm")
.await?;
let keycloak_instance = Arc::new(keycloak_instance);
let cors = CorsLayer::permissive(); // 生产严格配置
let tls_config = RustlsConfig::from_pem_file("certs/fullchain.pem", "certs/privkey.pem").await?;
let app = Router::new()
.route("/public", get(public))
.route("/protected", get(protected))
.route("/admin", get(admin))
.layer(cors)
.layer(
KeycloakAuthLayer::<AppRole>::builder()
.instance(keycloak_instance.clone())
.passthrough_mode(PassthroughMode::Block) // 未认证直接拒绝
.build(),
)
.layer(TraceLayer::new_for_http());
let addr = ([0, 0, 0, 0], 443).into();
println!("Axum with Keycloak OIDC running on https://{}", addr);
axum_server::bind_rustls(addr, tls_config)
.serve(app.into_make_service())
.await?;
Ok(())
}
优势与最佳实践
- 自动 JWKS Discovery:无需手动管理公钥
- 角色检查宏:
expect_role!编译时安全 - 高性能:异步验证,零拷贝
- 生产安全:
- 精确 Redirect URI(禁用
*) - HTTPS 强制(TLS 已启用)
- Client Secret 保密(Confidential Client)
- 可扩展:结合前文 Refresh Token 系统
- 精确 Redirect URI(禁用
测试流程
- 访问
/protected→ 重定向到 Keycloak 登录 - 登录成功 → 返回 Axum 应用,显示用户信息
- 访问
/admin→ 仅 admin 角色用户通过
参考资料
- Keycloak 官方文档(26.x):https://www.keycloak.org/docs/latest/securing_apps/#_oidc
- axum-keycloak-auth crate:https://crates.io/crates/axum-keycloak-auth
- Keycloak Discovery Endpoint:
http://localhost:8080/realms/{realm}/.well-known/openid-configuration - OIDC 最佳实践:https://openid.net/connect/
现在你的 Axum 服务已完美集成 Keycloak OIDC:安全、标准、易维护,完全符合 2026 年工业级要求。
版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)