在 IdentityServer 中,Client Secrets 和 Scope Secrets 有什么区别?

In IdentityServer, what is the difference between Client Secrets and Scope Secrets?

有人可以解释一下两者之间的区别吗?我了解客户端机密,但范围机密仍然不清楚...以及为什么范围机密甚至需要存在?

虽然我发现 documentation 在某些方面有帮助,但我发现它对解释两者之间的区别没有帮助。

客户端机密用于授权访问 token endpoint。此端点使用客户端 ID 和客户端密码,并允许您请求访问令牌。

Scope Secrets 用于授权访问 introspection endpoint。此端点使用范围 ID 和范围机密,因为只有包含在访问令牌中的范围才允许对其进行内省。

多亏了 Scott Brady,我才得以回答我的问题。这是我发现的...

客户端机密

正如 Scott Brady 所说,当您的客户端应用程序调用 token end point 时,将使用客户端机密。您的客户端应用程序必须具有有效的客户端 ID 和客户端密码才能调用令牌端点。

范围秘密

但是如果你的资源服务器需要调用IdentityServer怎么办?当资源服务器调用 introspection endpoint 时会发生这种情况。当您的应用程序使用引用令牌或使用 JWT 的服务器端验证时,会发生这种情况。因此,假设您的经过身份验证的客户端调用资源服务器上的受保护端点。然后,资源服务器必须使用 IdentityServer 验证该 JWT 持有者令牌。但是,从您的资源服务器发送到 IdentityServer 的请求必须是受保护的调用。也就是说,资源服务器必须向 IdentityServer 提供 JWT 承载令牌才能使用内省端点。资源服务器不能使用它试图验证的令牌,因为它属于客户端(受众不是资源服务器,而是客户端应用程序)。此外,资源服务器不确定不记名令牌是否有效。资源服务器使用有问题的不记名令牌来验证验证所述不记名令牌的请求是没有意义的。那么现在有一个问题...资源服务器如何向IdentityServer发送经过身份验证的请求?

这就是 Scope Secrets 的用武之地。IdentityServer 解决这个问题的方法是允许您创建一个包含 Scope Secret 的 Scope。此范围已添加到您的资源服务器身份验证选项中。例如:

app.UseIdentityServerBearerTokenAuthentication(
                new IdentityServerBearerTokenAuthenticationOptions
                {
                    Authority = "http://localhost:5000",
                    ClientId = "api", //The Scope name
                    ClientSecret = "api-secret", //This is the non hashed/encrypted Scope Secret
                    RequiredScopes = new[] { "api" } //Must add the Scope name here
                });

通过将此范围设为必需,我们可以确保任何经过身份验证的客户端应用程序都将具有此范围。然后在 IdentityServer 中,您将像这样添加范围:

new Scope
    {
        Name = "api",
        DisplayName = "Scope DisplayName",
        Description = "This will grant you access to the API",

        //The secret here must be Sha256-ed in order for the /introspection end point to work.
        //If the API's IdentityServerBearerTokenAuthenticationOptions field is set as so ValidationMode = ValidationMode.ValidationEndpoint,
        //then the API will call the /introspection end point to validate the token on each request (instead of ValidationModel.ValidationLocal.
        //The ClientSecret must be the NON Sha256-ed string (for example Api = "api-secret" then scope secret must = "api-secret".Sha256())
        //for the token to be validated. There must be a Scope that has the same name as the ClientId field in IdentityServerBearerTokenAuthenticationOptions.
        //This is an API authenticates with IdentityServer
         ScopeSecrets = new List<Secret>
                         {
                              new Secret("api-secret".Sha256())
                         },
          Type = ScopeType.Resource
      }

因此,当资源服务器调用内省端点时,它将简单地使用范围秘密作为客户端秘密,使用范围名称作为客户端 ID。