项目
版本

OpenIddict 声明目标

在从登录操作期间指定的 ClaimsPrincipal 生成授权码、刷新令牌和设备/用户代码时OpenIddict 会自动将所有声明复制到生成的代码/令牌中。这是一个安全的操作,因为这些令牌始终是加密的,除了 OpenIddict 本身外,任何人都无法读取(请求它们的用户或客户端应用程序无法阅读其内容)。

而对于访问令牌和身份令牌,工作方式有所不同,因为这些令牌旨在被不同的方阅读:

  • 客户端应用程序完全有权访问他们收到的身份令牌中所包含的声明。
  • 资源服务器应能够读取 API 调用中使用的访问令牌中所包含的声明。
  • 对于桌面、移动或基于浏览器的应用程序,用户访问身份令牌(例如,通过 Fiddler 拦截 HTTP 响应、使用开发者工具或转储客户端进程的内存)通常并不困难。
  • 如果明确禁用了访问令牌的加密,那么客户端应用程序或用户自己就有可能访问访问令牌的内容(例如,通过复制令牌负载并使用像 jwt.io 这样的工具)。

基于这些原因,OpenIddict 不会自动将附加到 ClaimsPrincipal 的声明复制到访问令牌或身份令牌中(除非是 sub 声明,它是 OpenIddict 中唯一强制性的声明)。要允许 OpenIddict 将特定声明持久化到访问或身份令牌中,必须向每个你想要公开的 Claim 实例添加一个称为“声明目标”的标志。

要为一个声明附加一个或多个目标,使用在 OpenIddict.Abstractions 中定义的 principal.SetDestinations() 扩展方法。在典型情况下,授予的范围可用于确定哪些声明被允许复制到访问和身份令牌中,如下例所示。

var principal = await _signInManager.CreateUserPrincipalAsync(user);

// Note: in this sample, the granted scopes match the requested scope
// but you may want to allow the user to uncheck specific scopes.
// For that, simply restrict the list of scopes before calling SetScopes().
principal.SetScopes(request.GetScopes());
principal.SetResources(await _scopeManager.ListResourcesAsync(principal.GetScopes()).ToListAsync());
principal.SetDestinations(static claim => claim.Type switch
{
    // If the "profile" scope was granted, allow the "name" claim to be
    // added to the access and identity tokens derived from the principal.
    Claims.Name when claim.Subject.HasScope(Scopes.Profile) =>
    [
        OpenIddictConstants.Destinations.AccessToken,
        OpenIddictConstants.Destinations.IdentityToken
    ],

    // Never add the "secret_value" claim to access or identity tokens.
    // In this case, it will only be added to authorization codes,
    // refresh tokens and user/device codes, that are always encrypted.
    "secret_value" => [],

    // Otherwise, add the claim to the access tokens only.
    _ => [OpenIddictConstants.Destinations.AccessToken]
});

return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
在本文档中