You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

IdentityServer4内存存储集成测试遇invalid_grant错误求助

我来帮你排查这个invalid_grant的问题,在IdentityServer4的密码模式测试场景里,这个错误通常由几个常见配置问题导致,咱们逐一分析解决:

1. TestUser的密码未正确哈希(最可能的根因)

IdentityServer4的TestUser类的Password属性要求存储哈希后的密码,而不是明文。默认的TestUserPasswordValidator会用ASP.NET Core的PasswordHasher来验证密码——如果你直接给Password赋值明文,验证时会把输入的密码哈希后和存储的明文对比,自然不匹配,就会返回invalid_username_or_password。

修复方法很简单,先生成哈希密码再赋值:

// 实例化密码哈希器
var passwordHasher = new PasswordHasher<TestUser>();

// 为测试用户生成哈希密码
var elevatedUser = MyDemoUser.ElevatedUser;
var hashedElevatedPwd = passwordHasher.HashPassword(null, elevatedUser.Password);

var workstationUser = MyDemoUser.WorkstationUser;
var hashedWorkstationPwd = passwordHasher.HashPassword(null, workstationUser.Password);

// 更新TestUser配置
builder.AddTestUsers(new List<TestUser> {
    new TestUser {
        SubjectId = Guid.NewGuid().ToString(),
        Claims = new List<Claim> {
            new Claim(JwtClaimTypes.Subject, elevatedUser.UserName),
            new Claim(JwtClaimTypes.Email, elevatedUser.Email),
            new Claim(JwtClaimTypes.Role, elevatedUser.Roles[0]),
            new Claim(JwtClaimTypes.Role, elevatedUser.Roles[1])
        },
        IsActive = true,
        Password = hashedElevatedPwd, // 用哈希后的密码
        Username = elevatedUser.UserName
    },
    new TestUser {
        SubjectId = Guid.NewGuid().ToString(),
        Claims = new List<Claim> {
            new Claim(JwtClaimTypes.Subject, workstationUser.UserName),
            new Claim(JwtClaimTypes.Email, workstationUser.Email),
            new Claim(JwtClaimTypes.Role, workstationUser.Roles[0])
        },
        IsActive = true,
        Password = hashedWorkstationPwd,
        Username = workstationUser.UserName
    }
});

2. 客户端未启用密码授权类型

检查IS4Config.GetClients()返回的客户端配置,确保你的MyClient的AllowedGrantTypes包含GrantTypes.ResourceOwnerPassword:

// 示例客户端配置(参考调整你的代码)
new Client {
    ClientId = MyClient.ClientId,
    ClientSecrets = { new Secret(MyClient.ClientSecret.Sha256()) },
    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, // 必须包含这个授权类型
    AllowedScopes = { MyApiResource.Gateway.Name },
    // 其他必要配置...
}

如果客户端没开启密码授权,IdentityServer会直接拒绝令牌请求,触发invalid_grant错误。

3. 发行者URI大小写不匹配

你在IdentityServer配置里设置的IssuerUri是"https://my.services.is4host"(小写m),但测试代码里调用GetDiscoveryDocumentAsync用的是"https://My.services.is4host"(大写M)。IdentityServer对发行者URI的验证是严格的,大小写不一致可能导致发现文档的issuer不匹配,进而影响令牌请求。建议统一成一致的大小写:

// 配置端保持统一
options.IssuerUri = "https://my.services.is4host";

// 测试端同步修改
var disco = await client.GetDiscoveryDocumentAsync("https://my.services.is4host");

4. 多余的SQLite内存数据库配置

你当前配置了SQLite内存库和SecurityDbContext,但并没有把IdentityServer的配置/操作数据绑定到这个DbContext(没有调用AddConfigurationStore或AddOperationalStore)。这个配置完全是多余的,建议移除,避免混淆和不必要的资源消耗。


按照以上步骤逐一排查,应该就能解决你的令牌请求错误了。

内容的提问来源于stack exchange,提问作者secretAgentB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:14:13