Blazor Server(.NET Core3.1)获取当前用户AAD访问令牌失败求助
解决Blazor Server (.NET Core 3.1) 无法获取Azure AD访问令牌的问题
我帮你梳理下可能的问题点和对应的解决步骤,你可以一步步排查:
1. 确认Azure AD应用注册的API权限配置是否正确
要获取下游API的访问令牌,你的Blazor Server应用必须在Azure AD中注册并添加正确的委托权限(Delegated Permissions):
- 登录Azure门户,找到你的Blazor Server应用注册
- 进入「API权限」页面,点击「添加权限」,选择你的下游API
- 添加对应的委托权限(比如
access_as_user),然后点击「授予管理员同意」(这一步很关键,否则用户登录后无法获取令牌)
2. 完善Startup.cs中的认证配置
你已经设置了SaveTokens=true,但还需要确保OpenIdConnect的配置包含下游API的Scope,并且使用授权码流(ResponseType为code id_token):
using Microsoft.AspNetCore.Authentication.AzureAD.UI; using Microsoft.AspNetCore.Authentication.OpenIdConnect; public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(AzureADDefaults.AuthenticationScheme) .AddAzureAD(options => Configuration.Bind("AzureAd", options)); // 显式配置OpenIdConnect选项,确保获取access token services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options => { options.SaveTokens = true; // 添加下游API的Scope,格式为api://{下游API的ClientId}/{权限名称} options.Scope.Add("api://xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/access_as_user"); // 指定授权码流,这是获取access token的必要条件 options.ResponseType = "code id_token"; // 可选:添加事件日志,调试时查看令牌获取情况 options.Events = new OpenIdConnectEvents { OnTokenValidated = context => { var accessToken = context.TokenEndpointResponse?.AccessToken; if (!string.IsNullOrEmpty(accessToken)) { System.Diagnostics.Debug.WriteLine("获取到Access Token: " + accessToken); } return Task.CompletedTask; } }; }); // 其他服务配置... services.AddHttpContextAccessor(); // 后续Blazor组件中需要用到 services.AddRazorPages(); services.AddServerSideBlazor(); }
3. 正确获取令牌的方式
在控制器中获取
不要从ClaimsPrincipal直接找令牌,access token存储在HttpContext的认证属性中,用GetTokenAsync方法获取:
[Authorize] public class ApiCallController : Controller { public async Task<IActionResult> CallDownstreamApi() { var accessToken = await HttpContext.GetTokenAsync("access_token"); if (string.IsNullOrEmpty(accessToken)) { // 令牌未获取到,跳转到重新认证 return Challenge(); } // 使用access token调用下游API var client = new HttpClient(); client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken); var response = await client.GetAsync("https://your-downstream-api-url"); // 处理响应... return View(); } }
在Blazor组件中获取
Blazor组件无法直接访问HttpContext,需要注入IHttpContextAccessor:
@inject IHttpContextAccessor HttpContextAccessor @if (HttpContextAccessor.HttpContext.User.Identity.IsAuthenticated) { <p>已认证,正在获取令牌...</p> } @code { protected override async Task OnInitializedAsync() { if (HttpContextAccessor.HttpContext.User.Identity.IsAuthenticated) { var accessToken = await HttpContextAccessor.HttpContext.GetTokenAsync("access_token"); if (!string.IsNullOrEmpty(accessToken)) { // 使用令牌调用API } else { // 令牌为空,触发重新认证 NavigationManager.NavigateTo("/MicrosoftIdentity/Account/SignIn", forceLoad: true); } } } }
4. 验证回调地址和应用配置
- 确保Azure AD应用注册中的「回复URL(Redirect URIs)」包含你的Blazor Server的回调地址,比如
https://localhost:5001/signin-oidc(生产环境替换为实际域名) - 检查
appsettings.json中的Azure AD配置是否正确:ClientId、TenantId、CallbackPath(默认是/signin-oidc)必须和Azure门户中的配置一致
5. 调试排查
如果还是拿不到令牌,可以通过以下方式排查:
- 查看调试日志中的
OnTokenValidated事件输出,确认是否从Azure AD获取到了access token - 使用浏览器的开发者工具,查看认证回调时的网络请求(
/signin-oidc),检查返回的令牌数据中是否包含access_token
内容的提问来源于stack exchange,提问作者Falco Lannoo
相关产品推荐
相关产品推荐

