Identity Server 4 身份相关范围请求,但没有 openid 范围

Identity Server 4 Identity related scope requests, but no openid scope

我正在尝试添加自定义 resource/scope,为了测试,我选择它作为电子邮件,但据我所知,它可以是任何值。所以对于我的资源,我有这个:

return new List<IdentityResource>
{
    new IdentityResources.OpenId(),
    new IdentityResources.Profile(),
    new IdentityResource("email", "Email", new [] { "email" })
    //new IdentityResources.Email()  -- This was tried as well, same error.
};

return new List<ApiResource> { new ApiResource("test", "Test") };

然后对于客户端的作用域如下:

AllowedScopes = new List<string>
{
    "openid", "profile", "email", "test"
}

但是,当我请求带有 http://localhost:5000/connect/authorize?Scope=test email 的令牌时,页面出现错误,我看到

2019-07-05 11:08:00.681 -04:00 [ERR] Invalid scope: email
2019-07-05 11:08:00.684 -04:00 [ERR] Request validation failed

我真的不知道我哪里做错了。根据我找到的所有文档和 SO 帖子,这就是它的完成方式。

编辑:有一个内部错误被忽略并导致错误的 List<IdentityResource> 通过。但是,即使解决了这个问题,现在仍然会导致出现不同错误消息的问题:

Identity related scope requests, but no openid scope

编辑 2:

在一些帮助表格 d_f 之后,我意识到我需要更新我的请求,现在看起来像这样:

/connect/authorize?scope=test openid email&response_type=id_token token&nonce=NONCE

我现在获得授权,我可以在声明中看到电子邮件范围。然而,即使我将电子邮件视为一个范围,我也没有在声明中的任何地方看到实际的电子邮件。

电子邮件是标准身份资源。

尝试

return new List<IdentityResource>
{
  new IdentityResources.OpenId(),
  new IdentityResources.Profile(),
  new IdentityResources.Email()
}; 

documentation

如果你想添加自定义的,你可以找到它here

您在 IdentityResource 中添加 IdentityResources.Email() 声明,这意味着 id_token 将包含用户的电子邮件信息。您可以使用 https://jwt.io/ 等在线工具解码 id_token(不是访问令牌)以检查返回的声明。

您还可以在客户端配置中将 AlwaysIncludeUserClaimsInIdToken 设置为 true 以查看它是否包含电子邮件声明:

new Client
{
    ClientId = "mvc",
    ClientName = "MVC Client",
    AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,

    ....

    ....
    AlwaysIncludeUserClaimsInIdToken = true,
    AllowedScopes =
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
        "api1",
        IdentityServerConstants.StandardScopes.Email,
    },
    AllowOfflineAccess = true
},

此外,还有不同种类(身份验证流程)的 IdentityServer 4 快速入门示例:

https://github.com/IdentityServer/IdentityServer4/tree/master/samples/Quickstarts

您可以开始根据代码示例自定义 client/IDS4。

我看到答案需要一些理论背景。 正如您在任何基础工作或原始 specification 中所发现的那样,OpenID Connect 协议变成了 OpenId 和 OAuth 的组合。 OIdC 与第二个兼容,正如您在请求转换期间看到的那样。 OIdC 的新功能是额外的 身份令牌 。 OAuth 引入了 access aka bearer token + refresh token 以获得新的 access一个当现有的过期。所有这些都是关于使用不记名授权 http header 访问 API。新的 身份令牌 代表应用程序的用户 session,而不是 api。

身份服务器 4 中 identity_tokenaccess_token 的有效负载相应地由两个单独的词典 IdentityResources and ApiResources 控制。不幸的是,您不能同时向两者添加范围。但是您可以使用相同的声明定义两个不同的范围。例如:

public static IEnumerable<ApiResource> GetApiResources()
{
    return new List<ApiResource>
    {
        new ApiResource
        {
            Name = "test-api",
            Scopes =
            {
                new Scope
                {
                    Name = "test",
                    UserClaims =
                    {
                        JwtClaimTypes.SessionId,
                        JwtClaimTypes.Role,
                        Constants.TenantIdClaimType,
                        JwtClaimTypes.Email,
                        JwtClaimTypes.Locale
                    }
                }
            }
        }
    };
}

public static List<IdentityResource> GetIdentityResources()
{
    // Claims automatically included in OpenId scope
    var openIdScope = new IdentityResources.OpenId();
    openIdScope.UserClaims.Add(JwtClaimTypes.Locale);

    // Available scopes
    return new List<IdentityResource>
    {
        openIdScope,
        new IdentityResources.Profile(),
        new IdentityResources.Email(),
        new IdentityResource(Constants.RolesScopeType, Constants.RolesScopeType,
                    new List<string> {JwtClaimTypes.Role, Constants.TenantIdClaimType})
            {
                Required = true
            }
    };
}

在此示例中,我们添加了在 access_token 中作为 test 范围的一部分以及在 id_token 中作为标准 email 的一部分获取电子邮件声明的可能性范围。

此外,我们必须记住 id_token 默认情况下针对大小进行了优化,并且在其有效负载中只有 protocol-required 声明。可以从 IdP 的 Userinfo endpoint 额外请求所有额外声明。要获取 id_token 内的所有用户声明,您可以在 IdSrv 的客户端配置中设置 AlwaysIncludeUserClaimsInIdToken=true