diff --git a/src/OpenIddict.Abstractions/Descriptors/OpenIddictApplicationDescriptor.cs b/src/OpenIddict.Abstractions/Descriptors/OpenIddictApplicationDescriptor.cs index 399397d7..b1638f1b 100644 --- a/src/OpenIddict.Abstractions/Descriptors/OpenIddictApplicationDescriptor.cs +++ b/src/OpenIddict.Abstractions/Descriptors/OpenIddictApplicationDescriptor.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Text.Json; namespace OpenIddict.Abstractions { @@ -34,28 +35,32 @@ namespace OpenIddict.Abstractions /// /// Gets the localized display names associated with the application. /// - public Dictionary DisplayNames { get; } - = new Dictionary(); + public Dictionary DisplayNames { get; } = new(); /// /// Gets the permissions associated with the application. /// - public HashSet Permissions { get; } = new HashSet(StringComparer.Ordinal); + public HashSet Permissions { get; } = new(StringComparer.Ordinal); /// /// Gets the logout callback URLs associated with the application. /// - public HashSet PostLogoutRedirectUris { get; } = new HashSet(); + public HashSet PostLogoutRedirectUris { get; } = new(); + + /// + /// Gets the additional properties associated with the application. + /// + public Dictionary Properties { get; } = new(StringComparer.Ordinal); /// /// Gets the callback URLs associated with the application. /// - public HashSet RedirectUris { get; } = new HashSet(); + public HashSet RedirectUris { get; } = new(); /// /// Gets the requirements associated with the application. /// - public HashSet Requirements { get; } = new HashSet(StringComparer.Ordinal); + public HashSet Requirements { get; } = new(StringComparer.Ordinal); /// /// Gets or sets the application type associated with the application. diff --git a/src/OpenIddict.Abstractions/Descriptors/OpenIddictAuthorizationDescriptor.cs b/src/OpenIddict.Abstractions/Descriptors/OpenIddictAuthorizationDescriptor.cs index 88563153..9c038894 100644 --- a/src/OpenIddict.Abstractions/Descriptors/OpenIddictAuthorizationDescriptor.cs +++ b/src/OpenIddict.Abstractions/Descriptors/OpenIddictAuthorizationDescriptor.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Security.Claims; +using System.Text.Json; namespace OpenIddict.Abstractions { @@ -25,10 +26,15 @@ namespace OpenIddict.Abstractions /// public ClaimsPrincipal? Principal { get; set; } + /// + /// Gets the additional properties associated with the authorization. + /// + public Dictionary Properties { get; } = new(StringComparer.Ordinal); + /// /// Gets the scopes associated with the authorization. /// - public HashSet Scopes { get; } = new HashSet(StringComparer.Ordinal); + public HashSet Scopes { get; } = new(StringComparer.Ordinal); /// /// Gets or sets the status associated with the authorization. diff --git a/src/OpenIddict.Abstractions/Descriptors/OpenIddictScopeDescriptor.cs b/src/OpenIddict.Abstractions/Descriptors/OpenIddictScopeDescriptor.cs index 3ea35327..69ba8f5b 100644 --- a/src/OpenIddict.Abstractions/Descriptors/OpenIddictScopeDescriptor.cs +++ b/src/OpenIddict.Abstractions/Descriptors/OpenIddictScopeDescriptor.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Text.Json; namespace OpenIddict.Abstractions { @@ -17,7 +18,7 @@ namespace OpenIddict.Abstractions /// /// Gets the localized descriptions associated with the scope. /// - public Dictionary Descriptions { get; } = new Dictionary(); + public Dictionary Descriptions { get; } = new(); /// /// Gets or sets the display name associated with the scope. @@ -27,16 +28,21 @@ namespace OpenIddict.Abstractions /// /// Gets the localized display names associated with the scope. /// - public Dictionary DisplayNames { get; } = new Dictionary(); + public Dictionary DisplayNames { get; } = new(); /// /// Gets or sets the unique name associated with the scope. /// public string? Name { get; set; } + /// + /// Gets the additional properties associated with the scope. + /// + public Dictionary Properties { get; } = new(StringComparer.Ordinal); + /// /// Gets the resources associated with the scope. /// - public HashSet Resources { get; } = new HashSet(StringComparer.Ordinal); + public HashSet Resources { get; } = new(StringComparer.Ordinal); } } diff --git a/src/OpenIddict.Abstractions/Descriptors/OpenIddictTokenDescriptor.cs b/src/OpenIddict.Abstractions/Descriptors/OpenIddictTokenDescriptor.cs index f75d81f7..4c931407 100644 --- a/src/OpenIddict.Abstractions/Descriptors/OpenIddictTokenDescriptor.cs +++ b/src/OpenIddict.Abstractions/Descriptors/OpenIddictTokenDescriptor.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.Security.Claims; +using System.Text.Json; namespace OpenIddict.Abstractions { @@ -39,6 +41,11 @@ namespace OpenIddict.Abstractions /// public ClaimsPrincipal? Principal { get; set; } + /// + /// Gets the additional properties associated with the token. + /// + public Dictionary Properties { get; } = new(StringComparer.Ordinal); + /// /// Gets or sets the redemption date associated with the token. /// diff --git a/src/OpenIddict.Abstractions/Managers/IOpenIddictApplicationManager.cs b/src/OpenIddict.Abstractions/Managers/IOpenIddictApplicationManager.cs index a9ffaea0..be956652 100644 --- a/src/OpenIddict.Abstractions/Managers/IOpenIddictApplicationManager.cs +++ b/src/OpenIddict.Abstractions/Managers/IOpenIddictApplicationManager.cs @@ -10,6 +10,7 @@ using System.Collections.Immutable; using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -275,6 +276,17 @@ namespace OpenIddict.Abstractions /// ValueTask> GetPostLogoutRedirectUrisAsync(object application, CancellationToken cancellationToken = default); + /// + /// Retrieves the additional properties associated with an application. + /// + /// The application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the additional properties associated with the application. + /// + ValueTask> GetPropertiesAsync(object application, CancellationToken cancellationToken = default); + /// /// Retrieves the callback addresses associated with an application. /// diff --git a/src/OpenIddict.Abstractions/Managers/IOpenIddictAuthorizationManager.cs b/src/OpenIddict.Abstractions/Managers/IOpenIddictAuthorizationManager.cs index d8824a97..44d5e22f 100644 --- a/src/OpenIddict.Abstractions/Managers/IOpenIddictAuthorizationManager.cs +++ b/src/OpenIddict.Abstractions/Managers/IOpenIddictAuthorizationManager.cs @@ -10,6 +10,7 @@ using System.Collections.Immutable; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Security.Claims; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -232,6 +233,17 @@ namespace OpenIddict.Abstractions /// ValueTask GetIdAsync(object authorization, CancellationToken cancellationToken = default); + /// + /// Retrieves the additional properties associated with an authorization. + /// + /// The authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the additional properties associated with the authorization. + /// + ValueTask> GetPropertiesAsync(object authorization, CancellationToken cancellationToken = default); + /// /// Retrieves the scopes associated with an authorization. /// diff --git a/src/OpenIddict.Abstractions/Managers/IOpenIddictScopeManager.cs b/src/OpenIddict.Abstractions/Managers/IOpenIddictScopeManager.cs index d9107d94..bcfb9cd7 100644 --- a/src/OpenIddict.Abstractions/Managers/IOpenIddictScopeManager.cs +++ b/src/OpenIddict.Abstractions/Managers/IOpenIddictScopeManager.cs @@ -10,6 +10,7 @@ using System.Collections.Immutable; using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -264,6 +265,17 @@ namespace OpenIddict.Abstractions /// ValueTask GetNameAsync(object scope, CancellationToken cancellationToken = default); + /// + /// Retrieves the additional properties associated with a scope. + /// + /// The scope. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the additional properties associated with the scope. + /// + ValueTask> GetPropertiesAsync(object scope, CancellationToken cancellationToken = default); + /// /// Retrieves the resources associated with a scope. /// diff --git a/src/OpenIddict.Abstractions/Managers/IOpenIddictTokenManager.cs b/src/OpenIddict.Abstractions/Managers/IOpenIddictTokenManager.cs index 1acfe65c..d3d2cb43 100644 --- a/src/OpenIddict.Abstractions/Managers/IOpenIddictTokenManager.cs +++ b/src/OpenIddict.Abstractions/Managers/IOpenIddictTokenManager.cs @@ -6,8 +6,10 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.ComponentModel.DataAnnotations; using System.Linq; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -253,6 +255,17 @@ namespace OpenIddict.Abstractions /// ValueTask GetPayloadAsync(object token, CancellationToken cancellationToken = default); + /// + /// Retrieves the additional properties associated with a token. + /// + /// The token. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the additional properties associated with the token. + /// + ValueTask> GetPropertiesAsync(object token, CancellationToken cancellationToken = default); + /// /// Retrieves the redemption date associated with a token. /// diff --git a/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs b/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs index ee0d18c4..db0eb6dd 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs +++ b/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs @@ -15,6 +15,7 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Text; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -696,6 +697,26 @@ namespace OpenIddict.Core return Store.GetPostLogoutRedirectUrisAsync(application, cancellationToken); } + /// + /// Retrieves the additional properties associated with an application. + /// + /// The application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the additional properties associated with the application. + /// + public virtual ValueTask> GetPropertiesAsync( + TApplication application, CancellationToken cancellationToken = default) + { + if (application is null) + { + throw new ArgumentNullException(nameof(application)); + } + + return Store.GetPropertiesAsync(application, cancellationToken); + } + /// /// Retrieves the callback addresses associated with an application. /// @@ -909,6 +930,7 @@ namespace OpenIddict.Core await Store.SetPermissionsAsync(application, descriptor.Permissions.ToImmutableArray(), cancellationToken); await Store.SetPostLogoutRedirectUrisAsync(application, ImmutableArray.CreateRange( descriptor.PostLogoutRedirectUris.Select(address => address.OriginalString)), cancellationToken); + await Store.SetPropertiesAsync(application, descriptor.Properties.ToImmutableDictionary(), cancellationToken); await Store.SetRedirectUrisAsync(application, ImmutableArray.CreateRange( descriptor.RedirectUris.Select(address => address.OriginalString)), cancellationToken); await Store.SetRequirementsAsync(application, descriptor.Requirements.ToImmutableArray(), cancellationToken); @@ -971,6 +993,12 @@ namespace OpenIddict.Core descriptor.PostLogoutRedirectUris.Add(uri); } + descriptor.Properties.Clear(); + foreach (var pair in await Store.GetPropertiesAsync(application, cancellationToken)) + { + descriptor.Properties.Add(pair.Key, pair.Value); + } + descriptor.RedirectUris.Clear(); foreach (var address in await Store.GetRedirectUrisAsync(application, cancellationToken)) { @@ -1581,6 +1609,10 @@ namespace OpenIddict.Core ValueTask> IOpenIddictApplicationManager.GetPostLogoutRedirectUrisAsync(object application, CancellationToken cancellationToken) => GetPostLogoutRedirectUrisAsync((TApplication) application, cancellationToken); + /// + ValueTask> IOpenIddictApplicationManager.GetPropertiesAsync(object application, CancellationToken cancellationToken) + => GetPropertiesAsync((TApplication) application, cancellationToken); + /// ValueTask> IOpenIddictApplicationManager.GetRedirectUrisAsync(object application, CancellationToken cancellationToken) => GetRedirectUrisAsync((TApplication) application, cancellationToken); diff --git a/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs b/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs index 3851ff2a..2ee0b741 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs +++ b/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs @@ -12,6 +12,7 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Security.Claims; using System.Text; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -714,6 +715,26 @@ namespace OpenIddict.Core return Store.GetIdAsync(authorization, cancellationToken); } + /// + /// Retrieves the additional properties associated with an authorization. + /// + /// The authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the additional properties associated with the authorization. + /// + public virtual ValueTask> GetPropertiesAsync( + TAuthorization authorization, CancellationToken cancellationToken = default) + { + if (authorization is null) + { + throw new ArgumentNullException(nameof(authorization)); + } + + return Store.GetPropertiesAsync(authorization, cancellationToken); + } + /// /// Retrieves the scopes associated with an authorization. /// @@ -933,6 +954,7 @@ namespace OpenIddict.Core await Store.SetApplicationIdAsync(authorization, descriptor.ApplicationId, cancellationToken); await Store.SetCreationDateAsync(authorization, descriptor.CreationDate, cancellationToken); + await Store.SetPropertiesAsync(authorization, descriptor.Properties.ToImmutableDictionary(), cancellationToken); await Store.SetScopesAsync(authorization, descriptor.Scopes.ToImmutableArray(), cancellationToken); await Store.SetStatusAsync(authorization, descriptor.Status, cancellationToken); await Store.SetSubjectAsync(authorization, descriptor.Subject, cancellationToken); @@ -969,6 +991,12 @@ namespace OpenIddict.Core descriptor.Status = await Store.GetStatusAsync(authorization, cancellationToken); descriptor.Subject = await Store.GetSubjectAsync(authorization, cancellationToken); descriptor.Type = await Store.GetTypeAsync(authorization, cancellationToken); + + descriptor.Properties.Clear(); + foreach (var pair in await Store.GetPropertiesAsync(authorization, cancellationToken)) + { + descriptor.Properties.Add(pair.Key, pair.Value); + } } /// @@ -1231,6 +1259,10 @@ namespace OpenIddict.Core ValueTask IOpenIddictAuthorizationManager.GetIdAsync(object authorization, CancellationToken cancellationToken) => GetIdAsync((TAuthorization) authorization, cancellationToken); + /// + ValueTask> IOpenIddictAuthorizationManager.GetPropertiesAsync(object authorization, CancellationToken cancellationToken) + => GetPropertiesAsync((TAuthorization) authorization, cancellationToken); + /// ValueTask> IOpenIddictAuthorizationManager.GetScopesAsync(object authorization, CancellationToken cancellationToken) => GetScopesAsync((TAuthorization) authorization, cancellationToken); diff --git a/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs b/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs index 77acd25e..ea7d9ca5 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs +++ b/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs @@ -12,6 +12,7 @@ using System.Globalization; using System.Linq; using System.Runtime.CompilerServices; using System.Text; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -650,6 +651,26 @@ namespace OpenIddict.Core return Store.GetNameAsync(scope, cancellationToken); } + /// + /// Retrieves the additional properties associated with a scope. + /// + /// The scope. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the additional properties associated with the scope. + /// + public virtual ValueTask> GetPropertiesAsync( + TScope scope, CancellationToken cancellationToken = default) + { + if (scope is null) + { + throw new ArgumentNullException(nameof(scope)); + } + + return Store.GetPropertiesAsync(scope, cancellationToken); + } + /// /// Retrieves the resources associated with a scope. /// @@ -769,6 +790,7 @@ namespace OpenIddict.Core await Store.SetDisplayNameAsync(scope, descriptor.DisplayName, cancellationToken); await Store.SetDisplayNamesAsync(scope, descriptor.DisplayNames.ToImmutableDictionary(), cancellationToken); await Store.SetNameAsync(scope, descriptor.Name, cancellationToken); + await Store.SetPropertiesAsync(scope, descriptor.Properties.ToImmutableDictionary(), cancellationToken); await Store.SetResourcesAsync(scope, descriptor.Resources.ToImmutableArray(), cancellationToken); } @@ -812,6 +834,12 @@ namespace OpenIddict.Core { descriptor.Descriptions.Add(pair.Key, pair.Value); } + + descriptor.Properties.Clear(); + foreach (var pair in await Store.GetPropertiesAsync(scope, cancellationToken)) + { + descriptor.Properties.Add(pair.Key, pair.Value); + } } /// @@ -1019,6 +1047,10 @@ namespace OpenIddict.Core ValueTask IOpenIddictScopeManager.GetNameAsync(object scope, CancellationToken cancellationToken) => GetNameAsync((TScope) scope, cancellationToken); + /// + ValueTask> IOpenIddictScopeManager.GetPropertiesAsync(object scope, CancellationToken cancellationToken) + => GetPropertiesAsync((TScope) scope, cancellationToken); + /// ValueTask> IOpenIddictScopeManager.GetResourcesAsync(object scope, CancellationToken cancellationToken) => GetResourcesAsync((TScope) scope, cancellationToken); diff --git a/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs b/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs index 7282a343..dc5f363a 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs +++ b/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs @@ -12,6 +12,7 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Text; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -736,6 +737,26 @@ namespace OpenIddict.Core return Store.GetPayloadAsync(token, cancellationToken); } + /// + /// Retrieves the additional properties associated with a token. + /// + /// The token. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the additional properties associated with the token. + /// + public virtual ValueTask> GetPropertiesAsync( + TToken token, CancellationToken cancellationToken = default) + { + if (token is null) + { + throw new ArgumentNullException(nameof(token)); + } + + return Store.GetPropertiesAsync(token, cancellationToken); + } + /// /// Retrieves the redemption date associated with a token. /// @@ -954,6 +975,7 @@ namespace OpenIddict.Core await Store.SetCreationDateAsync(token, descriptor.CreationDate, cancellationToken); await Store.SetExpirationDateAsync(token, descriptor.ExpirationDate, cancellationToken); await Store.SetPayloadAsync(token, descriptor.Payload, cancellationToken); + await Store.SetPropertiesAsync(token, descriptor.Properties.ToImmutableDictionary(), cancellationToken); await Store.SetRedemptionDateAsync(token, descriptor.RedemptionDate, cancellationToken); await Store.SetReferenceIdAsync(token, descriptor.ReferenceId, cancellationToken); await Store.SetStatusAsync(token, descriptor.Status, cancellationToken); @@ -994,6 +1016,12 @@ namespace OpenIddict.Core descriptor.Status = await Store.GetStatusAsync(token, cancellationToken); descriptor.Subject = await Store.GetSubjectAsync(token, cancellationToken); descriptor.Type = await Store.GetTypeAsync(token, cancellationToken); + + descriptor.Properties.Clear(); + foreach (var pair in await Store.GetPropertiesAsync(token, cancellationToken)) + { + descriptor.Properties.Add(pair.Key, pair.Value); + } } /// @@ -1370,6 +1398,10 @@ namespace OpenIddict.Core ValueTask IOpenIddictTokenManager.GetPayloadAsync(object token, CancellationToken cancellationToken) => GetPayloadAsync((TToken) token, cancellationToken); + /// + ValueTask> IOpenIddictTokenManager.GetPropertiesAsync(object token, CancellationToken cancellationToken) + => GetPropertiesAsync((TToken) token, cancellationToken); + /// ValueTask IOpenIddictTokenManager.GetRedemptionDateAsync(object token, CancellationToken cancellationToken) => GetRedemptionDateAsync((TToken) token, cancellationToken);