令牌中的自定义属性

custom properties within token

我发现 OpenIddictTokenPropertiesPayload 字段。据我了解,可以由自定义数据填充,这些数据将保留在数据库中但不会发送给客户端。但是我找不到我应该如何 write/read 这些属性?我看到我可以为 AuthenticationTicket 提供自定义属性,但它似乎是完全不同的属性。 使用这些属性的正确方法是什么?

Properties 列 - 所有 OpenIddict 实体共有 - 确实意味着用作非基本属性的通用包,它允许存储数据而无需更改模式。使用默认管理器不能直接访问属性。相反,我们鼓励您创建自己的从内置管理器派生的管理器,并使用 Store.GetPropertiesAsync()/Store.SetPropertiesAsync() 访问属性。

OrchardCore 的 OpenID 模块有一个自定义应用程序管理器,使用它来存储应用程序角色,因此您可以查看源代码以了解它们的使用方式:https://github.com/OrchardCMS/OrchardCore/blob/dev/src/OrchardCore/OrchardCore.OpenId.Core/Services/Managers/OpenIdApplicationManager.cs#L86-L92

注意:在 OpenIddict 3.0 中,Store.GetPropertiesAsync()/Store.SetPropertiesAsync() 更新为使用 System.Text.Json 而不是 JSON.NET。


Payload 列用于存储引用标记,并不意味着用于存储其他数据。


值得注意的是,如果您想存储将保密的数据,有一个简单的选项:如果您不将访问 token/identity 令牌目的地添加到您的私人声明中,它们将不会保留在 access/identity 令牌中,并且只会出现在授权 codes/refresh 令牌中,这些令牌始终是加密的,客户端无法读取。

真的,OpenIddictAuthorizationManager 的行为确实很奇怪 PopulateAsync function:

await Store.SetApplicationIdAsync(authorization, descriptor.ApplicationId, cancellationToken);
await Store.SetScopesAsync(authorization, ImmutableArray.CreateRange(descriptor.Scopes), cancellationToken);
await Store.SetStatusAsync(authorization, descriptor.Status, cancellationToken);
await Store.SetSubjectAsync(authorization, descriptor.Subject, cancellationToken);
await Store.SetTypeAsync(authorization, descriptor.Type, cancellationToken);

它填充除属性之外的所有内容。所以在这里我做了什么来持久化数据库中的属性。首先我在授权阶段添加了我需要的属性 /connect/authorize:

var ticket = new AuthenticationTicket(
  principal,
  new AuthenticationProperties(new Dictionary<string, string>{ { "name", "value" } }),
  OpenIddictServerDefaults.AuthenticationScheme);

然后按照上面答案中的建议,我创建了自己的小型授权管理器:

public class AuthorizationManager<TAuthorization>: OpenIddictAuthorizationManager<TAuthorization> where TAuthorization : OpenIddict.MongoDb.Models.OpenIddictAuthorization
    {
        public AuthorizationManager(...): base(cache, resolver, logger, options)
        {
        }

        public async override Task PopulateAsync(
            [NotNull] TAuthorization authorization,
            [NotNull] OpenIddictAuthorizationDescriptor descriptor,
            CancellationToken cancellationToken = default)
        {
            await base.PopulateAsync(authorization, descriptor, cancellationToken);
            if (descriptor.Properties.Any())
            {
                authorization.Properties = new MongoDB.Bson.BsonDocument(
                    descriptor.Properties.Where(p => p.Key[0] != '.') // skip scopes and other technical fields
                    .Select(p => new MongoDB.Bson.BsonElement(p.Key, p.Value))
                    );
            }
        }
    }

我在其中填充了所有属性。最后我刚刚启用了我的经理:

options.ReplaceAuthorizationManager<Services.OpenId.AuthorizationManager<OpenIddictAuthorization>>();