ASP.NET MVC 5配置Azure AD OIDC登录Issuer验证失败问题
我正尝试为ASP.NET MVC 5(.NET 4.8)应用配置基于OpenID Connect(OIDC)的Azure Active Directory(Azure AD)单点登录(SSO)。该应用是用于测试的全新项目,仅对脚手架代码的Startup.Auth.cs文件做了如下修改:
// 自动添加的引用: using Microsoft.IdentityModel.Tokens; using Microsoft.Owin.Security.OpenIdConnect; // 在public void ConfigureAuth(IAppBuilder app)方法中: app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { ClientId = "{ClientId of AAD App}", ClientSecret = "{Secret generated for the AAD app}", CallbackPath = new PathString("/signin-microsoft"), MetadataAddress = "https://login.microsoftonline.com/organizations/v2.0/.well-known/openid-configuration", TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidIssuer = "https://login.microsoftonline.com/{Directory (tenant) ID}/v2.0" } });
当我将ValidateIssuer设置为false时,一切正常,可使用组织邮箱登录应用。但一旦设置为true,就会出现如下错误:
IDX10205: Issuer validation failed. Issuer: '[PII is hidden]'. Did not match: validationParameters.ValidIssuer: '[PII is hidden]' or validationParameters.ValidIssuers: '[PII is hidden]'.
我尝试将ValidIssuer修改为Stack Overflow相关帖子中提到的所有选项,但均无效。当前ValidIssuer是MetadataAddress对应的URL,替换为已注册应用的具体目录(租户)ID。
已注册的Azure AD应用中,我已将“Access tokens (used for implicit flows)”和“ID tokens (used for implicit and hybrid flows)”设置为true,“Supported account types”设置为“Accounts in any organizational directory (Any Azure AD directory - Multitenant)”。
请问问题出在哪里?
核心问题是多租户应用场景下,不能硬编码单个ValidIssuer——不同租户用户登录时,令牌的Issuer会是对应租户的ID,而非你自己的租户ID,硬编码自然会匹配失败。
具体原因
你配置的MetadataAddress是多租户通用端点(organizations/v2.0),允许任意Azure AD租户的用户登录。此时每个租户用户的令牌Issuer格式为https://login.microsoftonline.com/{租户ID}/v2.0,但你硬编码了自己的租户ID作为ValidIssuer,其他租户用户登录时必然验证不通过。
正确配置方式
方法1:启用自动Issuer验证(推荐)
移除手动设置的ValidIssuer,保留ValidateIssuer = true,并通过IssuerValidator自动从元数据验证Issuer合法性:
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { ClientId = "{ClientId of AAD App}", ClientSecret = "{Secret generated for the AAD app}", CallbackPath = new PathString("/signin-microsoft"), MetadataAddress = "https://login.microsoftonline.com/organizations/v2.0/.well-known/openid-configuration", TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true // 移除硬编码的ValidIssuer }, IssuerValidator = (issuer, token, parameters) => { // 验证Issuer是否符合多租户格式 var baseIssuer = parameters.Configuration.Issuer.Substring(0, parameters.Configuration.Issuer.LastIndexOf('/')); if (issuer.StartsWith(baseIssuer)) { return issuer; } throw new SecurityTokenInvalidIssuerException("Issuer验证失败"); } });
方法2:动态设置ValidIssuers(限制特定租户登录)
如果只允许指定租户的用户访问,可以将这些租户的Issuer URL加入ValidIssuers集合:
TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidIssuers = new List<string> { "https://login.microsoftonline.com/租户ID1/v2.0", "https://login.microsoftonline.com/租户ID2/v2.0" } };
额外排查技巧
开启PII日志可查看具体的Issuer值,方便定位不匹配问题:在Startup.cs的Configuration方法中添加:
IdentityModelEventSource.ShowPII = true;
这样错误日志会显示真实的Issuer和ValidIssuer内容,更容易找到差异点。
内容的提问来源于stack exchange,提问作者dzenesiz

