如何编程测试Azure AD B2C用户工作流并获取有效令牌?
解决方案:Azure AD B2C 用户名密码式获取令牌并调用Graph API
针对你需要自动化测试授权工作流、用用户名密码编程获取令牌并查询Graph API组成员的需求,这里有几个可行的方案,尤其适合Ruby和Go这类没有官方ADAL库的后端:
1. 使用ROPC(Resource Owner Password Credentials)流直接获取令牌
Azure AD B2C支持ROPC流,这是专门为**信任的客户端(比如你的自动化测试脚本)**设计的,允许直接用用户名和密码换取令牌,不需要跳转登录页面。
前提准备
- 在Azure AD B2C中创建一个ROPC类型的用户流(或者用自定义策略,用户流更适合快速上手):
- 进入B2C租户 -> 用户流 -> 新建用户流 -> 选择“资源所有者密码凭据”类型,配置所需的属性和令牌内容。
- 确保你的测试账号是本地账号(ROPC不支持社交登录账号,也不支持启用MFA的账号,测试环境建议用无MFA的本地测试用户)。
- 给你的后端应用注册添加API权限:如果要调用Graph API,需要添加
Directory.Read.All或User.Read.All等权限,并且授予管理员同意(因为要查询组成员,需要应用级权限)。
令牌请求示例(HTTP POST)
直接向B2C的令牌端点发送请求:
POST https://{your-b2c-tenant-name}.b2clogin.com/{your-b2c-tenant-name}.onmicrosoft.com/{your-ropc-user-flow-name}/oauth2/v2.0/token Content-Type: application/x-www-form-urlencoded grant_type=password &client_id={your-app-client-id} &scope=https://graph.microsoft.com/.default openid offline_access &username={test-user-username} &password={test-user-password} &response_type=token id_token
scope里的https://graph.microsoft.com/.default表示请求应用已配置的所有Graph API权限,这样拿到的令牌就能直接调用Graph API。- 成功响应会返回
access_token、id_token和refresh_token。
2. 用拿到的令牌调用Graph API查询组成员
拿到access_token后,就可以调用Microsoft Graph API的memberOf端点获取用户所属的组:
GET https://graph.microsoft.com/v1.0/me/memberOf Authorization: Bearer {your-access-token}
响应会返回用户所在的所有组信息,包括组ID、名称等,满足你验证授权工作流的需求。
3. Ruby和Go的代码实现示例
Ruby 示例(用HTTParty)
require 'httparty' # 配置参数 tenant_name = "your-b2c-tenant-name" user_flow = "your-ropc-user-flow-name" client_id = "your-app-client-id" username = "test-user@your-tenant.onmicrosoft.com" password = "test-user-password" # 获取令牌 token_url = "https://#{tenant_name}.b2clogin.com/#{tenant_name}.onmicrosoft.com/#{user_flow}/oauth2/v2.0/token" token_response = HTTParty.post(token_url, body: { grant_type: "password", client_id: client_id, scope: "https://graph.microsoft.com/.default openid offline_access", username: username, password: password }, headers: { 'Content-Type' => 'application/x-www-form-urlencoded' } ) access_token = token_response.parsed_response["access_token"] # 调用Graph API查询组成员 graph_url = "https://graph.microsoft.com/v1.0/me/memberOf" graph_response = HTTParty.get(graph_url, headers: { 'Authorization' => "Bearer #{access_token}" } ) puts graph_response.parsed_response
Go 示例
package main import ( "bytes" "encoding/json" "fmt" "net/http" "net/url" ) func main() { // 配置参数 tenantName := "your-b2c-tenant-name" userFlow := "your-ropc-user-flow-name" clientID := "your-app-client-id" username := "test-user@your-tenant.onmicrosoft.com" password := "test-user-password" // 构造令牌请求 tokenURL := fmt.Sprintf("https://%s.b2clogin.com/%s.onmicrosoft.com/%s/oauth2/v2.0/token", tenantName, tenantName, userFlow) data := url.Values{} data.Set("grant_type", "password") data.Set("client_id", clientID) data.Set("scope", "https://graph.microsoft.com/.default openid offline_access") data.Set("username", username) data.Set("password", password) tokenResp, err := http.Post(tokenURL, "application/x-www-form-urlencoded", bytes.NewBufferString(data.Encode())) if err != nil { fmt.Println("获取令牌失败:", err) return } defer tokenResp.Body.Close() var tokenResult map[string]interface{} json.NewDecoder(tokenResp.Body).Decode(&tokenResult) accessToken := tokenResult["access_token"].(string) // 调用Graph API查询组成员 graphURL := "https://graph.microsoft.com/v1.0/me/memberOf" req, _ := http.NewRequest("GET", graphURL, nil) req.Header.Set("Authorization", "Bearer "+accessToken) graphResp, err := http.DefaultClient.Do(req) if err != nil { fmt.Println("调用Graph API失败:", err) return } defer graphResp.Body.Close() var graphResult map[string]interface{} json.NewDecoder(graphResp.Body).Decode(&graphResult) fmt.Println("用户所属组:", graphResult) }
注意事项
- ROPC流仅适合测试环境,生产环境不建议使用,因为它会直接处理用户密码,存在安全风险。
- 不支持启用MFA的用户,测试账号请关闭MFA。
- 确保应用的权限是最小必要的,不要给超过测试所需的权限。
内容的提问来源于stack exchange,提问作者Max Burke
相关产品推荐
相关产品推荐

