使用OpenID Connect在Blazor Server中获取Azure B2C签发的JWT令牌
可以获取到Azure B2C签发的原始JWT令牌,不需要自行生成,具体实现流程如下:
前置配置
首先确保你的项目已经完成以下基础配置:
- 在Program.cs中注册Microsoft Identity服务时开启令牌保存,同时启用令牌获取能力和令牌缓存:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAdB2C"), options => { // 必须开启,才会把Azure返回的令牌存到认证票据中 options.SaveTokens = true; }) // 启用令牌获取服务,对应你用MSAL.js的acquireTokenSilent能力 .EnableTokenAcquisitionToCallDownstreamApi() // 配置内存令牌缓存,生产环境可替换为分布式缓存 .AddInMemoryTokenCaches(); // 注册HttpContext访问服务(如果你用方式1获取令牌需要加) builder.Services.AddHttpContextAccessor();
组件内获取令牌的两种实现方式
方式1:通过HttpContext获取(仅适用页面首次预渲染阶段)
直接在LoginDisplay.razor组件中注入IHttpContextAccessor,然后调用GetTokenAsync方法获取:
@inject IHttpContextAccessor HttpContextAccessor @code { [CascadingParameter] private Task<AuthenticationState> authenticationStateTask { get; set; } protected override async Task OnInitializedAsync() { var authState = await authenticationStateTask; var user = authState.User; var identity = user.Identity as ClaimsIdentity; if (identity != null && identity.IsAuthenticated) { IEnumerable<Claim> claims = identity.Claims; // 在此处获取JWT令牌 if (HttpContextAccessor.HttpContext != null) { // 身份令牌id_token var idToken = await HttpContextAccessor.HttpContext.GetTokenAsync("id_token"); // 访问令牌access_token var accessToken = await HttpContextAccessor.HttpContext.GetTokenAsync("access_token"); } } } }
注意:该方式仅在页面首次加载的预渲染阶段可用,Blazor Server建立SignalR长连接之后,HttpContext会被释放,此时调用会返回null。
方式2:通过ITokenAcquisition服务获取(推荐全场景使用)
这是微软官方提供的令牌获取服务,能力和你之前在SPA中使用的MSAL.acquireTokenSilent完全一致,会自动处理令牌缓存、刷新逻辑,不需要自行处理HttpContext:
首先在组件中注入ITokenAcquisition服务:
@inject ITokenAcquisition TokenAcquisition @code { [CascadingParameter] private Task<AuthenticationState> authenticationStateTask { get; set; } protected override async Task OnInitializedAsync() { var authState = await authenticationStateTask; var user = authState.User; var identity = user.Identity as ClaimsIdentity; if (identity != null && identity.IsAuthenticated) { IEnumerable<Claim> claims = identity.Claims; // 在此处获取JWT令牌 // 替换为你在Azure B2C中注册的下游API作用域 var scopes = new[] { "你的API作用域,例如https://xxx.onmicrosoft.com/xxx/access_as_user" }; try { var accessToken = await TokenAcquisition.GetAccessTokenForUserAsync(scopes); // 此处拿到的就是Azure B2C签名的原始JWT令牌 } catch (MicrosoftIdentityWebChallengeUserException) { // 处理需要用户重新交互的场景,例如令牌过期无法刷新、权限变更 } } } }
GetTokenAsync返回null的排查方案
如果调用HttpContext.GetTokenAsync返回null,可按以下步骤排查:
- 确认OpenIdConnect配置中
SaveTokens = true已正确设置 - 确认调用时机在HttpContext有效阶段,若为长连接建立后的交互场景,直接改用ITokenAcquisition服务即可
- 确认用户已完成完整的Azure B2C登录流程,身份认证已成功
内容的提问来源于stack exchange,提问作者Jonny
相关产品推荐
相关产品推荐

