使用AddMicrosoftAccount时GetExternalLoginInfoAsync返回null问题
问题场景
我在程序中配置了Microsoft账户登录:
builder.Services.AddAuthentication().AddMicrosoftAccount(microsoftOptions => { microsoftOptions.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; microsoftOptions.ClientId = "..."; microsoftOptions.ClientSecret = "..."; microsoftOptions.AuthorizationEndpoint = "https://login.microsoftonline.com/.../oauth2/v2.0/authorize"; microsoftOptions.TokenEndpoint = "https://login.microsoftonline.com/.../oauth2/v2.0/token"; microsoftOptions.Scope.Add("openid"); microsoftOptions.Scope.Add("profile"); microsoftOptions.Scope.Add("email"); });
Azure端配置已完成,登录按钮显示在/Identity/Account/Login页面,登录流程可正常跳转,但回调最终到Identity/Account/ExternalLoginCallback时,执行var info = await _signInManager.GetExternalLoginInfoAsync();返回null。请求中存在idsrv.externalCookie,但.User对象无任何声明。
解决办法
1. 确认ExternalCookie认证方案的注册顺序
你指定了SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme,但必须确保这个认证方案已正确注册。在ASP.NET Core + IdentityServer场景中,可手动显式注册ExternalCookie方案,再添加Microsoft账户登录配置:
builder.Services.AddAuthentication() .AddCookie(IdentityServerConstants.ExternalCookieAuthenticationScheme, options => { options.Cookie.Name = "idsrv.external"; options.ExpireTimeSpan = TimeSpan.FromMinutes(5); options.SlidingExpiration = true; }) .AddMicrosoftAccount(microsoftOptions => { // 你的原有配置 });
2. 为ExternalLoginCallback指定认证方案
ExternalLoginCallback需要能读取idsrv.externalCookie中的认证信息,可在对应控制器动作上添加指定认证方案的授权属性:
[Authorize(AuthenticationSchemes = IdentityServerConstants.ExternalCookieAuthenticationScheme)] public async Task<IActionResult> ExternalLoginCallback() { var info = await _signInManager.GetExternalLoginInfoAsync(); // 后续逻辑 }
或者直接在调用GetExternalLoginInfoAsync时传入认证方案:
var info = await _signInManager.GetExternalLoginInfoAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
3. 调试OpenID Connect响应的声明
手动指定AuthorizationEndpoint和TokenEndpoint后,需确认Azure返回的ID Token包含必要声明(如sub、name、email)。可添加认证事件调试返回的令牌内容:
microsoftOptions.Events = new OAuthEvents { OnCreatingTicket = context => { // 此处可断点查看context.Identity中的声明是否完整 var claims = context.Identity.Claims; return Task.CompletedTask; } };
若声明缺失,检查Azure AD应用注册中是否配置了正确的权限,或确认Scope中已包含所需的OpenID Connect权限。
4. 检查Cookie的安全配置
如果站点使用HTTPS,需确保idsrv.externalCookie的Secure和SameSite属性配置正确,避免Cookie无法被读取:
options.Cookie.SecurePolicy = CookieSecurePolicy.Always; options.Cookie.SameSite = SameSiteMode.Lax;
内容的提问来源于stack exchange,提问作者Richard Barraclough

