如何处理Azure AD B2C登录后的重定向请求以提取用户声明
嘿,你已经搞定了Azure AD B2C的基础配置和登录跳转,现在就差解析返回的用户信息这一步了对吧?我给你梳理下具体怎么做:
你已经在Request.Params里拿到了id_token,这是一个JWT格式的令牌,里面已经包含了你在B2C里配置的所有用户Claims。在ASP.NET里可以用System.IdentityModel.Tokens.Jwt包来轻松解析:
首先确保你通过NuGet安装了System.IdentityModel.Tokens.Jwt包,然后在你的Login.aspx的Page_Load方法里加这段代码:
using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Linq; protected void Page_Load(object sender, EventArgs e) { if (!string.IsNullOrEmpty(Request.Params["id_token"])) { var idToken = Request.Params["id_token"]; var tokenHandler = new JwtSecurityTokenHandler(); // 先快速解析(生产环境务必加签名验证!) var jwtToken = tokenHandler.ReadJwtToken(idToken); // 遍历所有Claims,或者提取你需要的特定字段 foreach (var claim in jwtToken.Claims) { // 这里可以把Claims存入Session或者展示出来 Response.Write($"<div>{claim.Type}: {claim.Value}</div>"); } // 比如获取邮箱、用户名这些常用字段 var userEmail = jwtToken.Claims.FirstOrDefault(c => c.Type == "emails")?.Value; var userName = jwtToken.Claims.FirstOrDefault(c => c.Type == "name")?.Value; } }
重要提醒:生产环境中必须验证JWT的签名、有效期、受众(aud),防止伪造令牌。验证需要用到B2C的公开密钥,你可以从
https://login.microsoftonline.com/{你的租户ID}/discovery/v2.0/keys?p={你的登录策略名}这个端点获取密钥,然后用TokenValidationParameters来配置验证规则。
你同时拿到的code是授权码,可以用来向B2C的token端点换取access_token、刷新令牌,甚至重新获取id_token。如果需要调用Microsoft Graph或者自定义API,这个access_token就派上用场了。示例代码如下:
using System.Net.Http; using System.Collections.Generic; using Newtonsoft.Json; protected async void Page_Load(object sender, EventArgs e) { if (!string.IsNullOrEmpty(Request.Params["code"])) { var code = Request.Params["code"]; var tokenEndpoint = $"https://login.microsoftonline.com/{AuthenticationConstants.Tenant}/oauth2/v2.0/token?p={AuthenticationConstants.PolicySignIn}"; using (var client = new HttpClient()) { var formData = new Dictionary<string, string> { {"grant_type", "authorization_code"}, {"client_id", AuthenticationConstants.ClientID}, {"code", code}, {"redirect_uri", "https://localhost:44301/auth/Login.aspx"}, // 必须和授权请求里的redirect_uri完全一致 {"scope", $"openid {AuthenticationConstants.ClientID}"} // 和授权请求的scope保持一致 }; var response = await client.PostAsync(tokenEndpoint, new FormUrlEncodedContent(formData)); var responseJson = await response.Content.ReadAsStringAsync(); // 解析返回的令牌数据 var tokenResult = JsonConvert.DeserializeObject<dynamic>(responseJson); var accessToken = tokenResult.access_token; var newIdToken = tokenResult.id_token; // 之后可以用accessToken调用API,或者解析newIdToken获取Claims } } }
其实手动处理跳转和令牌解析比较繁琐,ASP.NET的OWIN中间件已经封装了Azure AD B2C的认证流程,你只需要配置中间件,就能自动处理登录跳转、令牌验证,用户信息会直接存到User.Claims里,省去很多重复代码。不过如果你已经写了现有逻辑,先按上面的方法搞定当前需求也没问题。
内容的提问来源于stack exchange,提问作者radders

