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

ASP.NET Core Web API多值scp声明验证失败求助

问题解决:Okta SCP数组Claim在ASP.NET Web API授权失败

问题根源

Okta返回的JWT中scp是数组类型的Claim,但ASP.NET Core默认会将整个数组作为单个scp Claim的值存储(比如值为["claim1","claim2",...]的字符串形式),而你的授权策略RequireClaim("scp", "claim1")是在寻找值为claim1的独立scp Claim,因此匹配失败。

解决方案

需要在JWT认证配置中,自定义scp Claim的解析逻辑,将数组拆分为多个独立的scp Claim:

方法1:使用ClaimAction解析数组

在AddJwtBearer配置中添加自定义的Claim映射,遍历scp数组并生成多个Claim:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        // 基础的Token验证配置(替换为你的Okta参数)
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = "https://your-okta-domain.com/oauth2/default",
            ValidAudience = "your-api-audience",
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your-signing-key"))
        };

        // 自定义解析scp数组,生成多个scp Claim
        options.ClaimActions.MapCustomJson("scp", token =>
        {
            if (token.TryGetProperty("scp", out var scpProp) && scpProp.ValueKind == JsonValueKind.Array)
            {
                return scpProp.EnumerateArray()
                              .Select(item => item.GetString())
                              .ToList();
            }
            return new List<string>();
        });
    });

方法2:在Token验证事件中手动拆分Claim

通过OnTokenValidated事件,移除原有的数组形式scp Claim,添加拆分后的单个Claim:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        // 基础的Token验证配置(同上)
        options.TokenValidationParameters = new TokenValidationParameters
        {
            // ... 你的配置
        };

        options.Events = new JwtBearerEvents
        {
            OnTokenValidated = context =>
            {
                var identity = context.Principal.Identity as ClaimsIdentity;
                if (identity == null) return Task.CompletedTask;

                // 找到原有的scp Claim
                var scpArrayClaim = identity.FindFirst("scp");
                if (scpArrayClaim == null) return Task.CompletedTask;

                // 移除原Claim
                identity.RemoveClaim(scpArrayClaim);

                // 解析数组并添加多个scp Claim
                try
                {
                    var scpValues = JsonSerializer.Deserialize<List<string>>(scpArrayClaim.Value);
                    foreach (var value in scpValues)
                    {
                        identity.AddClaim(new Claim("scp", value));
                    }
                }
                catch (JsonException)
                {
                    // 处理解析失败的情况(比如scp不是数组)
                }

                return Task.CompletedTask;
            }
        };
    });

验证

完成配置后,ASP.NET Core会将每个scp数组项作为独立的scp Claim,此时你的授权策略HasClaim1就能正确匹配到值为claim1的Claim,授权验证通过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 12:13:34