如何在Rust中实现无用户交互的MS Graph身份验证
使用graph-rs-sdk实现无用户交互的Microsoft Graph应用身份验证(客户端凭证流)
你的核心问题是误用了委托权限的授权码流程(引入warp服务器、调用浏览器授权),而应用身份验证需要纯后端的客户端凭证流,不需要任何用户交互。同时端点和Scope的配置也存在错误,导致AADSTS900144报错。
修正后的完整实现
use graph_rs_sdk::{oauth::OAuth, Graph}; use crate::{CLIENT_ID, CLIENT_SECRET, TENANT_ID}; #[tokio::test] async fn ut_client_credentials() { // 初始化OAuth客户端 let oauth = get_oauth_client(); let mut token_request = oauth.build_async().client_credentials(); // 直接请求访问令牌(无用户交互) match token_request.access_token().send().await { Ok(access_token) => { println!("获取令牌成功: {:#?}", access_token); // 用令牌创建Graph客户端 let graph_client = Graph::new(access_token.access_token().unwrap()); // 调用Graph API示例(以获取租户用户为例,需提前授予User.Read.All应用权限) match graph_client.v1().users().list_users().send().await { Ok(users) => println!("用户列表: {:#?}", users), Err(e) => eprintln!("API调用失败: {}", e), } } Err(e) => eprintln!("令牌请求失败: {}", e), } } fn get_oauth_client() -> OAuth { let mut oauth = OAuth::new(); oauth .client_id(CLIENT_ID) .client_secret(CLIENT_SECRET) .tenant_id(TENANT_ID) // 应用权限必须使用 .default 范围,代表所有已授予的应用权限 .add_scope("https://graph.microsoft.com/.default") // 替换common为具体租户ID,确保请求到正确的租户认证端点 .access_token_url(format!( "https://login.microsoftonline.com/{}/oauth2/v2.0/token", TENANT_ID )); oauth }
关键修正点说明
移除浏览器授权相关代码
你之前的代码中request.browser_authorization().open()和warp服务器是用于委托权限的授权码流程,会触发浏览器登录,完全不符合无交互的应用身份需求,必须全部移除。客户端凭证流是直接从后端向Azure AD请求令牌,不需要任何前端交互。修正Scope配置
应用权限的Scope不能指定单个权限(比如User.Invite.All),Azure AD v2.0端点要求应用权限使用https://graph.microsoft.com/.default,这个值会自动包含所有已在Azure AD中授予该应用的应用权限。修正认证端点
将access_token_url中的common替换为你的具体租户ID,common用于多租户应用的用户登录,而应用身份验证必须指定明确的租户,否则会导致Scope识别错误(即AADSTS900144报错)。移除不必要的Redirect URI
客户端凭证流不需要回调地址,因此可以删除.redirect_uri()的配置。
额外注意事项
- 确保Azure AD应用已正确配置应用权限(而非委托权限),并且完成了管理员同意。
- 客户端密钥必须有效且未过期,若密钥过期需在Azure AD中重新生成。
- Cargo.toml中需添加必要依赖:
[dependencies] graph-rs-sdk = "0.2.0" # 或最新版本 tokio = { version = "1.0", features = ["full"] }
内容的提问来源于stack exchange,提问作者RAVN Mateus
相关产品推荐
相关产品推荐

