diff --git a/src/OpenIddict.Core/Descriptors/OpenIddictApplicationDescriptor.cs b/src/OpenIddict.Abstractions/Descriptors/OpenIddictApplicationDescriptor.cs similarity index 98% rename from src/OpenIddict.Core/Descriptors/OpenIddictApplicationDescriptor.cs rename to src/OpenIddict.Abstractions/Descriptors/OpenIddictApplicationDescriptor.cs index ad68de3d..94864d2e 100644 --- a/src/OpenIddict.Core/Descriptors/OpenIddictApplicationDescriptor.cs +++ b/src/OpenIddict.Abstractions/Descriptors/OpenIddictApplicationDescriptor.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace OpenIddict.Core +namespace OpenIddict.Abstractions { /// /// Represents an OpenIddict application descriptor. diff --git a/src/OpenIddict.Core/Descriptors/OpenIddictAuthorizationDescriptor.cs b/src/OpenIddict.Abstractions/Descriptors/OpenIddictAuthorizationDescriptor.cs similarity index 98% rename from src/OpenIddict.Core/Descriptors/OpenIddictAuthorizationDescriptor.cs rename to src/OpenIddict.Abstractions/Descriptors/OpenIddictAuthorizationDescriptor.cs index a34603f9..62247fd6 100644 --- a/src/OpenIddict.Core/Descriptors/OpenIddictAuthorizationDescriptor.cs +++ b/src/OpenIddict.Abstractions/Descriptors/OpenIddictAuthorizationDescriptor.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Security.Claims; -namespace OpenIddict.Core +namespace OpenIddict.Abstractions { /// /// Represents an OpenIddict authorization descriptor. diff --git a/src/OpenIddict.Core/Descriptors/OpenIddictScopeDescriptor.cs b/src/OpenIddict.Abstractions/Descriptors/OpenIddictScopeDescriptor.cs similarity index 96% rename from src/OpenIddict.Core/Descriptors/OpenIddictScopeDescriptor.cs rename to src/OpenIddict.Abstractions/Descriptors/OpenIddictScopeDescriptor.cs index 01b41d12..fedf6881 100644 --- a/src/OpenIddict.Core/Descriptors/OpenIddictScopeDescriptor.cs +++ b/src/OpenIddict.Abstractions/Descriptors/OpenIddictScopeDescriptor.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace OpenIddict.Core +namespace OpenIddict.Abstractions { /// /// Represents an OpenIddict scope descriptor. diff --git a/src/OpenIddict.Core/Descriptors/OpenIddictTokenDescriptor.cs b/src/OpenIddict.Abstractions/Descriptors/OpenIddictTokenDescriptor.cs similarity index 98% rename from src/OpenIddict.Core/Descriptors/OpenIddictTokenDescriptor.cs rename to src/OpenIddict.Abstractions/Descriptors/OpenIddictTokenDescriptor.cs index 53fdb819..e9b059df 100644 --- a/src/OpenIddict.Core/Descriptors/OpenIddictTokenDescriptor.cs +++ b/src/OpenIddict.Abstractions/Descriptors/OpenIddictTokenDescriptor.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Security.Claims; -namespace OpenIddict.Core +namespace OpenIddict.Abstractions { /// /// Represents an OpenIddict token descriptor. diff --git a/src/OpenIddict.Abstractions/Managers/IOpenIddictApplicationManager.cs b/src/OpenIddict.Abstractions/Managers/IOpenIddictApplicationManager.cs new file mode 100644 index 00000000..26b2aa87 --- /dev/null +++ b/src/OpenIddict.Abstractions/Managers/IOpenIddictApplicationManager.cs @@ -0,0 +1,421 @@ +using System; +using System.Collections.Immutable; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using JetBrains.Annotations; + +namespace OpenIddict.Abstractions +{ + /// + /// Provides methods allowing to manage the applications stored in the store. + /// Note: this interface is not meant to be implemented by custom managers, + /// that should inherit from the generic OpenIddictApplicationManager class. + /// It is primarily intended to be used by services that cannot easily depend + /// on the generic application manager. The actual application entity type + /// is automatically determined at runtime based on the OpenIddict core options. + /// + public interface IOpenIddictApplicationManager + { + /// + /// Determines the number of applications that exist in the database. + /// + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the number of applications in the database. + /// + Task CountAsync(CancellationToken cancellationToken = default); + + /// + /// Determines the number of applications that match the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the number of applications that match the specified query. + /// + Task CountAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken = default); + + /// + /// Creates a new application based on the specified descriptor. + /// Note: the default implementation automatically hashes the client + /// secret before storing it in the database, for security reasons. + /// + /// The application descriptor. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the unique identifier associated with the application. + /// + Task CreateAsync([NotNull] OpenIddictApplicationDescriptor descriptor, CancellationToken cancellationToken = default); + + /// + /// Creates a new application. + /// + /// The application to create. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task CreateAsync([NotNull] object application, CancellationToken cancellationToken = default); + + /// + /// Creates a new application. + /// Note: the default implementation automatically hashes the client + /// secret before storing it in the database, for security reasons. + /// + /// The application to create. + /// The client secret associated with the application, if applicable. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task CreateAsync([NotNull] object application, [CanBeNull] string secret, CancellationToken cancellationToken = default); + + /// + /// Removes an existing application. + /// + /// The application to delete. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task DeleteAsync([NotNull] object application, CancellationToken cancellationToken = default); + + /// + /// Retrieves an application using its client identifier. + /// + /// The client identifier associated with the application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the client application corresponding to the identifier. + /// + Task FindByClientIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default); + + /// + /// Retrieves an application using its unique identifier. + /// + /// The unique identifier associated with the application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the client application corresponding to the identifier. + /// + Task FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default); + + /// + /// Retrieves all the applications associated with the specified post_logout_redirect_uri. + /// + /// The post_logout_redirect_uri associated with the applications. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, whose result + /// returns the client applications corresponding to the specified post_logout_redirect_uri. + /// + Task> FindByPostLogoutRedirectUriAsync([NotNull] string address, CancellationToken cancellationToken = default); + + /// + /// Retrieves all the applications associated with the specified redirect_uri. + /// + /// The redirect_uri associated with the applications. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, whose result + /// returns the client applications corresponding to the specified redirect_uri. + /// + Task> FindByRedirectUriAsync([NotNull] string address, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns the first element. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the first element returned when executing the query. + /// + Task GetAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns the first element. + /// + /// The state type. + /// The result type. + /// The query to execute. + /// The optional state. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the first element returned when executing the query. + /// + Task GetAsync([NotNull] Func, TState, IQueryable> query, [CanBeNull] TState state, CancellationToken cancellationToken = default); + + /// + /// Retrieves the client identifier 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 the client identifier associated with the application. + /// + ValueTask GetClientIdAsync([NotNull] object application, CancellationToken cancellationToken = default); + + /// + /// Retrieves the client type 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 the client type of the application (by default, "public"). + /// + ValueTask GetClientTypeAsync([NotNull] object application, CancellationToken cancellationToken = default); + + /// + /// Retrieves the consent type 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 the consent type of the application (by default, "explicit"). + /// + ValueTask GetConsentTypeAsync([NotNull] object application, CancellationToken cancellationToken = default); + + /// + /// Retrieves the display name 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 the display name associated with the application. + /// + ValueTask GetDisplayNameAsync([NotNull] object application, CancellationToken cancellationToken = default); + + /// + /// Retrieves the unique identifier 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 the unique identifier associated with the application. + /// + ValueTask GetIdAsync([NotNull] object application, CancellationToken cancellationToken = default); + + /// + /// Retrieves the permissions 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 permissions associated with the application. + /// + ValueTask> GetPermissionsAsync([NotNull] object application, CancellationToken cancellationToken = default); + + /// + /// Retrieves the logout callback addresses 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 post_logout_redirect_uri associated with the application. + /// + ValueTask> GetPostLogoutRedirectUrisAsync([NotNull] object application, CancellationToken cancellationToken = default); + + /// + /// Retrieves the callback addresses 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 redirect_uri associated with the application. + /// + ValueTask> GetRedirectUrisAsync([NotNull] object application, CancellationToken cancellationToken = default); + + /// + /// Determines whether the specified permission has been granted to the application. + /// + /// The application. + /// The permission. + /// The that can be used to abort the operation. + /// true if the application has been granted the specified permission, false otherwise. + Task HasPermissionAsync([NotNull] object application, [NotNull] string permission, CancellationToken cancellationToken = default); + + /// + /// Determines whether an application is a confidential client. + /// + /// The application. + /// The that can be used to abort the operation. + /// true if the application is a confidential client, false otherwise. + Task IsConfidentialAsync([NotNull] object application, CancellationToken cancellationToken = default); + + /// + /// Determines whether an application is a hybrid client. + /// + /// The application. + /// The that can be used to abort the operation. + /// true if the application is a hybrid client, false otherwise. + Task IsHybridAsync([NotNull] object application, CancellationToken cancellationToken = default); + + /// + /// Determines whether an application is a public client. + /// + /// The application. + /// The that can be used to abort the operation. + /// true if the application is a public client, false otherwise. + Task IsPublicAsync([NotNull] object application, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns all the corresponding elements. + /// + /// The number of results to return. + /// The number of results to skip. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + Task> ListAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns all the corresponding elements. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + Task> ListAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns all the corresponding elements. + /// + /// The state type. + /// The result type. + /// The query to execute. + /// The optional state. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + Task> ListAsync([NotNull] Func, TState, IQueryable> query, [CanBeNull] TState state, CancellationToken cancellationToken = default); + + /// + /// Populates the specified descriptor using the properties exposed by the application. + /// + /// The descriptor. + /// The application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task PopulateAsync([NotNull] OpenIddictApplicationDescriptor descriptor, [NotNull] object application, CancellationToken cancellationToken = default); + + /// + /// Populates the application using the specified descriptor. + /// + /// The application. + /// The descriptor. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task PopulateAsync([NotNull] object application, [NotNull] OpenIddictApplicationDescriptor descriptor, CancellationToken cancellationToken = default); + + /// + /// Updates an existing application. + /// + /// The application to update. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task UpdateAsync([NotNull] object application, CancellationToken cancellationToken = default); + + /// + /// Updates an existing application. + /// + /// The application to update. + /// The descriptor used to update the application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task UpdateAsync([NotNull] object application, [NotNull] OpenIddictApplicationDescriptor descriptor, CancellationToken cancellationToken = default); + + /// + /// Updates an existing application and replaces the existing secret. + /// Note: the default implementation automatically hashes the client + /// secret before storing it in the database, for security reasons. + /// + /// The application to update. + /// The client secret associated with the application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task UpdateAsync([NotNull] object application, [CanBeNull] string secret, CancellationToken cancellationToken = default); + + /// + /// Validates the application to ensure it's in a consistent state. + /// + /// The application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the validation error encountered when validating the application. + /// + Task> ValidateAsync([NotNull] object application, CancellationToken cancellationToken = default); + + /// + /// Validates the client_secret associated with an application. + /// + /// The application. + /// The secret that should be compared to the client_secret stored in the database. + /// The that can be used to abort the operation. + /// A that can be used to monitor the asynchronous operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns a boolean indicating whether the client secret was valid. + /// + Task ValidateClientSecretAsync([NotNull] object application, string secret, CancellationToken cancellationToken = default); + + /// + /// Validates the specified post_logout_redirect_uri. + /// + /// The address that should be compared to the post_logout_redirect_uri stored in the database. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, whose result + /// returns a boolean indicating whether the post_logout_redirect_uri was valid. + /// + Task ValidatePostLogoutRedirectUriAsync([NotNull] string address, CancellationToken cancellationToken = default); + + /// + /// Validates the redirect_uri to ensure it's associated with an application. + /// + /// The application. + /// The address that should be compared to one of the redirect_uri stored in the database. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns a boolean indicating whether the redirect_uri was valid. + /// + Task ValidateRedirectUriAsync([NotNull] object application, [NotNull] string address, CancellationToken cancellationToken = default); + } +} diff --git a/src/OpenIddict.Abstractions/Managers/IOpenIddictAuthorizationManager.cs b/src/OpenIddict.Abstractions/Managers/IOpenIddictAuthorizationManager.cs new file mode 100644 index 00000000..5a848f6b --- /dev/null +++ b/src/OpenIddict.Abstractions/Managers/IOpenIddictAuthorizationManager.cs @@ -0,0 +1,419 @@ +using System; +using System.Collections.Immutable; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Security.Claims; +using System.Threading; +using System.Threading.Tasks; +using JetBrains.Annotations; + +namespace OpenIddict.Abstractions +{ + /// + /// Provides methods allowing to manage the authorizations stored in the store. + /// Note: this interface is not meant to be implemented by custom managers, + /// that should inherit from the generic OpenIddictAuthorizationManager class. + /// It is primarily intended to be used by services that cannot easily depend + /// on the generic authorization manager. The actual authorization entity type + /// is automatically determined at runtime based on the OpenIddict core options. + /// + public interface IOpenIddictAuthorizationManager + { + /// + /// Determines the number of authorizations that exist in the database. + /// + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the number of authorizations in the database. + /// + Task CountAsync(CancellationToken cancellationToken = default); + + /// + /// Determines the number of authorizations that match the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the number of authorizations that match the specified query. + /// + Task CountAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken = default); + + /// + /// Creates a new permanent authorization based on the specified parameters. + /// + /// The principal associated with the authorization. + /// The subject associated with the authorization. + /// The client associated with the authorization. + /// The authorization type. + /// The minimal scopes associated with the authorization. + /// The authentication properties associated with the authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, whose result returns the authorization. + /// + Task CreateAsync([NotNull] ClaimsPrincipal principal, [NotNull] string subject, [NotNull] string client, [NotNull] string type, ImmutableArray scopes, [CanBeNull] ImmutableDictionary properties, CancellationToken cancellationToken = default); + + /// + /// Creates a new authorization based on the specified descriptor. + /// + /// The authorization descriptor. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, whose result returns the authorization. + /// + Task CreateAsync([NotNull] OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken = default); + + /// + /// Creates a new authorization. + /// + /// The application to create. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task CreateAsync([NotNull] object authorization, CancellationToken cancellationToken = default); + + /// + /// Removes an existing authorization. + /// + /// The authorization to delete. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task DeleteAsync([NotNull] object authorization, CancellationToken cancellationToken = default); + + /// + /// Retrieves the authorizations corresponding to the specified + /// subject and associated with the application identifier. + /// + /// The subject associated with the authorization. + /// The client associated with the authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the authorizations corresponding to the subject/client. + /// + Task> FindAsync([NotNull] string subject, [NotNull] string client, CancellationToken cancellationToken = default); + + /// + /// Retrieves the authorizations matching the specified parameters. + /// + /// The subject associated with the authorization. + /// The client associated with the authorization. + /// The authorization status. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the authorizations corresponding to the criteria. + /// + Task> FindAsync([NotNull] string subject, [NotNull] string client, [NotNull] string status, CancellationToken cancellationToken); + + /// + /// Retrieves the authorizations matching the specified parameters. + /// + /// The subject associated with the authorization. + /// The client associated with the authorization. + /// The authorization status. + /// The authorization type. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the authorizations corresponding to the criteria. + /// + Task> FindAsync([NotNull] string subject, [NotNull] string client, [NotNull] string status, [NotNull] string type, CancellationToken cancellationToken = default); + + /// + /// Retrieves the authorizations matching the specified parameters. + /// + /// The subject associated with the authorization. + /// The client associated with the authorization. + /// The authorization status. + /// The authorization type. + /// The minimal scopes associated with the authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the authorizations corresponding to the criteria. + /// + Task> FindAsync([NotNull] string subject, [NotNull] string client, [NotNull] string status, [NotNull] string type, ImmutableArray scopes, CancellationToken cancellationToken = default); + + /// + /// Retrieves an authorization using its unique identifier. + /// + /// The unique identifier associated with the authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the authorization corresponding to the identifier. + /// + Task FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default); + + /// + /// Retrieves all the authorizations corresponding to the specified subject. + /// + /// The subject associated with the authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the authorizations corresponding to the specified subject. + /// + Task> FindBySubjectAsync([NotNull] string subject, CancellationToken cancellationToken = default); + + /// + /// Retrieves the optional application identifier 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 the application identifier associated with the authorization. + /// + ValueTask GetApplicationIdAsync([NotNull] object authorization, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns the first element. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the first element returned when executing the query. + /// + Task GetAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns the first element. + /// + /// The state type. + /// The result type. + /// The query to execute. + /// The optional state. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the first element returned when executing the query. + /// + Task GetAsync([NotNull] Func, TState, IQueryable> query, [CanBeNull] TState state, CancellationToken cancellationToken = default); + + /// + /// Retrieves the unique identifier 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 the unique identifier associated with the authorization. + /// + ValueTask GetIdAsync([NotNull] object authorization, CancellationToken cancellationToken = default); + + /// + /// Retrieves the scopes 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 the scopes associated with the specified authorization. + /// + ValueTask> GetScopesAsync([NotNull] object authorization, CancellationToken cancellationToken = default); + + /// + /// Retrieves the status 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 the status associated with the specified authorization. + /// + ValueTask GetStatusAsync([NotNull] object authorization, CancellationToken cancellationToken = default); + + /// + /// Retrieves the subject 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 the subject associated with the specified authorization. + /// + ValueTask GetSubjectAsync([NotNull] object authorization, CancellationToken cancellationToken = default); + + /// + /// Retrieves the type 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 the type associated with the specified authorization. + /// + ValueTask GetTypeAsync([NotNull] object authorization, CancellationToken cancellationToken = default); + + /// + /// Determines whether the specified scopes are included in the authorization. + /// + /// The authorization. + /// The scopes. + /// The that can be used to abort the operation. + /// true if the scopes are included in the authorization, false otherwise. + Task HasScopesAsync([NotNull] object authorization, ImmutableArray scopes, CancellationToken cancellationToken = default); + + /// + /// Determines whether a given authorization is ad hoc. + /// + /// The authorization. + /// The that can be used to abort the operation. + /// true if the authorization is ad hoc, false otherwise. + Task IsAdHocAsync([NotNull] object authorization, CancellationToken cancellationToken = default); + + /// + /// Determines whether a given authorization is permanent. + /// + /// The authorization. + /// The that can be used to abort the operation. + /// true if the authorization is permanent, false otherwise. + Task IsPermanentAsync([NotNull] object authorization, CancellationToken cancellationToken = default); + + /// + /// Determines whether a given authorization has been revoked. + /// + /// The authorization. + /// The that can be used to abort the operation. + /// true if the authorization has been revoked, false otherwise. + Task IsRevokedAsync([NotNull] object authorization, CancellationToken cancellationToken = default); + + /// + /// Determines whether a given authorization is valid. + /// + /// The authorization. + /// The that can be used to abort the operation. + /// true if the authorization is valid, false otherwise. + Task IsValidAsync([NotNull] object authorization, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns all the corresponding elements. + /// + /// The number of results to return. + /// The number of results to skip. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + Task> ListAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns all the corresponding elements. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + Task> ListAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns all the corresponding elements. + /// + /// The state type. + /// The result type. + /// The query to execute. + /// The optional state. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + Task> ListAsync([NotNull] Func, TState, IQueryable> query, [CanBeNull] TState state, CancellationToken cancellationToken = default); + + /// + /// Populates the specified descriptor using the properties exposed by the authorization. + /// + /// The descriptor. + /// The authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task PopulateAsync([NotNull] OpenIddictAuthorizationDescriptor descriptor, [NotNull] object authorization, CancellationToken cancellationToken = default); + + /// + /// Populates the authorization using the specified descriptor. + /// + /// The authorization. + /// The descriptor. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task PopulateAsync([NotNull] object authorization, [NotNull] OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken = default); + + /// + /// Removes the ad-hoc authorizations that are marked as invalid or have no valid token attached. + /// + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task PruneAsync(CancellationToken cancellationToken = default); + + /// + /// Revokes an authorization. + /// + /// The authorization to revoke. + /// The that can be used to abort the operation. + /// A that can be used to monitor the asynchronous operation. + Task RevokeAsync([NotNull] object authorization, CancellationToken cancellationToken = default); + + /// + /// Sets the application identifier associated with an authorization. + /// + /// The authorization. + /// The unique identifier associated with the client application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task SetApplicationIdAsync([NotNull] object authorization, [CanBeNull] string identifier, CancellationToken cancellationToken = default); + + /// + /// Updates an existing authorization. + /// + /// The authorization to update. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task UpdateAsync([NotNull] object authorization, CancellationToken cancellationToken = default); + + /// + /// Updates an existing authorization. + /// + /// The authorization to update. + /// The descriptor used to update the authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task UpdateAsync([NotNull] object authorization, [NotNull] OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken = default); + + /// + /// Validates the authorization to ensure it's in a consistent state. + /// + /// The authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the validation error encountered when validating the authorization. + /// + Task> ValidateAsync([NotNull] object authorization, CancellationToken cancellationToken = default); + } +} diff --git a/src/OpenIddict.Abstractions/Managers/IOpenIddictScopeManager.cs b/src/OpenIddict.Abstractions/Managers/IOpenIddictScopeManager.cs new file mode 100644 index 00000000..fbecbaa4 --- /dev/null +++ b/src/OpenIddict.Abstractions/Managers/IOpenIddictScopeManager.cs @@ -0,0 +1,290 @@ +using System; +using System.Collections.Immutable; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using JetBrains.Annotations; + +namespace OpenIddict.Abstractions +{ + /// + /// Provides methods allowing to manage the scopes stored in the store. + /// Note: this interface is not meant to be implemented by custom managers, + /// that should inherit from the generic OpenIddictScopeManager class. + /// It is primarily intended to be used by services that cannot easily + /// depend on the generic scope manager. The actual scope entity type is + /// automatically determined at runtime based on the OpenIddict core options. + /// + public interface IOpenIddictScopeManager + { + /// + /// Determines the number of scopes that exist in the database. + /// + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the number of scopes in the database. + /// + Task CountAsync(CancellationToken cancellationToken = default); + + /// + /// Determines the number of scopes that match the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the number of scopes that match the specified query. + /// + Task CountAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken = default); + + /// + /// Creates a new scope based on the specified descriptor. + /// + /// The scope descriptor. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, whose result returns the scope. + /// + Task CreateAsync([NotNull] OpenIddictScopeDescriptor descriptor, CancellationToken cancellationToken = default); + + /// + /// Creates a new scope. + /// + /// The scope to create. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task CreateAsync([NotNull] object scope, CancellationToken cancellationToken = default); + + /// + /// Removes an existing scope. + /// + /// The scope to delete. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task DeleteAsync([NotNull] object scope, CancellationToken cancellationToken = default); + + /// + /// Retrieves a scope using its unique identifier. + /// + /// The unique identifier associated with the scope. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the scope corresponding to the identifier. + /// + Task FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default); + + /// + /// Retrieves a scope using its name. + /// + /// The name associated with the scope. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the scope corresponding to the specified name. + /// + Task FindByNameAsync([NotNull] string name, CancellationToken cancellationToken = default); + + /// + /// Retrieves a list of scopes using their name. + /// + /// The names associated with the scopes. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the scopes corresponding to the specified names. + /// + Task> FindByNamesAsync(ImmutableArray names, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns the first element. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the first element returned when executing the query. + /// + Task GetAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns the first element. + /// + /// The state type. + /// The result type. + /// The query to execute. + /// The optional state. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the first element returned when executing the query. + /// + Task GetAsync([NotNull] Func, TState, IQueryable> query, [CanBeNull] TState state, CancellationToken cancellationToken = default); + + /// + /// Retrieves the description 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 the description associated with the specified scope. + /// + ValueTask GetDescriptionAsync([NotNull] object scope, CancellationToken cancellationToken = default); + + /// + /// Retrieves the display name 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 the display name associated with the scope. + /// + ValueTask GetDisplayNameAsync([NotNull] object scope, CancellationToken cancellationToken = default); + + /// + /// Retrieves the unique identifier 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 the unique identifier associated with the scope. + /// + ValueTask GetIdAsync([NotNull] object scope, CancellationToken cancellationToken = default); + + /// + /// Retrieves the name 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 the name associated with the specified scope. + /// + ValueTask GetNameAsync([NotNull] object scope, CancellationToken cancellationToken = default); + + /// + /// Retrieves the resources 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 resources associated with the scope. + /// + ValueTask> GetResourcesAsync([NotNull] object scope, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns all the corresponding elements. + /// + /// The number of results to return. + /// The number of results to skip. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + Task> ListAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns all the corresponding elements. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + Task> ListAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns all the corresponding elements. + /// + /// The state type. + /// The result type. + /// The query to execute. + /// The optional state. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + Task> ListAsync([NotNull] Func, TState, IQueryable> query, [CanBeNull] TState state, CancellationToken cancellationToken = default); + + /// + /// Lists all the resources associated with the specified scopes. + /// + /// The scopes. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the resources associated with the specified scopes. + /// + Task> ListResourcesAsync(ImmutableArray scopes, CancellationToken cancellationToken = default); + + /// + /// Populates the specified descriptor using the properties exposed by the scope. + /// + /// The descriptor. + /// The scope. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task PopulateAsync([NotNull] OpenIddictScopeDescriptor descriptor, [NotNull] object scope, CancellationToken cancellationToken = default); + + /// + /// Populates the scope using the specified descriptor. + /// + /// The scope. + /// The descriptor. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task PopulateAsync([NotNull] object scope, [NotNull] OpenIddictScopeDescriptor descriptor, CancellationToken cancellationToken = default); + + /// + /// Updates an existing scope. + /// + /// The scope to update. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task UpdateAsync([NotNull] object scope, CancellationToken cancellationToken = default); + + /// + /// Updates an existing scope. + /// + /// The scope to update. + /// The descriptor used to update the scope. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task UpdateAsync([NotNull] object scope, [NotNull] OpenIddictScopeDescriptor descriptor, CancellationToken cancellationToken = default); + + /// + /// Validates the scope to ensure it's in a consistent state. + /// + /// The scope. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the validation error encountered when validating the scope. + /// + Task> ValidateAsync([NotNull] object scope, CancellationToken cancellationToken = default); + } +} diff --git a/src/OpenIddict.Abstractions/Managers/IOpenIddictTokenManager.cs b/src/OpenIddict.Abstractions/Managers/IOpenIddictTokenManager.cs new file mode 100644 index 00000000..d70cbad3 --- /dev/null +++ b/src/OpenIddict.Abstractions/Managers/IOpenIddictTokenManager.cs @@ -0,0 +1,452 @@ +using System; +using System.Collections.Immutable; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using JetBrains.Annotations; + +namespace OpenIddict.Abstractions +{ + /// + /// Provides methods allowing to manage the tokens stored in the store. + /// Note: this interface is not meant to be implemented by custom managers, + /// that should inherit from the generic OpenIddictTokenManager class. + /// It is primarily intended to be used by services that cannot easily + /// depend on the generic token manager. The actual token entity type is + /// automatically determined at runtime based on the OpenIddict core options. + /// + public interface IOpenIddictTokenManager + { + /// + /// Determines the number of tokens that exist in the database. + /// + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the number of tokens in the database. + /// + Task CountAsync(CancellationToken cancellationToken = default); + + /// + /// Determines the number of tokens that match the specified query. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the number of tokens that match the specified query. + /// + Task CountAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken = default); + + /// + /// Creates a new token based on the specified descriptor. + /// + /// The token descriptor. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, whose result returns the token. + /// + Task CreateAsync([NotNull] OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken = default); + + /// + /// Creates a new token. + /// + /// The token. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task CreateAsync([NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Removes an existing token. + /// + /// The token to delete. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task DeleteAsync([NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Extends the specified token by replacing its expiration date. + /// + /// The token. + /// The date on which the token will no longer be considered valid. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task ExtendAsync([NotNull] object token, [CanBeNull] DateTimeOffset? date, CancellationToken cancellationToken = default); + + /// + /// Retrieves the list of tokens corresponding to the specified application identifier. + /// + /// The application identifier associated with the tokens. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the tokens corresponding to the specified application. + /// + Task> FindByApplicationIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default); + + /// + /// Retrieves the list of tokens corresponding to the specified authorization identifier. + /// + /// The authorization identifier associated with the tokens. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the tokens corresponding to the specified authorization. + /// + Task> FindByAuthorizationIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default); + + /// + /// Retrieves a token using its unique identifier. + /// + /// The unique identifier associated with the token. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the token corresponding to the unique identifier. + /// + Task FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default); + + /// + /// Retrieves the list of tokens corresponding to the specified reference identifier. + /// Note: the reference identifier may be hashed or encrypted for security reasons. + /// + /// The reference identifier associated with the tokens. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the tokens corresponding to the specified reference identifier. + /// + Task FindByReferenceIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default); + + /// + /// Retrieves the list of tokens corresponding to the specified subject. + /// + /// The subject associated with the tokens. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the tokens corresponding to the specified subject. + /// + Task> FindBySubjectAsync([NotNull] string subject, CancellationToken cancellationToken = default); + + /// + /// Retrieves the optional application identifier 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 the application identifier associated with the token. + /// + ValueTask GetApplicationIdAsync([NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns the first element. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the first element returned when executing the query. + /// + Task GetAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns the first element. + /// + /// The state type. + /// The result type. + /// The query to execute. + /// The optional state. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the first element returned when executing the query. + /// + Task GetAsync([NotNull] Func, TState, IQueryable> query, [CanBeNull] TState state, CancellationToken cancellationToken = default); + + /// + /// Retrieves the optional authorization identifier 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 the authorization identifier associated with the token. + /// + ValueTask GetAuthorizationIdAsync([NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Retrieves the creation date 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 the creation date associated with the specified token. + /// + ValueTask GetCreationDateAsync([NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Retrieves the expiration date 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 the expiration date associated with the specified token. + /// + ValueTask GetExpirationDateAsync([NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Retrieves the unique identifier 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 the unique identifier associated with the token. + /// + ValueTask GetIdAsync([NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Retrieves the payload 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 the payload associated with the specified token. + /// + ValueTask GetPayloadAsync([NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Retrieves the reference identifier associated with a token. + /// Note: depending on the manager used to create the token, + /// the reference identifier may be hashed for security reasons. + /// + /// The token. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the reference identifier associated with the specified token. + /// + ValueTask GetReferenceIdAsync([NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Retrieves the status 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 the status associated with the specified token. + /// + ValueTask GetStatusAsync([NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Retrieves the subject 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 the subject associated with the specified token. + /// + ValueTask GetSubjectAsync([NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Retrieves the token type 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 the token type associated with the specified token. + /// + ValueTask GetTokenTypeAsync([NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Determines whether a given token has already been redemeed. + /// + /// The token. + /// The that can be used to abort the operation. + /// true if the token has already been redemeed, false otherwise. + Task IsRedeemedAsync([NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Determines whether a given token has been revoked. + /// + /// The token. + /// The that can be used to abort the operation. + /// true if the token has been revoked, false otherwise. + Task IsRevokedAsync([NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Determines whether a given token is valid. + /// + /// The token. + /// The that can be used to abort the operation. + /// true if the token is valid, false otherwise. + Task IsValidAsync([NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns all the corresponding elements. + /// + /// The number of results to return. + /// The number of results to skip. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + Task> ListAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns all the corresponding elements. + /// + /// The result type. + /// The query to execute. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + Task> ListAsync([NotNull] Func, IQueryable> query, CancellationToken cancellationToken = default); + + /// + /// Executes the specified query and returns all the corresponding elements. + /// + /// The state type. + /// The result type. + /// The query to execute. + /// The optional state. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns all the elements returned when executing the specified query. + /// + Task> ListAsync([NotNull] Func, TState, IQueryable> query, [CanBeNull] TState state, CancellationToken cancellationToken = default); + + /// + /// Obfuscates the specified reference identifier so it can be safely stored in a database. + /// By default, this method returns a simple hashed representation computed using SHA256. + /// + /// The client identifier. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task ObfuscateReferenceIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default); + + /// + /// Populates the specified descriptor using the properties exposed by the token. + /// + /// The descriptor. + /// The token. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task PopulateAsync([NotNull] OpenIddictTokenDescriptor descriptor, [NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Populates the token using the specified descriptor. + /// + /// The token. + /// The descriptor. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task PopulateAsync([NotNull] object token, [NotNull] OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken = default); + + /// + /// Removes the tokens that are marked as expired or invalid. + /// + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task PruneAsync(CancellationToken cancellationToken = default); + + /// + /// Redeems a token. + /// + /// The token to redeem. + /// The that can be used to abort the operation. + /// A that can be used to monitor the asynchronous operation. + Task RedeemAsync([NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Revokes a token. + /// + /// The token to revoke. + /// The that can be used to abort the operation. + /// A that can be used to monitor the asynchronous operation. + Task RevokeAsync([NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Sets the application identifier associated with a token. + /// + /// The token. + /// The unique identifier associated with the client application. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task SetApplicationIdAsync([NotNull] object token, [CanBeNull] string identifier, CancellationToken cancellationToken = default); + + /// + /// Sets the authorization identifier associated with a token. + /// + /// The token. + /// The unique identifier associated with the authorization. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task SetAuthorizationIdAsync([NotNull] object token, [CanBeNull] string identifier, CancellationToken cancellationToken = default); + + /// + /// Updates an existing token. + /// + /// The token to update. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task UpdateAsync([NotNull] object token, CancellationToken cancellationToken = default); + + /// + /// Updates an existing token. + /// + /// The token to update. + /// The descriptor used to update the token. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation. + /// + Task UpdateAsync([NotNull] object token, [NotNull] OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken = default); + + /// + /// Validates the token to ensure it's in a consistent state. + /// + /// The token. + /// The that can be used to abort the operation. + /// + /// A that can be used to monitor the asynchronous operation, + /// whose result returns the validation error encountered when validating the token. + /// + Task> ValidateAsync([NotNull] object token, CancellationToken cancellationToken = default); + } +} diff --git a/src/OpenIddict.Abstractions/OpenIddict.Abstractions.csproj b/src/OpenIddict.Abstractions/OpenIddict.Abstractions.csproj index 08be8f9b..afbe268d 100644 --- a/src/OpenIddict.Abstractions/OpenIddict.Abstractions.csproj +++ b/src/OpenIddict.Abstractions/OpenIddict.Abstractions.csproj @@ -17,6 +17,7 @@ + diff --git a/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs b/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs index e18443b2..0fedc51e 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs +++ b/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs @@ -22,7 +22,7 @@ namespace OpenIddict.Core /// Provides methods allowing to manage the applications stored in the store. /// /// The type of the Application entity. - public class OpenIddictApplicationManager where TApplication : class + public class OpenIddictApplicationManager : IOpenIddictApplicationManager where TApplication : class { public OpenIddictApplicationManager( [NotNull] IOpenIddictApplicationStoreResolver resolver, @@ -58,9 +58,7 @@ namespace OpenIddict.Core /// whose result returns the number of applications in the database. /// public virtual Task CountAsync(CancellationToken cancellationToken = default) - { - return Store.CountAsync(cancellationToken); - } + => Store.CountAsync(cancellationToken); /// /// Determines the number of applications that match the specified query. @@ -1349,5 +1347,113 @@ namespace OpenIddict.Core return Task.FromResult(false); } } + + Task IOpenIddictApplicationManager.CountAsync(CancellationToken cancellationToken) + => CountAsync(cancellationToken); + + Task IOpenIddictApplicationManager.CountAsync(Func, IQueryable> query, CancellationToken cancellationToken) + => CountAsync(query, cancellationToken); + + async Task IOpenIddictApplicationManager.CreateAsync(OpenIddictApplicationDescriptor descriptor, CancellationToken cancellationToken) + => await CreateAsync(descriptor, cancellationToken); + + Task IOpenIddictApplicationManager.CreateAsync(object application, CancellationToken cancellationToken) + => CreateAsync((TApplication) application, cancellationToken); + + Task IOpenIddictApplicationManager.CreateAsync(object application, string secret, CancellationToken cancellationToken) + => CreateAsync((TApplication) application, secret, cancellationToken); + + Task IOpenIddictApplicationManager.DeleteAsync(object application, CancellationToken cancellationToken) + => DeleteAsync((TApplication) application, cancellationToken); + + async Task IOpenIddictApplicationManager.FindByClientIdAsync(string identifier, CancellationToken cancellationToken) + => await FindByClientIdAsync(identifier, cancellationToken); + + async Task IOpenIddictApplicationManager.FindByIdAsync(string identifier, CancellationToken cancellationToken) + => await FindByIdAsync(identifier, cancellationToken); + + async Task> IOpenIddictApplicationManager.FindByPostLogoutRedirectUriAsync(string address, CancellationToken cancellationToken) + => (await FindByPostLogoutRedirectUriAsync(address, cancellationToken)).CastArray(); + + async Task> IOpenIddictApplicationManager.FindByRedirectUriAsync(string address, CancellationToken cancellationToken) + => (await FindByRedirectUriAsync(address, cancellationToken)).CastArray(); + + Task IOpenIddictApplicationManager.GetAsync(Func, IQueryable> query, CancellationToken cancellationToken) + => GetAsync(query, cancellationToken); + + Task IOpenIddictApplicationManager.GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) + => GetAsync(query, state, cancellationToken); + + ValueTask IOpenIddictApplicationManager.GetClientIdAsync(object application, CancellationToken cancellationToken) + => GetClientIdAsync((TApplication) application, cancellationToken); + + ValueTask IOpenIddictApplicationManager.GetClientTypeAsync(object application, CancellationToken cancellationToken) + => GetClientTypeAsync((TApplication) application, cancellationToken); + + ValueTask IOpenIddictApplicationManager.GetConsentTypeAsync(object application, CancellationToken cancellationToken) + => GetConsentTypeAsync((TApplication) application, cancellationToken); + + ValueTask IOpenIddictApplicationManager.GetDisplayNameAsync(object application, CancellationToken cancellationToken) + => GetDisplayNameAsync((TApplication) application, cancellationToken); + + ValueTask IOpenIddictApplicationManager.GetIdAsync(object application, CancellationToken cancellationToken) + => GetIdAsync((TApplication) application, cancellationToken); + + ValueTask> IOpenIddictApplicationManager.GetPermissionsAsync(object application, CancellationToken cancellationToken) + => GetPermissionsAsync((TApplication) application, cancellationToken); + + ValueTask> IOpenIddictApplicationManager.GetPostLogoutRedirectUrisAsync(object application, CancellationToken cancellationToken) + => GetPostLogoutRedirectUrisAsync((TApplication) application, cancellationToken); + + ValueTask> IOpenIddictApplicationManager.GetRedirectUrisAsync(object application, CancellationToken cancellationToken) + => GetRedirectUrisAsync((TApplication) application, cancellationToken); + + Task IOpenIddictApplicationManager.HasPermissionAsync(object application, string permission, CancellationToken cancellationToken) + => HasPermissionAsync((TApplication) application, permission, cancellationToken); + + Task IOpenIddictApplicationManager.IsConfidentialAsync(object application, CancellationToken cancellationToken) + => IsConfidentialAsync((TApplication) application, cancellationToken); + + Task IOpenIddictApplicationManager.IsHybridAsync(object application, CancellationToken cancellationToken) + => IsHybridAsync((TApplication) application, cancellationToken); + + Task IOpenIddictApplicationManager.IsPublicAsync(object application, CancellationToken cancellationToken) + => IsPublicAsync((TApplication) application, cancellationToken); + + async Task> IOpenIddictApplicationManager.ListAsync(int? count, int? offset, CancellationToken cancellationToken) + => (await ListAsync(count, offset, cancellationToken)).CastArray(); + + Task> IOpenIddictApplicationManager.ListAsync(Func, IQueryable> query, CancellationToken cancellationToken) + => ListAsync(query, cancellationToken); + + Task> IOpenIddictApplicationManager.ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) + => ListAsync(query, state, cancellationToken); + + Task IOpenIddictApplicationManager.PopulateAsync(OpenIddictApplicationDescriptor descriptor, object application, CancellationToken cancellationToken) + => PopulateAsync(descriptor, (TApplication) application, cancellationToken); + + Task IOpenIddictApplicationManager.PopulateAsync(object application, OpenIddictApplicationDescriptor descriptor, CancellationToken cancellationToken) + => PopulateAsync((TApplication) application, descriptor, cancellationToken); + + Task IOpenIddictApplicationManager.UpdateAsync(object application, CancellationToken cancellationToken) + => UpdateAsync((TApplication) application, cancellationToken); + + Task IOpenIddictApplicationManager.UpdateAsync(object application, OpenIddictApplicationDescriptor descriptor, CancellationToken cancellationToken) + => UpdateAsync((TApplication) application, descriptor, cancellationToken); + + Task IOpenIddictApplicationManager.UpdateAsync(object application, string secret, CancellationToken cancellationToken) + => UpdateAsync((TApplication) application, secret, cancellationToken); + + Task> IOpenIddictApplicationManager.ValidateAsync(object application, CancellationToken cancellationToken) + => ValidateAsync((TApplication) application, cancellationToken); + + Task IOpenIddictApplicationManager.ValidateClientSecretAsync(object application, string secret, CancellationToken cancellationToken) + => ValidateClientSecretAsync((TApplication) application, secret, cancellationToken); + + Task IOpenIddictApplicationManager.ValidatePostLogoutRedirectUriAsync(string address, CancellationToken cancellationToken) + => ValidatePostLogoutRedirectUriAsync(address, cancellationToken); + + Task IOpenIddictApplicationManager.ValidateRedirectUriAsync(object application, string address, CancellationToken cancellationToken) + => ValidateRedirectUriAsync((TApplication) application, address, cancellationToken); } } \ No newline at end of file diff --git a/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs b/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs index fba23032..199bfc96 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs +++ b/src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs @@ -22,7 +22,7 @@ namespace OpenIddict.Core /// Provides methods allowing to manage the authorizations stored in the store. /// /// The type of the Authorization entity. - public class OpenIddictAuthorizationManager where TAuthorization : class + public class OpenIddictAuthorizationManager : IOpenIddictAuthorizationManager where TAuthorization : class { public OpenIddictAuthorizationManager( [NotNull] IOpenIddictAuthorizationStoreResolver resolver, @@ -58,9 +58,7 @@ namespace OpenIddict.Core /// whose result returns the number of authorizations in the database. /// public virtual Task CountAsync(CancellationToken cancellationToken = default) - { - return Store.CountAsync(cancellationToken); - } + => Store.CountAsync(cancellationToken); /// /// Determines the number of authorizations that match the specified query. @@ -1035,5 +1033,113 @@ namespace OpenIddict.Core builder.MoveToImmutable() : builder.ToImmutable(); } + + Task IOpenIddictAuthorizationManager.CountAsync(CancellationToken cancellationToken) + => CountAsync(cancellationToken); + + Task IOpenIddictAuthorizationManager.CountAsync(Func, IQueryable> query, CancellationToken cancellationToken) + => CountAsync(query, cancellationToken); + + async Task IOpenIddictAuthorizationManager.CreateAsync(ClaimsPrincipal principal, string subject, string client, string type, ImmutableArray scopes, ImmutableDictionary properties, CancellationToken cancellationToken) + => await CreateAsync(principal, subject, client, type, scopes, properties, cancellationToken); + + async Task IOpenIddictAuthorizationManager.CreateAsync(OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken) + => await CreateAsync(descriptor, cancellationToken); + + Task IOpenIddictAuthorizationManager.CreateAsync(object authorization, CancellationToken cancellationToken) + => CreateAsync((TAuthorization) authorization, cancellationToken); + + Task IOpenIddictAuthorizationManager.DeleteAsync(object authorization, CancellationToken cancellationToken) + => DeleteAsync((TAuthorization) authorization, cancellationToken); + + async Task> IOpenIddictAuthorizationManager.FindAsync(string subject, string client, CancellationToken cancellationToken) + => (await FindAsync(subject, client, cancellationToken)).CastArray(); + + async Task> IOpenIddictAuthorizationManager.FindAsync(string subject, string client, string status, CancellationToken cancellationToken) + => (await FindAsync(subject, client, status, cancellationToken)).CastArray(); + + async Task> IOpenIddictAuthorizationManager.FindAsync(string subject, string client, string status, string type, CancellationToken cancellationToken) + => (await FindAsync(subject, client, status, type, cancellationToken)).CastArray(); + + async Task> IOpenIddictAuthorizationManager.FindAsync(string subject, string client, string status, string type, ImmutableArray scopes, CancellationToken cancellationToken) + => (await FindAsync(subject, client, status, type, scopes, cancellationToken)).CastArray(); + + async Task IOpenIddictAuthorizationManager.FindByIdAsync(string identifier, CancellationToken cancellationToken) + => await FindByIdAsync(identifier, cancellationToken); + + async Task> IOpenIddictAuthorizationManager.FindBySubjectAsync(string subject, CancellationToken cancellationToken) + => (await FindBySubjectAsync(subject, cancellationToken)).CastArray(); + + ValueTask IOpenIddictAuthorizationManager.GetApplicationIdAsync(object authorization, CancellationToken cancellationToken) + => GetApplicationIdAsync((TAuthorization) authorization, cancellationToken); + + Task IOpenIddictAuthorizationManager.GetAsync(Func, IQueryable> query, CancellationToken cancellationToken) + => GetAsync(query, cancellationToken); + + Task IOpenIddictAuthorizationManager.GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) + => GetAsync(query, state, cancellationToken); + + ValueTask IOpenIddictAuthorizationManager.GetIdAsync(object authorization, CancellationToken cancellationToken) + => GetIdAsync((TAuthorization) authorization, cancellationToken); + + ValueTask> IOpenIddictAuthorizationManager.GetScopesAsync(object authorization, CancellationToken cancellationToken) + => GetScopesAsync((TAuthorization) authorization, cancellationToken); + + ValueTask IOpenIddictAuthorizationManager.GetStatusAsync(object authorization, CancellationToken cancellationToken) + => GetStatusAsync((TAuthorization) authorization, cancellationToken); + + ValueTask IOpenIddictAuthorizationManager.GetSubjectAsync(object authorization, CancellationToken cancellationToken) + => GetSubjectAsync((TAuthorization) authorization, cancellationToken); + + ValueTask IOpenIddictAuthorizationManager.GetTypeAsync(object authorization, CancellationToken cancellationToken) + => GetTypeAsync((TAuthorization) authorization, cancellationToken); + + Task IOpenIddictAuthorizationManager.HasScopesAsync(object authorization, ImmutableArray scopes, CancellationToken cancellationToken) + => HasScopesAsync((TAuthorization) authorization, scopes, cancellationToken); + + Task IOpenIddictAuthorizationManager.IsAdHocAsync(object authorization, CancellationToken cancellationToken) + => IsAdHocAsync((TAuthorization) authorization, cancellationToken); + + Task IOpenIddictAuthorizationManager.IsPermanentAsync(object authorization, CancellationToken cancellationToken) + => IsPermanentAsync((TAuthorization) authorization, cancellationToken); + + Task IOpenIddictAuthorizationManager.IsRevokedAsync(object authorization, CancellationToken cancellationToken) + => IsRevokedAsync((TAuthorization) authorization, cancellationToken); + + Task IOpenIddictAuthorizationManager.IsValidAsync(object authorization, CancellationToken cancellationToken) + => IsValidAsync((TAuthorization) authorization, cancellationToken); + + async Task> IOpenIddictAuthorizationManager.ListAsync(int? count, int? offset, CancellationToken cancellationToken) + => (await ListAsync(count, offset, cancellationToken)).CastArray(); + + Task> IOpenIddictAuthorizationManager.ListAsync(Func, IQueryable> query, CancellationToken cancellationToken) + => ListAsync(query, cancellationToken); + + Task> IOpenIddictAuthorizationManager.ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) + => ListAsync(query, state, cancellationToken); + + Task IOpenIddictAuthorizationManager.PopulateAsync(OpenIddictAuthorizationDescriptor descriptor, object authorization, CancellationToken cancellationToken) + => PopulateAsync(descriptor, (TAuthorization) authorization, cancellationToken); + + Task IOpenIddictAuthorizationManager.PopulateAsync(object authorization, OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken) + => PopulateAsync((TAuthorization) authorization, descriptor, cancellationToken); + + Task IOpenIddictAuthorizationManager.PruneAsync(CancellationToken cancellationToken) + => PruneAsync(cancellationToken); + + Task IOpenIddictAuthorizationManager.RevokeAsync(object authorization, CancellationToken cancellationToken) + => RevokeAsync((TAuthorization) authorization, cancellationToken); + + Task IOpenIddictAuthorizationManager.SetApplicationIdAsync(object authorization, string identifier, CancellationToken cancellationToken) + => SetApplicationIdAsync((TAuthorization) authorization, identifier, cancellationToken); + + Task IOpenIddictAuthorizationManager.UpdateAsync(object authorization, CancellationToken cancellationToken) + => UpdateAsync((TAuthorization) authorization, cancellationToken); + + Task IOpenIddictAuthorizationManager.UpdateAsync(object authorization, OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken) + => UpdateAsync((TAuthorization) authorization, cancellationToken); + + Task> IOpenIddictAuthorizationManager.ValidateAsync(object authorization, CancellationToken cancellationToken) + => ValidateAsync((TAuthorization) authorization, cancellationToken); } } \ No newline at end of file diff --git a/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs b/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs index 31b110a9..8c76eb93 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs +++ b/src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs @@ -22,7 +22,7 @@ namespace OpenIddict.Core /// Provides methods allowing to manage the scopes stored in the store. /// /// The type of the Scope entity. - public class OpenIddictScopeManager where TScope : class + public class OpenIddictScopeManager : IOpenIddictScopeManager where TScope : class { public OpenIddictScopeManager( [NotNull] IOpenIddictScopeStoreResolver resolver, @@ -58,9 +58,7 @@ namespace OpenIddict.Core /// whose result returns the number of scopes in the database. /// public virtual Task CountAsync(CancellationToken cancellationToken = default) - { - return Store.CountAsync(cancellationToken); - } + => Store.CountAsync(cancellationToken); /// /// Determines the number of scopes that match the specified query. @@ -627,5 +625,77 @@ namespace OpenIddict.Core builder.MoveToImmutable() : builder.ToImmutable(); } + + Task IOpenIddictScopeManager.CountAsync(CancellationToken cancellationToken) + => CountAsync(cancellationToken); + + Task IOpenIddictScopeManager.CountAsync(Func, IQueryable> query, CancellationToken cancellationToken) + => CountAsync(query, cancellationToken); + + async Task IOpenIddictScopeManager.CreateAsync(OpenIddictScopeDescriptor descriptor, CancellationToken cancellationToken) + => await CreateAsync(descriptor, cancellationToken); + + Task IOpenIddictScopeManager.CreateAsync(object scope, CancellationToken cancellationToken) + => CreateAsync((TScope) scope, cancellationToken); + + Task IOpenIddictScopeManager.DeleteAsync(object scope, CancellationToken cancellationToken) + => DeleteAsync((TScope) scope, cancellationToken); + + async Task IOpenIddictScopeManager.FindByIdAsync(string identifier, CancellationToken cancellationToken) + => await FindByIdAsync(identifier, cancellationToken); + + async Task IOpenIddictScopeManager.FindByNameAsync(string name, CancellationToken cancellationToken) + => await FindByNameAsync(name, cancellationToken); + + async Task> IOpenIddictScopeManager.FindByNamesAsync(ImmutableArray names, CancellationToken cancellationToken) + => (await FindByNamesAsync(names, cancellationToken)).CastArray(); + + Task IOpenIddictScopeManager.GetAsync(Func, IQueryable> query, CancellationToken cancellationToken) + => GetAsync(query, cancellationToken); + + Task IOpenIddictScopeManager.GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) + => GetAsync(query, state, cancellationToken); + + ValueTask IOpenIddictScopeManager.GetDescriptionAsync(object scope, CancellationToken cancellationToken) + => GetDescriptionAsync((TScope) scope, cancellationToken); + + ValueTask IOpenIddictScopeManager.GetDisplayNameAsync(object scope, CancellationToken cancellationToken) + => GetDisplayNameAsync((TScope) scope, cancellationToken); + + ValueTask IOpenIddictScopeManager.GetIdAsync(object scope, CancellationToken cancellationToken) + => GetIdAsync((TScope) scope, cancellationToken); + + ValueTask IOpenIddictScopeManager.GetNameAsync(object scope, CancellationToken cancellationToken) + => GetNameAsync((TScope) scope, cancellationToken); + + ValueTask> IOpenIddictScopeManager.GetResourcesAsync(object scope, CancellationToken cancellationToken) + => GetResourcesAsync((TScope) scope, cancellationToken); + + async Task> IOpenIddictScopeManager.ListAsync(int? count, int? offset, CancellationToken cancellationToken) + => (await ListAsync(count, offset, cancellationToken)).CastArray(); + + Task> IOpenIddictScopeManager.ListAsync(Func, IQueryable> query, CancellationToken cancellationToken) + => ListAsync(query, cancellationToken); + + Task> IOpenIddictScopeManager.ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) + => ListAsync(query, state, cancellationToken); + + Task> IOpenIddictScopeManager.ListResourcesAsync(ImmutableArray scopes, CancellationToken cancellationToken) + => ListResourcesAsync(scopes, cancellationToken); + + Task IOpenIddictScopeManager.PopulateAsync(OpenIddictScopeDescriptor descriptor, object scope, CancellationToken cancellationToken) + => PopulateAsync(descriptor, (TScope) scope, cancellationToken); + + Task IOpenIddictScopeManager.PopulateAsync(object scope, OpenIddictScopeDescriptor descriptor, CancellationToken cancellationToken) + => PopulateAsync((TScope) scope, descriptor, cancellationToken); + + Task IOpenIddictScopeManager.UpdateAsync(object scope, CancellationToken cancellationToken) + => UpdateAsync((TScope) scope, cancellationToken); + + Task IOpenIddictScopeManager.UpdateAsync(object scope, OpenIddictScopeDescriptor descriptor, CancellationToken cancellationToken) + => UpdateAsync((TScope) scope, descriptor, cancellationToken); + + Task> IOpenIddictScopeManager.ValidateAsync(object scope, CancellationToken cancellationToken) + => ValidateAsync((TScope) scope, cancellationToken); } } \ No newline at end of file diff --git a/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs b/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs index 5a5fc637..3787aa03 100644 --- a/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs +++ b/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs @@ -23,7 +23,7 @@ namespace OpenIddict.Core /// Provides methods allowing to manage the tokens stored in the store. /// /// The type of the Token entity. - public class OpenIddictTokenManager where TToken : class + public class OpenIddictTokenManager : IOpenIddictTokenManager where TToken : class { public OpenIddictTokenManager( [NotNull] IOpenIddictTokenStoreResolver resolver, @@ -59,9 +59,7 @@ namespace OpenIddict.Core /// whose result returns the number of tokens in the database. /// public virtual Task CountAsync(CancellationToken cancellationToken = default) - { - return Store.CountAsync(cancellationToken); - } + => Store.CountAsync(cancellationToken); /// /// Determines the number of tokens that match the specified query. @@ -968,5 +966,125 @@ namespace OpenIddict.Core builder.MoveToImmutable() : builder.ToImmutable(); } + + Task IOpenIddictTokenManager.CountAsync(CancellationToken cancellationToken) + => CountAsync(cancellationToken); + + Task IOpenIddictTokenManager.CountAsync(Func, IQueryable> query, CancellationToken cancellationToken) + => CountAsync(query, cancellationToken); + + async Task IOpenIddictTokenManager.CreateAsync(OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken) + => await CreateAsync(descriptor, cancellationToken); + + Task IOpenIddictTokenManager.CreateAsync(object token, CancellationToken cancellationToken) + => CreateAsync((TToken) token, cancellationToken); + + Task IOpenIddictTokenManager.DeleteAsync(object token, CancellationToken cancellationToken) + => DeleteAsync((TToken) token, cancellationToken); + + Task IOpenIddictTokenManager.ExtendAsync(object token, DateTimeOffset? date, CancellationToken cancellationToken) + => ExtendAsync((TToken) token, date, cancellationToken); + + async Task> IOpenIddictTokenManager.FindByApplicationIdAsync(string identifier, CancellationToken cancellationToken) + => (await FindByApplicationIdAsync(identifier, cancellationToken)).CastArray(); + + async Task> IOpenIddictTokenManager.FindByAuthorizationIdAsync(string identifier, CancellationToken cancellationToken) + => (await FindByAuthorizationIdAsync(identifier, cancellationToken)).CastArray(); + + async Task IOpenIddictTokenManager.FindByIdAsync(string identifier, CancellationToken cancellationToken) + => await FindByIdAsync(identifier, cancellationToken); + + async Task IOpenIddictTokenManager.FindByReferenceIdAsync(string identifier, CancellationToken cancellationToken) + => await FindByReferenceIdAsync(identifier, cancellationToken); + + async Task> IOpenIddictTokenManager.FindBySubjectAsync(string subject, CancellationToken cancellationToken) + => (await FindBySubjectAsync(subject, cancellationToken)).CastArray(); + + ValueTask IOpenIddictTokenManager.GetApplicationIdAsync(object token, CancellationToken cancellationToken) + => GetApplicationIdAsync((TToken) token, cancellationToken); + + Task IOpenIddictTokenManager.GetAsync(Func, IQueryable> query, CancellationToken cancellationToken) + => GetAsync(query, cancellationToken); + + Task IOpenIddictTokenManager.GetAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) + => GetAsync(query, state, cancellationToken); + + ValueTask IOpenIddictTokenManager.GetAuthorizationIdAsync(object token, CancellationToken cancellationToken) + => GetAuthorizationIdAsync((TToken) token, cancellationToken); + + ValueTask IOpenIddictTokenManager.GetCreationDateAsync(object token, CancellationToken cancellationToken) + => GetCreationDateAsync((TToken) token, cancellationToken); + + ValueTask IOpenIddictTokenManager.GetExpirationDateAsync(object token, CancellationToken cancellationToken) + => GetExpirationDateAsync((TToken) token, cancellationToken); + + ValueTask IOpenIddictTokenManager.GetIdAsync(object token, CancellationToken cancellationToken) + => GetIdAsync((TToken) token, cancellationToken); + + ValueTask IOpenIddictTokenManager.GetPayloadAsync(object token, CancellationToken cancellationToken) + => GetPayloadAsync((TToken) token, cancellationToken); + + ValueTask IOpenIddictTokenManager.GetReferenceIdAsync(object token, CancellationToken cancellationToken) + => GetReferenceIdAsync((TToken) token, cancellationToken); + + ValueTask IOpenIddictTokenManager.GetStatusAsync(object token, CancellationToken cancellationToken) + => GetStatusAsync((TToken) token, cancellationToken); + + ValueTask IOpenIddictTokenManager.GetSubjectAsync(object token, CancellationToken cancellationToken) + => GetSubjectAsync((TToken) token, cancellationToken); + + ValueTask IOpenIddictTokenManager.GetTokenTypeAsync(object token, CancellationToken cancellationToken) + => GetTokenTypeAsync((TToken) token, cancellationToken); + + Task IOpenIddictTokenManager.IsRedeemedAsync(object token, CancellationToken cancellationToken) + => IsRedeemedAsync((TToken) token, cancellationToken); + + Task IOpenIddictTokenManager.IsRevokedAsync(object token, CancellationToken cancellationToken) + => IsRevokedAsync((TToken) token, cancellationToken); + + Task IOpenIddictTokenManager.IsValidAsync(object token, CancellationToken cancellationToken) + => IsValidAsync((TToken) token, cancellationToken); + + async Task> IOpenIddictTokenManager.ListAsync(int? count, int? offset, CancellationToken cancellationToken) + => (await ListAsync(count, offset, cancellationToken)).CastArray(); + + Task> IOpenIddictTokenManager.ListAsync(Func, IQueryable> query, CancellationToken cancellationToken) + => ListAsync(query, cancellationToken); + + Task> IOpenIddictTokenManager.ListAsync(Func, TState, IQueryable> query, TState state, CancellationToken cancellationToken) + => ListAsync(query, state, cancellationToken); + + Task IOpenIddictTokenManager.ObfuscateReferenceIdAsync(string identifier, CancellationToken cancellationToken) + => ObfuscateReferenceIdAsync(identifier, cancellationToken); + + Task IOpenIddictTokenManager.PopulateAsync(OpenIddictTokenDescriptor descriptor, object token, CancellationToken cancellationToken) + => PopulateAsync(descriptor, (TToken) token, cancellationToken); + + Task IOpenIddictTokenManager.PopulateAsync(object token, OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken) + => PopulateAsync((TToken) token, descriptor, cancellationToken); + + Task IOpenIddictTokenManager.PruneAsync(CancellationToken cancellationToken) + => PruneAsync(cancellationToken); + + Task IOpenIddictTokenManager.RedeemAsync(object token, CancellationToken cancellationToken) + => RedeemAsync((TToken) token, cancellationToken); + + Task IOpenIddictTokenManager.RevokeAsync(object token, CancellationToken cancellationToken) + => RevokeAsync((TToken) token, cancellationToken); + + Task IOpenIddictTokenManager.SetApplicationIdAsync(object token, string identifier, CancellationToken cancellationToken) + => SetApplicationIdAsync((TToken) token, identifier, cancellationToken); + + Task IOpenIddictTokenManager.SetAuthorizationIdAsync(object token, string identifier, CancellationToken cancellationToken) + => SetAuthorizationIdAsync((TToken) token, identifier, cancellationToken); + + Task IOpenIddictTokenManager.UpdateAsync(object token, CancellationToken cancellationToken) + => UpdateAsync((TToken) token, cancellationToken); + + Task IOpenIddictTokenManager.UpdateAsync(object token, OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken) + => UpdateAsync((TToken) token, descriptor, cancellationToken); + + Task> IOpenIddictTokenManager.ValidateAsync(object token, CancellationToken cancellationToken) + => ValidateAsync((TToken) token, cancellationToken); } } \ No newline at end of file diff --git a/src/OpenIddict.Core/OpenIddict.Core.csproj b/src/OpenIddict.Core/OpenIddict.Core.csproj index 5df1ad29..493b8986 100644 --- a/src/OpenIddict.Core/OpenIddict.Core.csproj +++ b/src/OpenIddict.Core/OpenIddict.Core.csproj @@ -20,12 +20,7 @@ - - - - - diff --git a/src/OpenIddict.Core/OpenIddictCoreExtensions.cs b/src/OpenIddict.Core/OpenIddictCoreExtensions.cs index 774da9c3..ceb11696 100644 --- a/src/OpenIddict.Core/OpenIddictCoreExtensions.cs +++ b/src/OpenIddict.Core/OpenIddictCoreExtensions.cs @@ -5,8 +5,10 @@ */ using System; +using System.Text; using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Options; using OpenIddict.Abstractions; using OpenIddict.Core; @@ -41,6 +43,70 @@ namespace Microsoft.Extensions.DependencyInjection builder.Services.TryAddScoped(); builder.Services.TryAddScoped(); + builder.Services.TryAddScoped(provider => + { + var options = provider.GetRequiredService>().CurrentValue; + if (options.DefaultApplicationType == null) + { + throw new InvalidOperationException(new StringBuilder() + .AppendLine("The default application type must be configured for the non-generic services to work correctly.") + .Append("To configure the entities, use either 'services.AddOpenIddict().AddCore().UseDefaultModels()' ") + .Append("or 'services.AddOpenIddict().AddCore().UseCustomModels()'.") + .ToString()); + } + + return (IOpenIddictApplicationManager) provider.GetRequiredService( + typeof(OpenIddictApplicationManager<>).MakeGenericType(options.DefaultApplicationType)); + }); + + builder.Services.TryAddScoped(provider => + { + var options = provider.GetRequiredService>().CurrentValue; + if (options.DefaultAuthorizationType == null) + { + throw new InvalidOperationException(new StringBuilder() + .AppendLine("The default authorization type must be configured for the non-generic services to work correctly.") + .Append("To configure the entities, use either 'services.AddOpenIddict().AddCore().UseDefaultModels()' ") + .Append("or 'services.AddOpenIddict().AddCore().UseCustomModels()'.") + .ToString()); + } + + return (IOpenIddictAuthorizationManager) provider.GetRequiredService( + typeof(OpenIddictAuthorizationManager<>).MakeGenericType(options.DefaultAuthorizationType)); + }); + + builder.Services.TryAddScoped(provider => + { + var options = provider.GetRequiredService>().CurrentValue; + if (options.DefaultScopeType == null) + { + throw new InvalidOperationException(new StringBuilder() + .AppendLine("The default scope type must be configured for the non-generic services to work correctly.") + .Append("To configure the entities, use either 'services.AddOpenIddict().AddCore().UseDefaultModels()' ") + .Append("or 'services.AddOpenIddict().AddCore().UseCustomModels()'.") + .ToString()); + } + + return (IOpenIddictScopeManager) provider.GetRequiredService( + typeof(OpenIddictScopeManager<>).MakeGenericType(options.DefaultScopeType)); + }); + + builder.Services.TryAddScoped(provider => + { + var options = provider.GetRequiredService>().CurrentValue; + if (options.DefaultTokenType == null) + { + throw new InvalidOperationException(new StringBuilder() + .AppendLine("The default token type must be configured for the non-generic services to work correctly.") + .Append("To configure the entities, use either 'services.AddOpenIddict().AddCore().UseDefaultModels()' ") + .Append("or 'services.AddOpenIddict().AddCore().UseCustomModels()'.") + .ToString()); + } + + return (IOpenIddictTokenManager) provider.GetRequiredService( + typeof(OpenIddictTokenManager<>).MakeGenericType(options.DefaultTokenType)); + }); + return new OpenIddictCoreBuilder(builder.Services); } diff --git a/src/OpenIddict.Core/OpenIddictCoreOptions.cs b/src/OpenIddict.Core/OpenIddictCoreOptions.cs index 5f728591..f805190c 100644 --- a/src/OpenIddict.Core/OpenIddictCoreOptions.cs +++ b/src/OpenIddict.Core/OpenIddictCoreOptions.cs @@ -11,22 +11,26 @@ namespace OpenIddict.Core public class OpenIddictCoreOptions { /// - /// Gets or sets the type corresponding to the Application entity. + /// Gets or sets the type corresponding to the default Application entity, + /// used by the non-generic application manager and the server/validation services. /// public Type DefaultApplicationType { get; set; } /// - /// Gets or sets the type corresponding to the Authorization entity. + /// Gets or sets the type corresponding to the default Authorization entity, + /// used by the non-generic authorization manager and the server/validation services. /// public Type DefaultAuthorizationType { get; set; } /// - /// Gets or sets the type corresponding to the Scope entity. + /// Gets or sets the type corresponding to the default Scope entity, + /// used by the non-generic scope manager and the server/validation services. /// public Type DefaultScopeType { get; set; } /// - /// Gets or sets the type corresponding to the Token entity. + /// Gets or sets the type corresponding to the default Token entity, + /// used by the non-generic token manager and the server/validation services. /// public Type DefaultTokenType { get; set; } } diff --git a/src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs b/src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs index 0fcc7066..ff3bea55 100644 --- a/src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs +++ b/src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs @@ -285,7 +285,7 @@ namespace OpenIddict.EntityFramework /// /// A that can be used to monitor the asynchronous operation. /// - public override async Task PruneAsync(CancellationToken cancellationToken = default) + public override async Task PruneAsync(CancellationToken cancellationToken) { // Note: Entity Framework 6.x doesn't support set-based deletes, which prevents removing // entities in a single command without having to retrieve and materialize them first. diff --git a/src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs b/src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs index e831691b..470e54c7 100644 --- a/src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs +++ b/src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs @@ -291,7 +291,7 @@ namespace OpenIddict.EntityFramework /// /// A that can be used to monitor the asynchronous operation. /// - public override async Task PruneAsync(CancellationToken cancellationToken = default) + public override async Task PruneAsync(CancellationToken cancellationToken) { // Note: Entity Framework 6.x doesn't support set-based deletes, which prevents removing // entities in a single command without having to retrieve and materialize them first. diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs index 039dbbe4..6ec354a7 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs +++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs @@ -527,7 +527,7 @@ namespace OpenIddict.EntityFrameworkCore /// /// A that can be used to monitor the asynchronous operation. /// - public override async Task PruneAsync(CancellationToken cancellationToken = default) + public override async Task PruneAsync(CancellationToken cancellationToken) { // Note: Entity Framework Core doesn't support set-based deletes, which prevents removing // entities in a single command without having to retrieve and materialize them first. diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs index d68bb36f..8ecb348b 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs +++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs @@ -469,7 +469,7 @@ namespace OpenIddict.EntityFrameworkCore /// /// A that can be used to monitor the asynchronous operation. /// - public override async Task PruneAsync(CancellationToken cancellationToken = default) + public override async Task PruneAsync(CancellationToken cancellationToken) { // Note: Entity Framework Core doesn't support set-based deletes, which prevents removing // entities in a single command without having to retrieve and materialize them first. diff --git a/src/OpenIddict.Server/Internal/OpenIddictServerInitializer.cs b/src/OpenIddict.Server/Internal/OpenIddictServerInitializer.cs index b1a1e1ee..9c8f9710 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerInitializer.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerInitializer.cs @@ -15,7 +15,6 @@ using Microsoft.AspNetCore.DataProtection; using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; -using OpenIddict.Core; namespace OpenIddict.Server { @@ -28,19 +27,16 @@ namespace OpenIddict.Server { private readonly IDistributedCache _cache; private readonly IDataProtectionProvider _dataProtectionProvider; - private readonly IOptionsMonitor _options; /// /// Creates a new instance of the class. /// public OpenIddictServerInitializer( [NotNull] IDistributedCache cache, - [NotNull] IDataProtectionProvider dataProtectionProvider, - [NotNull] IOptionsMonitor options) + [NotNull] IDataProtectionProvider dataProtectionProvider) { _cache = cache; _dataProtectionProvider = dataProtectionProvider; - _options = options; } /// @@ -193,26 +189,6 @@ namespace OpenIddict.Server { options.Scopes.Add(OpenIdConnectConstants.Scopes.OfflineAccess); } - - if (options.ApplicationType == null) - { - options.ApplicationType = _options.CurrentValue.DefaultApplicationType; - } - - if (options.AuthorizationType == null) - { - options.AuthorizationType = _options.CurrentValue.DefaultAuthorizationType; - } - - if (options.ScopeType == null) - { - options.ScopeType = _options.CurrentValue.DefaultScopeType; - } - - if (options.TokenType == null) - { - options.TokenType = _options.CurrentValue.DefaultTokenType; - } } } } diff --git a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Authentication.cs b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Authentication.cs index 46725f62..c4fb5cf6 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Authentication.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Authentication.cs @@ -23,8 +23,7 @@ using OpenIddict.Abstractions; namespace OpenIddict.Server { - public partial class OpenIddictServerProvider : OpenIdConnectServerProvider - where TApplication : class where TAuthorization : class where TScope : class where TToken : class + public partial class OpenIddictServerProvider : OpenIdConnectServerProvider { public override async Task ExtractAuthorizationRequest([NotNull] ExtractAuthorizationRequestContext context) { @@ -33,8 +32,8 @@ namespace OpenIddict.Server // Reject requests using the unsupported request parameter. if (!string.IsNullOrEmpty(context.Request.Request)) { - Logger.LogError("The authorization request was rejected because it contained " + - "an unsupported parameter: {Parameter}.", "request"); + _logger.LogError("The authorization request was rejected because it contained " + + "an unsupported parameter: {Parameter}.", "request"); context.Reject( error: OpenIdConnectConstants.Errors.RequestNotSupported, @@ -46,8 +45,8 @@ namespace OpenIddict.Server // Reject requests using the unsupported request_uri parameter. if (!string.IsNullOrEmpty(context.Request.RequestUri)) { - Logger.LogError("The authorization request was rejected because it contained " + - "an unsupported parameter: {Parameter}.", "request_uri"); + _logger.LogError("The authorization request was rejected because it contained " + + "an unsupported parameter: {Parameter}.", "request_uri"); context.Reject( error: OpenIdConnectConstants.Errors.RequestUriNotSupported, @@ -63,8 +62,8 @@ namespace OpenIddict.Server // Return an error if request caching support was not enabled. if (!options.EnableRequestCaching) { - Logger.LogError("The authorization request was rejected because " + - "request caching support was not enabled."); + _logger.LogError("The authorization request was rejected because " + + "request caching support was not enabled."); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -80,8 +79,8 @@ namespace OpenIddict.Server var payload = await options.Cache.GetAsync(key); if (payload == null) { - Logger.LogError("The authorization request was rejected because an unknown " + - "or invalid request_id parameter was specified."); + _logger.LogError("The authorization request was rejected because an unknown " + + "or invalid request_id parameter was specified."); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -115,8 +114,8 @@ namespace OpenIddict.Server // none and custom flows but OpenIddict uses a stricter policy rejecting none and custum flows. if (!context.Request.IsAuthorizationCodeFlow() && !context.Request.IsHybridFlow() && !context.Request.IsImplicitFlow()) { - Logger.LogError("The authorization request was rejected because the '{ResponseType}' " + - "response type is not supported.", context.Request.ResponseType); + _logger.LogError("The authorization request was rejected because the '{ResponseType}' " + + "response type is not supported.", context.Request.ResponseType); context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, @@ -129,8 +128,8 @@ namespace OpenIddict.Server if (context.Request.IsAuthorizationCodeFlow() && !options.GrantTypes.Contains(OpenIdConnectConstants.GrantTypes.AuthorizationCode)) { - Logger.LogError("The authorization request was rejected because " + - "the authorization code flow was not enabled."); + _logger.LogError("The authorization request was rejected because " + + "the authorization code flow was not enabled."); context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, @@ -142,7 +141,7 @@ namespace OpenIddict.Server // Reject implicit flow authorization requests if the implicit flow is not enabled. if (context.Request.IsImplicitFlow() && !options.GrantTypes.Contains(OpenIdConnectConstants.GrantTypes.Implicit)) { - Logger.LogError("The authorization request was rejected because the implicit flow was not enabled."); + _logger.LogError("The authorization request was rejected because the implicit flow was not enabled."); context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, @@ -155,8 +154,8 @@ namespace OpenIddict.Server if (context.Request.IsHybridFlow() && (!options.GrantTypes.Contains(OpenIdConnectConstants.GrantTypes.AuthorizationCode) || !options.GrantTypes.Contains(OpenIdConnectConstants.GrantTypes.Implicit))) { - Logger.LogError("The authorization request was rejected because the " + - "authorization code flow or the implicit flow was not enabled."); + _logger.LogError("The authorization request was rejected because the " + + "authorization code flow or the implicit flow was not enabled."); context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedResponseType, @@ -180,10 +179,10 @@ namespace OpenIddict.Server foreach (var scope in context.Request.GetScopes()) { if (options.EnableScopeValidation && !options.Scopes.Contains(scope) && - await Scopes.FindByNameAsync(scope) == null) + await _scopeManager.FindByNameAsync(scope) == null) { - Logger.LogError("The authorization request was rejected because an " + - "unregistered scope was specified: {Scope}.", scope); + _logger.LogError("The authorization request was rejected because an " + + "unregistered scope was specified: {Scope}.", scope); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -200,8 +199,8 @@ namespace OpenIddict.Server !context.Request.IsFragmentResponseMode() && !context.Request.IsQueryResponseMode()) { - Logger.LogError("The authorization request was rejected because the '{ResponseMode}' " + - "response mode is not supported.", context.Request.ResponseMode); + _logger.LogError("The authorization request was rejected because the '{ResponseMode}' " + + "response mode is not supported.", context.Request.ResponseMode); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -231,8 +230,8 @@ namespace OpenIddict.Server // reject the authorization request if the code_challenge_method is missing. if (string.IsNullOrEmpty(context.Request.CodeChallengeMethod)) { - Logger.LogError("The authorization request was rejected because the " + - "required 'code_challenge_method' parameter was missing."); + _logger.LogError("The authorization request was rejected because the " + + "required 'code_challenge_method' parameter was missing."); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -245,8 +244,8 @@ namespace OpenIddict.Server // See https://tools.ietf.org/html/rfc7636#section-7.2 for more information. if (string.Equals(context.Request.CodeChallengeMethod, OpenIdConnectConstants.CodeChallengeMethods.Plain)) { - Logger.LogError("The authorization request was rejected because the " + - "'code_challenge_method' parameter was set to 'plain'."); + _logger.LogError("The authorization request was rejected because the " + + "'code_challenge_method' parameter was set to 'plain'."); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -258,8 +257,8 @@ namespace OpenIddict.Server // Reject authorization requests that contain response_type=token when a code_challenge is specified. if (context.Request.HasResponseType(OpenIdConnectConstants.ResponseTypes.Token)) { - Logger.LogError("The authorization request was rejected because the " + - "specified response type was not compatible with PKCE."); + _logger.LogError("The authorization request was rejected because the " + + "specified response type was not compatible with PKCE."); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -270,11 +269,11 @@ namespace OpenIddict.Server } // Retrieve the application details corresponding to the requested client_id. - var application = await Applications.FindByClientIdAsync(context.ClientId); + var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - Logger.LogError("The authorization request was rejected because the client " + - "application was not found: '{ClientId}'.", context.ClientId); + _logger.LogError("The authorization request was rejected because the client " + + "application was not found: '{ClientId}'.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -291,7 +290,7 @@ namespace OpenIddict.Server // from the authorization endpoint are rejected if the client_id corresponds to a confidential application. // Note: when using the authorization code grant, ValidateTokenRequest is responsible of rejecting // the token request if the client_id corresponds to an unauthenticated confidential client. - if (await Applications.IsConfidentialAsync(application) && + if (await _applicationManager.IsConfidentialAsync(application) && context.Request.HasResponseType(OpenIdConnectConstants.ResponseTypes.Token)) { context.Reject( @@ -302,10 +301,10 @@ namespace OpenIddict.Server } // Reject the request if the application is not allowed to use the authorization endpoint. - if (!await Applications.HasPermissionAsync(application, OpenIddictConstants.Permissions.Endpoints.Authorization)) + if (!await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.Endpoints.Authorization)) { - Logger.LogError("The authorization request was rejected because the application '{ClientId}' " + - "was not allowed to use the authorization endpoint.", context.ClientId); + _logger.LogError("The authorization request was rejected because the application '{ClientId}' " + + "was not allowed to use the authorization endpoint.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.UnauthorizedClient, @@ -315,11 +314,11 @@ namespace OpenIddict.Server } // Reject the request if the application is not allowed to use the authorization code flow. - if (context.Request.IsAuthorizationCodeFlow() && !await Applications.HasPermissionAsync( + if (context.Request.IsAuthorizationCodeFlow() && !await _applicationManager.HasPermissionAsync( application, OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode)) { - Logger.LogError("The authorization request was rejected because the application '{ClientId}' " + - "was not allowed to use the authorization code flow.", context.ClientId); + _logger.LogError("The authorization request was rejected because the application '{ClientId}' " + + "was not allowed to use the authorization code flow.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.UnauthorizedClient, @@ -329,11 +328,11 @@ namespace OpenIddict.Server } // Reject the request if the application is not allowed to use the implicit flow. - if (context.Request.IsImplicitFlow() && !await Applications.HasPermissionAsync( + if (context.Request.IsImplicitFlow() && !await _applicationManager.HasPermissionAsync( application, OpenIddictConstants.Permissions.GrantTypes.Implicit)) { - Logger.LogError("The authorization request was rejected because the application '{ClientId}' " + - "was not allowed to use the implicit flow.", context.ClientId); + _logger.LogError("The authorization request was rejected because the application '{ClientId}' " + + "was not allowed to use the implicit flow.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.UnauthorizedClient, @@ -344,15 +343,15 @@ namespace OpenIddict.Server // Reject the request if the application is not allowed to use the authorization code/implicit flows. if (context.Request.IsHybridFlow() && - (!await Applications.HasPermissionAsync(application, OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode) || - !await Applications.HasPermissionAsync(application, OpenIddictConstants.Permissions.GrantTypes.Implicit))) + (!await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode) || + !await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.GrantTypes.Implicit))) { - Logger.LogError("The authorization request was rejected because the application '{ClientId}' " + - "was not allowed to use the hybrid flow.", context.ClientId); + _logger.LogError("The authorization request was rejected because the application '{ClientId}' " + + "was not allowed to use the hybrid flow.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.UnauthorizedClient, - description: "The client application is not allowed to use the hybrid flow."); + description: "The client application is not allowed to use the hybrid flow."); return; } @@ -360,10 +359,10 @@ namespace OpenIddict.Server // Reject the request if the offline_access scope was request and if the // application is not allowed to use the authorization code/implicit flows. if (context.Request.HasScope(OpenIdConnectConstants.Scopes.OfflineAccess) && - !await Applications.HasPermissionAsync(application, OpenIddictConstants.Permissions.GrantTypes.RefreshToken)) + !await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.GrantTypes.RefreshToken)) { - Logger.LogError("The authorization request was rejected because the application '{ClientId}' " + - "was not allowed to request the 'offline_access' scope.", context.ClientId); + _logger.LogError("The authorization request was rejected because the application '{ClientId}' " + + "was not allowed to request the 'offline_access' scope.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -373,10 +372,10 @@ namespace OpenIddict.Server } // Ensure that the specified redirect_uri is valid and is associated with the client application. - if (!await Applications.ValidateRedirectUriAsync(application, context.RedirectUri)) + if (!await _applicationManager.ValidateRedirectUriAsync(application, context.RedirectUri)) { - Logger.LogError("The authorization request was rejected because the redirect_uri " + - "was invalid: '{RedirectUri}'.", context.RedirectUri); + _logger.LogError("The authorization request was rejected because the redirect_uri " + + "was invalid: '{RedirectUri}'.", context.RedirectUri); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -395,10 +394,10 @@ namespace OpenIddict.Server } // Reject the request if the application is not allowed to use the iterated scope. - if (!await Applications.HasPermissionAsync(application, OpenIddictConstants.Permissions.Prefixes.Scope + scope)) + if (!await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.Prefixes.Scope + scope)) { - Logger.LogError("The authorization request was rejected because the application '{ClientId}' " + - "was not allowed to use the scope {Scope}.", context.ClientId, scope); + _logger.LogError("The authorization request was rejected because the application '{ClientId}' " + + "was not allowed to use the scope {Scope}.", context.ClientId, scope); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, diff --git a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Discovery.cs b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Discovery.cs index 1b2b6ea7..c5a56ef2 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Discovery.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Discovery.cs @@ -16,8 +16,7 @@ using OpenIddict.Abstractions; namespace OpenIddict.Server { - public partial class OpenIddictServerProvider : OpenIdConnectServerProvider - where TApplication : class where TAuthorization : class where TScope : class where TToken : class + public partial class OpenIddictServerProvider : OpenIdConnectServerProvider { public override async Task HandleConfigurationRequest([NotNull] HandleConfigurationRequestContext context) { diff --git a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Exchange.cs b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Exchange.cs index 4f95bd5e..305ec5bd 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Exchange.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Exchange.cs @@ -16,8 +16,7 @@ using OpenIddict.Abstractions; namespace OpenIddict.Server { - public partial class OpenIddictServerProvider : OpenIdConnectServerProvider - where TApplication : class where TAuthorization : class where TScope : class where TToken : class + public partial class OpenIddictServerProvider : OpenIdConnectServerProvider { public override async Task ValidateTokenRequest([NotNull] ValidateTokenRequestContext context) { @@ -26,8 +25,8 @@ namespace OpenIddict.Server // Reject token requests that don't specify a supported grant type. if (!options.GrantTypes.Contains(context.Request.GrantType)) { - Logger.LogError("The token request was rejected because the '{GrantType}' " + - "grant type is not supported.", context.Request.GrantType); + _logger.LogError("The token request was rejected because the '{GrantType}' " + + "grant type is not supported.", context.Request.GrantType); context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedGrantType, @@ -80,10 +79,10 @@ namespace OpenIddict.Server foreach (var scope in context.Request.GetScopes()) { if (options.EnableScopeValidation && !options.Scopes.Contains(scope) && - await Scopes.FindByNameAsync(scope) == null) + await _scopeManager.FindByNameAsync(scope) == null) { - Logger.LogError("The token request was rejected because an " + - "unregistered scope was specified: {Scope}.", scope); + _logger.LogError("The token request was rejected because an " + + "unregistered scope was specified: {Scope}.", scope); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -117,8 +116,8 @@ namespace OpenIddict.Server // Reject the request if client identification is mandatory. if (options.RequireClientIdentification) { - Logger.LogError("The token request was rejected becaused the " + - "mandatory client_id parameter was missing or empty."); + _logger.LogError("The token request was rejected becaused the " + + "mandatory client_id parameter was missing or empty."); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -127,8 +126,8 @@ namespace OpenIddict.Server return; } - Logger.LogDebug("The token request validation process was partially skipped " + - "because the 'client_id' parameter was missing or empty."); + _logger.LogDebug("The token request validation process was partially skipped " + + "because the 'client_id' parameter was missing or empty."); context.Skip(); @@ -136,11 +135,11 @@ namespace OpenIddict.Server } // Retrieve the application details corresponding to the requested client_id. - var application = await Applications.FindByClientIdAsync(context.ClientId); + var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - Logger.LogError("The token request was rejected because the client " + - "application was not found: '{ClientId}'.", context.ClientId); + _logger.LogError("The token request was rejected because the client " + + "application was not found: '{ClientId}'.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, @@ -154,10 +153,10 @@ namespace OpenIddict.Server context.Request.SetProperty($"{OpenIddictConstants.Properties.Application}:{context.ClientId}", application); // Reject the request if the application is not allowed to use the token endpoint. - if (!await Applications.HasPermissionAsync(application, OpenIddictConstants.Permissions.Endpoints.Token)) + if (!await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.Endpoints.Token)) { - Logger.LogError("The token request was rejected because the application '{ClientId}' " + - "was not allowed to use the token endpoint.", context.ClientId); + _logger.LogError("The token request was rejected because the application '{ClientId}' " + + "was not allowed to use the token endpoint.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.UnauthorizedClient, @@ -167,11 +166,11 @@ namespace OpenIddict.Server } // Reject the request if the application is not allowed to use the specified grant type. - if (!await Applications.HasPermissionAsync(application, + if (!await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.Prefixes.GrantType + context.Request.GrantType)) { - Logger.LogError("The token request was rejected because the application '{ClientId}' was not allowed to " + - "use the specified grant type: {GrantType}.", context.ClientId, context.Request.GrantType); + _logger.LogError("The token request was rejected because the application '{ClientId}' was not allowed to " + + "use the specified grant type: {GrantType}.", context.ClientId, context.Request.GrantType); context.Reject( error: OpenIdConnectConstants.Errors.UnauthorizedClient, @@ -180,13 +179,13 @@ namespace OpenIddict.Server return; } - if (await Applications.IsPublicAsync(application)) + if (await _applicationManager.IsPublicAsync(application)) { // Note: public applications are not allowed to use the client credentials grant. if (context.Request.IsClientCredentialsGrantType()) { - Logger.LogError("The token request was rejected because the public client application '{ClientId}' " + - "was not allowed to use the client credentials grant.", context.Request.ClientId); + _logger.LogError("The token request was rejected because the public client application '{ClientId}' " + + "was not allowed to use the client credentials grant.", context.Request.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.UnauthorizedClient, @@ -198,8 +197,8 @@ namespace OpenIddict.Server // Reject token requests containing a client_secret when the client is a public application. if (!string.IsNullOrEmpty(context.ClientSecret)) { - Logger.LogError("The token request was rejected because the public application '{ClientId}' " + - "was not allowed to send a client secret.", context.ClientId); + _logger.LogError("The token request was rejected because the public application '{ClientId}' " + + "was not allowed to send a client secret.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -208,8 +207,8 @@ namespace OpenIddict.Server return; } - Logger.LogDebug("The token request validation process was not fully validated because " + - "the client '{ClientId}' was a public application.", context.ClientId); + _logger.LogDebug("The token request validation process was not fully validated because " + + "the client '{ClientId}' was a public application.", context.ClientId); // If client authentication cannot be enforced, call context.Skip() to inform // the OpenID Connect server middleware that the caller cannot be fully trusted. @@ -222,8 +221,8 @@ namespace OpenIddict.Server // to protect them from impersonation attacks. if (string.IsNullOrEmpty(context.ClientSecret)) { - Logger.LogError("The token request was rejected because the confidential or hybrid application " + - "'{ClientId}' didn't specify a client secret.", context.ClientId); + _logger.LogError("The token request was rejected because the confidential or hybrid application " + + "'{ClientId}' didn't specify a client secret.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, @@ -232,10 +231,10 @@ namespace OpenIddict.Server return; } - if (!await Applications.ValidateClientSecretAsync(application, context.ClientSecret)) + if (!await _applicationManager.ValidateClientSecretAsync(application, context.ClientSecret)) { - Logger.LogError("The token request was rejected because the confidential or hybrid application " + - "'{ClientId}' didn't specify valid client credentials.", context.ClientId); + _logger.LogError("The token request was rejected because the confidential or hybrid application " + + "'{ClientId}' didn't specify valid client credentials.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, @@ -254,11 +253,11 @@ namespace OpenIddict.Server } // Reject the request if the application is not allowed to use the iterated scope. - if (!await Applications.HasPermissionAsync(application, + if (!await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.Prefixes.Scope + scope)) { - Logger.LogError("The token request was rejected because the application '{ClientId}' " + - "was not allowed to use the scope {Scope}.", context.ClientId, scope); + _logger.LogError("The token request was rejected because the application '{ClientId}' " + + "was not allowed to use the scope {Scope}.", context.ClientId, scope); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -298,13 +297,13 @@ namespace OpenIddict.Server Debug.Assert(!string.IsNullOrEmpty(identifier), "The authentication ticket should contain a token identifier."); // Retrieve the authorization code/refresh token from the request properties. - var token = context.Request.GetProperty($"{OpenIddictConstants.Properties.Token}:{identifier}"); + var token = context.Request.GetProperty($"{OpenIddictConstants.Properties.Token}:{identifier}"); Debug.Assert(token != null, "The token shouldn't be null."); // If the authorization code/refresh token is already marked as redeemed, this may indicate that // it was compromised. In this case, revoke the authorization and all the associated tokens. // See https://tools.ietf.org/html/rfc6749#section-10.5 for more information. - if (await Tokens.IsRedeemedAsync(token)) + if (await _tokenManager.IsRedeemedAsync(token)) { // Try to revoke the authorization and the associated tokens. // If the operation fails, the helpers will automatically log @@ -314,8 +313,8 @@ namespace OpenIddict.Server await TryRevokeTokensAsync(context.Ticket); await TryRevokeTokenAsync(token); - Logger.LogError("The token request was rejected because the authorization code " + - "or refresh token '{Identifier}' has already been redeemed.", identifier); + _logger.LogError("The token request was rejected because the authorization code " + + "or refresh token '{Identifier}' has already been redeemed.", identifier); context.Reject( error: OpenIdConnectConstants.Errors.InvalidGrant, @@ -326,10 +325,10 @@ namespace OpenIddict.Server return; } - else if (!await Tokens.IsValidAsync(token)) + else if (!await _tokenManager.IsValidAsync(token)) { - Logger.LogError("The token request was rejected because the authorization code " + - "or refresh token '{Identifier}' was no longer valid.", identifier); + _logger.LogError("The token request was rejected because the authorization code " + + "or refresh token '{Identifier}' was no longer valid.", identifier); context.Reject( error: OpenIdConnectConstants.Errors.InvalidGrant, diff --git a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Helpers.cs b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Helpers.cs index a24bba26..6d949cfb 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Helpers.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Helpers.cs @@ -18,12 +18,10 @@ using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Tokens; using Newtonsoft.Json.Linq; using OpenIddict.Abstractions; -using OpenIddict.Core; namespace OpenIddict.Server { - public partial class OpenIddictServerProvider : OpenIdConnectServerProvider - where TApplication : class where TAuthorization : class where TScope : class where TToken : class + public partial class OpenIddictServerProvider : OpenIdConnectServerProvider { private async Task CreateAuthorizationAsync([NotNull] AuthenticationTicket ticket, [NotNull] OpenIddictServerOptions options, [NotNull] OpenIdConnectRequest request) @@ -49,28 +47,28 @@ namespace OpenIddict.Server // If the client application is known, bind it to the authorization. if (!string.IsNullOrEmpty(request.ClientId)) { - var application = request.GetProperty($"{OpenIddictConstants.Properties.Application}:{request.ClientId}"); + var application = request.GetProperty($"{OpenIddictConstants.Properties.Application}:{request.ClientId}"); Debug.Assert(application != null, "The client application shouldn't be null."); - descriptor.ApplicationId = await Applications.GetIdAsync(application); + descriptor.ApplicationId = await _applicationManager.GetIdAsync(application); } - var authorization = await Authorizations.CreateAsync(descriptor); + var authorization = await _authorizationManager.CreateAsync(descriptor); if (authorization != null) { - var identifier = await Authorizations.GetIdAsync(authorization); + var identifier = await _authorizationManager.GetIdAsync(authorization); if (string.IsNullOrEmpty(request.ClientId)) { - Logger.LogInformation("An ad hoc authorization was automatically created and " + - "associated with an unknown application: {Identifier}.", identifier); + _logger.LogInformation("An ad hoc authorization was automatically created and " + + "associated with an unknown application: {Identifier}.", identifier); } else { - Logger.LogInformation("An ad hoc authorization was automatically created and " + - "associated with the '{ClientId}' application: {Identifier}.", - request.ClientId, identifier); + _logger.LogInformation("An ad hoc authorization was automatically created and " + + "associated with the '{ClientId}' application: {Identifier}.", + request.ClientId, identifier); } // Attach the unique identifier of the ad hoc authorization to the authentication ticket @@ -155,7 +153,7 @@ namespace OpenIddict.Server result = Base64UrlEncoder.Encode(bytes); // Obfuscate the reference identifier so it can be safely stored in the databse. - descriptor.ReferenceId = await Tokens.ObfuscateReferenceIdAsync(result); + descriptor.ReferenceId = await _tokenManager.ObfuscateReferenceIdAsync(result); } // Otherwise, only create a token metadata entry for authorization codes and refresh tokens. @@ -168,24 +166,24 @@ namespace OpenIddict.Server // If the client application is known, associate it with the token. if (!string.IsNullOrEmpty(request.ClientId)) { - var application = request.GetProperty($"{OpenIddictConstants.Properties.Application}:{request.ClientId}"); + var application = request.GetProperty($"{OpenIddictConstants.Properties.Application}:{request.ClientId}"); Debug.Assert(application != null, "The client application shouldn't be null."); - descriptor.ApplicationId = await Applications.GetIdAsync(application); + descriptor.ApplicationId = await _applicationManager.GetIdAsync(application); } // If a null value was returned by CreateAsync(), return immediately. // Note: the request cancellation token is deliberately not used here to ensure the caller // cannot prevent this operation from being executed by resetting the TCP connection. - var token = await Tokens.CreateAsync(descriptor); + var token = await _tokenManager.CreateAsync(descriptor); if (token == null) { return null; } // Throw an exception if the token identifier can't be resolved. - var identifier = await Tokens.GetIdAsync(token); + var identifier = await _tokenManager.GetIdAsync(token); if (string.IsNullOrEmpty(identifier)) { throw new InvalidOperationException("The unique key associated with a refresh token cannot be null or empty."); @@ -204,9 +202,9 @@ namespace OpenIddict.Server if (!string.IsNullOrEmpty(result)) { - Logger.LogTrace("A new reference token was successfully generated and persisted " + - "in the database: {Token} ; {Claims} ; {Properties}.", - result, ticket.Principal.Claims, ticket.Properties.Items); + _logger.LogTrace("A new reference token was successfully generated and persisted " + + "in the database: {Token} ; {Claims} ; {Properties}.", + result, ticket.Principal.Claims, ticket.Properties.Items); } return result; @@ -228,7 +226,7 @@ namespace OpenIddict.Server string identifier; AuthenticationTicket ticket; - TToken token; + object token; if (options.UseReferenceTokens) { @@ -239,14 +237,14 @@ namespace OpenIddict.Server // the property value (that may be null) is used instead of making a database call. if (request.HasProperty($"{OpenIddictConstants.Properties.ReferenceToken}:{value}")) { - token = request.GetProperty($"{OpenIddictConstants.Properties.ReferenceToken}:{value}"); + token = request.GetProperty($"{OpenIddictConstants.Properties.ReferenceToken}:{value}"); } else { // Retrieve the token entry from the database. If it // cannot be found, assume the token is not valid. - token = await Tokens.FindByReferenceIdAsync(value); + token = await _tokenManager.FindByReferenceIdAsync(value); // Store the token as a request property so it can be retrieved if this method is called another time. request.AddProperty($"{OpenIddictConstants.Properties.ReferenceToken}:{value}", token); @@ -254,28 +252,28 @@ namespace OpenIddict.Server if (token == null) { - Logger.LogInformation("The reference token corresponding to the '{Identifier}' " + - "reference identifier cannot be found in the database.", value); + _logger.LogInformation("The reference token corresponding to the '{Identifier}' " + + "reference identifier cannot be found in the database.", value); return null; } - identifier = await Tokens.GetIdAsync(token); + identifier = await _tokenManager.GetIdAsync(token); if (string.IsNullOrEmpty(identifier)) { - Logger.LogWarning("The identifier associated with the received token cannot be retrieved. " + - "This may indicate that the token entry is corrupted."); + _logger.LogWarning("The identifier associated with the received token cannot be retrieved. " + + "This may indicate that the token entry is corrupted."); return null; } // Extract the encrypted payload from the token. If it's null or empty, // assume the token is not a reference token and consider it as invalid. - var payload = await Tokens.GetPayloadAsync(token); + var payload = await _tokenManager.GetPayloadAsync(token); if (string.IsNullOrEmpty(payload)) { - Logger.LogWarning("The ciphertext associated with the token '{Identifier}' cannot be retrieved. " + - "This may indicate that the token is not a reference token.", identifier); + _logger.LogWarning("The ciphertext associated with the token '{Identifier}' cannot be retrieved. " + + "This may indicate that the token is not a reference token.", identifier); return null; } @@ -283,9 +281,9 @@ namespace OpenIddict.Server ticket = format.Unprotect(payload); if (ticket == null) { - Logger.LogWarning("The ciphertext associated with the token '{Identifier}' cannot be decrypted. " + - "This may indicate that the token entry is corrupted or tampered.", - await Tokens.GetIdAsync(token)); + _logger.LogWarning("The ciphertext associated with the token '{Identifier}' cannot be decrypted. " + + "This may indicate that the token entry is corrupted or tampered.", + await _tokenManager.GetIdAsync(token)); return null; } @@ -299,7 +297,7 @@ namespace OpenIddict.Server ticket = format.Unprotect(value); if (ticket == null) { - Logger.LogTrace("The received token was invalid or malformed: {Token}.", value); + _logger.LogTrace("The received token was invalid or malformed: {Token}.", value); return null; } @@ -307,8 +305,8 @@ namespace OpenIddict.Server identifier = ticket.GetTokenId(); if (string.IsNullOrEmpty(identifier)) { - Logger.LogWarning("The identifier associated with the received token cannot be retrieved. " + - "This may indicate that the token entry is corrupted."); + _logger.LogWarning("The identifier associated with the received token cannot be retrieved. " + + "This may indicate that the token entry is corrupted."); return null; } @@ -320,14 +318,14 @@ namespace OpenIddict.Server // the property value (that may be null) is used instead of making a database call. if (request.HasProperty($"{OpenIddictConstants.Properties.Token}:{identifier}")) { - token = request.GetProperty($"{OpenIddictConstants.Properties.Token}:{identifier}"); + token = request.GetProperty($"{OpenIddictConstants.Properties.Token}:{identifier}"); } // Otherwise, retrieve the authorization code/refresh token entry from the database. // If it cannot be found, assume the authorization code/refresh token is not valid. else { - token = await Tokens.FindByIdAsync(identifier); + token = await _tokenManager.FindByIdAsync(identifier); // Store the token as a request property so it can be retrieved if this method is called another time. request.AddProperty($"{OpenIddictConstants.Properties.Token}:{identifier}", token); @@ -335,7 +333,7 @@ namespace OpenIddict.Server if (token == null) { - Logger.LogInformation("The token '{Identifier}' cannot be found in the database.", ticket.GetTokenId()); + _logger.LogInformation("The token '{Identifier}' cannot be found in the database.", ticket.GetTokenId()); return null; } @@ -351,16 +349,16 @@ namespace OpenIddict.Server ticket.SetTokenId(identifier); // Dynamically set the creation and expiration dates. - ticket.Properties.IssuedUtc = await Tokens.GetCreationDateAsync(token); - ticket.Properties.ExpiresUtc = await Tokens.GetExpirationDateAsync(token); + ticket.Properties.IssuedUtc = await _tokenManager.GetCreationDateAsync(token); + ticket.Properties.ExpiresUtc = await _tokenManager.GetExpirationDateAsync(token); // Restore the authorization identifier using the identifier attached with the database entry. ticket.SetProperty(OpenIddictConstants.Properties.AuthorizationId, - await Tokens.GetAuthorizationIdAsync(token)); + await _tokenManager.GetAuthorizationIdAsync(token)); - Logger.LogTrace("The token '{Identifier}' was successfully decrypted and " + - "retrieved from the database: {Claims} ; {Properties}.", - ticket.GetTokenId(), ticket.Principal.Claims, ticket.Properties.Items); + _logger.LogTrace("The token '{Identifier}' was successfully decrypted and " + + "retrieved from the database: {Claims} ; {Properties}.", + ticket.GetTokenId(), ticket.Principal.Claims, ticket.Properties.Items); return ticket; } @@ -376,7 +374,7 @@ namespace OpenIddict.Server return true; } - var authorization = await Authorizations.FindByIdAsync(identifier); + var authorization = await _authorizationManager.FindByIdAsync(identifier); if (authorization == null) { return true; @@ -386,42 +384,42 @@ namespace OpenIddict.Server { // Note: the request cancellation token is deliberately not used here to ensure the caller // cannot prevent this operation from being executed by resetting the TCP connection. - await Authorizations.RevokeAsync(authorization); + await _authorizationManager.RevokeAsync(authorization); - Logger.LogInformation("The authorization '{Identifier}' was automatically revoked.", identifier); + _logger.LogInformation("The authorization '{Identifier}' was automatically revoked.", identifier); return true; } catch (Exception exception) { - Logger.LogDebug(exception, "An exception occurred while trying to revoke the authorization " + - "associated with the token '{Identifier}'.", identifier); + _logger.LogDebug(exception, "An exception occurred while trying to revoke the authorization " + + "associated with the token '{Identifier}'.", identifier); return false; } } - private async Task TryRevokeTokenAsync([NotNull] TToken token) + private async Task TryRevokeTokenAsync([NotNull] object token) { - var identifier = await Tokens.GetIdAsync(token); + var identifier = await _tokenManager.GetIdAsync(token); Debug.Assert(!string.IsNullOrEmpty(identifier), "The token identifier shouldn't be null or empty."); try { // Note: the request cancellation token is deliberately not used here to ensure the caller // cannot prevent this operation from being executed by resetting the TCP connection. - await Tokens.RevokeAsync(token); + await _tokenManager.RevokeAsync(token); - Logger.LogInformation("The token '{Identifier}' was automatically revoked.", identifier); + _logger.LogInformation("The token '{Identifier}' was automatically revoked.", identifier); return true; } catch (Exception exception) { - Logger.LogDebug(exception, "An exception occurred while trying to revoke " + - "the token '{Identifier}'.", identifier); + _logger.LogDebug(exception, "An exception occurred while trying to revoke " + + "the token '{Identifier}'.", identifier); return false; } @@ -438,10 +436,10 @@ namespace OpenIddict.Server var result = true; - foreach (var token in await Tokens.FindByAuthorizationIdAsync(identifier)) + foreach (var token in await _tokenManager.FindByAuthorizationIdAsync(identifier)) { // Don't change the status of the token used in the token request. - if (string.Equals(ticket.GetTokenId(), await Tokens.GetIdAsync(token), StringComparison.Ordinal)) + if (string.Equals(ticket.GetTokenId(), await _tokenManager.GetIdAsync(token), StringComparison.Ordinal)) { continue; } @@ -452,33 +450,33 @@ namespace OpenIddict.Server return result; } - private async Task TryRedeemTokenAsync([NotNull] TToken token) + private async Task TryRedeemTokenAsync([NotNull] object token) { - var identifier = await Tokens.GetIdAsync(token); + var identifier = await _tokenManager.GetIdAsync(token); Debug.Assert(!string.IsNullOrEmpty(identifier), "The token identifier shouldn't be null or empty."); try { // Note: the request cancellation token is deliberately not used here to ensure the caller // cannot prevent this operation from being executed by resetting the TCP connection. - await Tokens.RedeemAsync(token); + await _tokenManager.RedeemAsync(token); - Logger.LogInformation("The token '{Identifier}' was automatically marked as redeemed.", identifier); + _logger.LogInformation("The token '{Identifier}' was automatically marked as redeemed.", identifier); return true; } catch (Exception exception) { - Logger.LogDebug(exception, "An exception occurred while trying to " + - "redeem the token '{Identifier}'.", identifier); + _logger.LogDebug(exception, "An exception occurred while trying to " + + "redeem the token '{Identifier}'.", identifier); return false; } } private async Task TryExtendTokenAsync( - [NotNull] TToken token, [NotNull] AuthenticationTicket ticket, [NotNull] OpenIddictServerOptions options) + [NotNull] object token, [NotNull] AuthenticationTicket ticket, [NotNull] OpenIddictServerOptions options) { var identifier = ticket.GetTokenId(); Debug.Assert(!string.IsNullOrEmpty(identifier), "The token identifier shouldn't be null or empty."); @@ -491,18 +489,18 @@ namespace OpenIddict.Server // Note: the request cancellation token is deliberately not used here to ensure the caller // cannot prevent this operation from being executed by resetting the TCP connection. - await Tokens.ExtendAsync(token, date); + await _tokenManager.ExtendAsync(token, date); - Logger.LogInformation("The expiration date of the refresh token '{Identifier}' " + - "was automatically updated: {Date}.", identifier, date); + _logger.LogInformation("The expiration date of the refresh token '{Identifier}' " + + "was automatically updated: {Date}.", identifier, date); return true; } catch (Exception exception) { - Logger.LogDebug(exception, "An exception occurred while trying to update the " + - "expiration date of the token '{Identifier}'.", identifier); + _logger.LogDebug(exception, "An exception occurred while trying to update the " + + "expiration date of the token '{Identifier}'.", identifier); return false; } @@ -544,8 +542,8 @@ namespace OpenIddict.Server catch (Exception exception) { - Logger.LogWarning(exception, "An error occurred while parsing the public property " + - "'{Name}' from the authentication ticket.", name); + _logger.LogWarning(exception, "An error occurred while parsing the public property " + + "'{Name}' from the authentication ticket.", name); continue; } @@ -568,8 +566,8 @@ namespace OpenIddict.Server catch (Exception exception) { - Logger.LogWarning(exception, "An error occurred while parsing the public property " + - "'{Name}' from the authentication ticket.", name); + _logger.LogWarning(exception, "An error occurred while parsing the public property " + + "'{Name}' from the authentication ticket.", name); continue; } @@ -585,8 +583,8 @@ namespace OpenIddict.Server if (request.IsAuthorizationRequest() || request.IsLogoutRequest()) { - Logger.LogWarning("The JSON property '{Name}' was excluded as it was not " + - "compatible with the OpenID Connect response type.", name); + _logger.LogWarning("The JSON property '{Name}' was excluded as it was not " + + "compatible with the OpenID Connect response type.", name); continue; } @@ -600,8 +598,8 @@ namespace OpenIddict.Server catch (Exception exception) { - Logger.LogWarning(exception, "An error occurred while deserializing the public JSON " + - "property '{Name}' from the authentication ticket.", name); + _logger.LogWarning(exception, "An error occurred while deserializing the public JSON " + + "property '{Name}' from the authentication ticket.", name); continue; } diff --git a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Introspection.cs b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Introspection.cs index 683619a8..9748cc96 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Introspection.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Introspection.cs @@ -16,8 +16,7 @@ using OpenIddict.Abstractions; namespace OpenIddict.Server { - public partial class OpenIddictServerProvider : OpenIdConnectServerProvider - where TApplication : class where TAuthorization : class where TScope : class where TToken : class + public partial class OpenIddictServerProvider : OpenIdConnectServerProvider { public override Task ExtractIntrospectionRequest([NotNull] ExtractIntrospectionRequestContext context) { @@ -51,11 +50,11 @@ namespace OpenIddict.Server } // Retrieve the application details corresponding to the requested client_id. - var application = await Applications.FindByClientIdAsync(context.ClientId); + var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - Logger.LogError("The introspection request was rejected because the client " + - "application was not found: '{ClientId}'.", context.ClientId); + _logger.LogError("The introspection request was rejected because the client " + + "application was not found: '{ClientId}'.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, @@ -69,10 +68,10 @@ namespace OpenIddict.Server context.Request.SetProperty($"{OpenIddictConstants.Properties.Application}:{context.ClientId}", application); // Reject the request if the application is not allowed to use the introspection endpoint. - if (!await Applications.HasPermissionAsync(application, OpenIddictConstants.Permissions.Endpoints.Introspection)) + if (!await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.Endpoints.Introspection)) { - Logger.LogError("The introspection request was rejected because the application '{ClientId}' " + - "was not allowed to use the introspection endpoint.", context.ClientId); + _logger.LogError("The introspection request was rejected because the application '{ClientId}' " + + "was not allowed to use the introspection endpoint.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.UnauthorizedClient, @@ -82,10 +81,10 @@ namespace OpenIddict.Server } // Reject introspection requests sent by public applications. - if (await Applications.IsPublicAsync(application)) + if (await _applicationManager.IsPublicAsync(application)) { - Logger.LogError("The introspection request was rejected because the public application " + - "'{ClientId}' was not allowed to use this endpoint.", context.ClientId); + _logger.LogError("The introspection request was rejected because the public application " + + "'{ClientId}' was not allowed to use this endpoint.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, @@ -95,10 +94,10 @@ namespace OpenIddict.Server } // Validate the client credentials. - if (!await Applications.ValidateClientSecretAsync(application, context.ClientSecret)) + if (!await _applicationManager.ValidateClientSecretAsync(application, context.ClientSecret)) { - Logger.LogError("The introspection request was rejected because the confidential or hybrid application " + - "'{ClientId}' didn't specify valid client credentials.", context.ClientId); + _logger.LogError("The introspection request was rejected because the confidential or hybrid application " + + "'{ClientId}' didn't specify valid client credentials.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, @@ -122,7 +121,7 @@ namespace OpenIddict.Server if (!context.Ticket.IsAccessToken()) { - Logger.LogError("The token '{Identifier}' is not an access token and thus cannot be introspected.", identifier); + _logger.LogError("The token '{Identifier}' is not an access token and thus cannot be introspected.", identifier); context.Active = false; @@ -134,9 +133,9 @@ namespace OpenIddict.Server // For that, an error is automatically returned if no explicit audience is attached to the authentication ticket. if (!context.Ticket.HasAudience()) { - Logger.LogError("The token '{Identifier}' doesn't have any audience attached " + - "and cannot be introspected. To add an audience, use the " + - "'ticket.SetResources(...)' extension when creating the ticket.", identifier); + _logger.LogError("The token '{Identifier}' doesn't have any audience attached " + + "and cannot be introspected. To add an audience, use the " + + "'ticket.SetResources(...)' extension when creating the ticket.", identifier); context.Active = false; @@ -145,9 +144,9 @@ namespace OpenIddict.Server if (!context.Ticket.HasAudience(context.Request.ClientId)) { - Logger.LogError("The client application '{ClientId}' is not allowed to introspect the access " + - "token '{Identifier}' because it's not listed as a valid audience.", - context.Request.ClientId, identifier); + _logger.LogError("The client application '{ClientId}' is not allowed to introspect the access " + + "token '{Identifier}' because it's not listed as a valid audience.", + context.Request.ClientId, identifier); context.Active = false; @@ -162,12 +161,12 @@ namespace OpenIddict.Server } // Retrieve the token from the request properties. If it's marked as invalid, return active = false. - var token = context.Request.GetProperty($"{OpenIddictConstants.Properties.Token}:{identifier}"); + var token = context.Request.GetProperty($"{OpenIddictConstants.Properties.Token}:{identifier}"); Debug.Assert(token != null, "The token shouldn't be null."); - if (!await Tokens.IsValidAsync(token)) + if (!await _tokenManager.IsValidAsync(token)) { - Logger.LogInformation("The token '{Identifier}' was declared as inactive because it was revoked.", identifier); + _logger.LogInformation("The token '{Identifier}' was declared as inactive because it was revoked.", identifier); context.Active = false; diff --git a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Revocation.cs b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Revocation.cs index 935ffbf4..bd577209 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Revocation.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Revocation.cs @@ -16,8 +16,7 @@ using OpenIddict.Abstractions; namespace OpenIddict.Server { - public partial class OpenIddictServerProvider : OpenIdConnectServerProvider - where TApplication : class where TAuthorization : class where TScope : class where TToken : class + public partial class OpenIddictServerProvider : OpenIdConnectServerProvider { public override async Task ValidateRevocationRequest([NotNull] ValidateRevocationRequestContext context) { @@ -58,8 +57,8 @@ namespace OpenIddict.Server // Reject the request if client identification is mandatory. if (options.RequireClientIdentification) { - Logger.LogError("The revocation request was rejected becaused the " + - "mandatory client_id parameter was missing or empty."); + _logger.LogError("The revocation request was rejected becaused the " + + "mandatory client_id parameter was missing or empty."); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -68,8 +67,8 @@ namespace OpenIddict.Server return; } - Logger.LogDebug("The revocation request validation process was skipped " + - "because the client_id parameter was missing or empty."); + _logger.LogDebug("The revocation request validation process was skipped " + + "because the client_id parameter was missing or empty."); context.Skip(); @@ -77,11 +76,11 @@ namespace OpenIddict.Server } // Retrieve the application details corresponding to the requested client_id. - var application = await Applications.FindByClientIdAsync(context.ClientId); + var application = await _applicationManager.FindByClientIdAsync(context.ClientId); if (application == null) { - Logger.LogError("The revocation request was rejected because the client " + - "application was not found: '{ClientId}'.", context.ClientId); + _logger.LogError("The revocation request was rejected because the client " + + "application was not found: '{ClientId}'.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, @@ -95,10 +94,10 @@ namespace OpenIddict.Server context.Request.SetProperty($"{OpenIddictConstants.Properties.Application}:{context.ClientId}", application); // Reject the request if the application is not allowed to use the revocation endpoint. - if (!await Applications.HasPermissionAsync(application, OpenIddictConstants.Permissions.Endpoints.Revocation)) + if (!await _applicationManager.HasPermissionAsync(application, OpenIddictConstants.Permissions.Endpoints.Revocation)) { - Logger.LogError("The revocation request was rejected because the application '{ClientId}' " + - "was not allowed to use the revocation endpoint.", context.ClientId); + _logger.LogError("The revocation request was rejected because the application '{ClientId}' " + + "was not allowed to use the revocation endpoint.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.UnauthorizedClient, @@ -108,12 +107,12 @@ namespace OpenIddict.Server } // Reject revocation requests containing a client_secret if the application is a public client. - if (await Applications.IsPublicAsync(application)) + if (await _applicationManager.IsPublicAsync(application)) { if (!string.IsNullOrEmpty(context.ClientSecret)) { - Logger.LogError("The revocation request was rejected because the public application " + - "'{ClientId}' was not allowed to use this endpoint.", context.ClientId); + _logger.LogError("The revocation request was rejected because the public application " + + "'{ClientId}' was not allowed to use this endpoint.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -122,8 +121,8 @@ namespace OpenIddict.Server return; } - Logger.LogDebug("The revocation request validation process was not fully validated because " + - "the client '{ClientId}' was a public application.", context.ClientId); + _logger.LogDebug("The revocation request validation process was not fully validated because " + + "the client '{ClientId}' was a public application.", context.ClientId); // If client authentication cannot be enforced, call context.Skip() to inform // the OpenID Connect server middleware that the caller cannot be fully trusted. @@ -136,8 +135,8 @@ namespace OpenIddict.Server // to protect them from impersonation attacks. if (string.IsNullOrEmpty(context.ClientSecret)) { - Logger.LogError("The revocation request was rejected because the confidential or hybrid application " + - "'{ClientId}' didn't specify a client secret.", context.ClientId); + _logger.LogError("The revocation request was rejected because the confidential or hybrid application " + + "'{ClientId}' didn't specify a client secret.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, @@ -146,10 +145,10 @@ namespace OpenIddict.Server return; } - if (!await Applications.ValidateClientSecretAsync(application, context.ClientSecret)) + if (!await _applicationManager.ValidateClientSecretAsync(application, context.ClientSecret)) { - Logger.LogError("The revocation request was rejected because the confidential or hybrid application " + - "'{ClientId}' didn't specify valid client credentials.", context.ClientId); + _logger.LogError("The revocation request was rejected because the confidential or hybrid application " + + "'{ClientId}' didn't specify valid client credentials.", context.ClientId); context.Reject( error: OpenIdConnectConstants.Errors.InvalidClient, @@ -171,7 +170,7 @@ namespace OpenIddict.Server // return an error to indicate that the token cannot be revoked. if (context.Ticket.IsIdentityToken()) { - Logger.LogError("The revocation request was rejected because identity tokens are not revocable."); + _logger.LogError("The revocation request was rejected because identity tokens are not revocable."); context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedTokenType, @@ -183,7 +182,7 @@ namespace OpenIddict.Server // If the received token is an access token, return an error if reference tokens are not enabled. if (!options.UseReferenceTokens && context.Ticket.IsAccessToken()) { - Logger.LogError("The revocation request was rejected because the access token was not revocable."); + _logger.LogError("The revocation request was rejected because the access token was not revocable."); context.Reject( error: OpenIdConnectConstants.Errors.UnsupportedTokenType, @@ -197,13 +196,13 @@ namespace OpenIddict.Server Debug.Assert(!string.IsNullOrEmpty(identifier), "The authentication ticket should contain a token identifier."); // Retrieve the token from the request properties. If it's already marked as revoked, directly return a 200 response. - var token = context.Request.GetProperty($"{OpenIddictConstants.Properties.Token}:{identifier}"); + var token = context.Request.GetProperty($"{OpenIddictConstants.Properties.Token}:{identifier}"); Debug.Assert(token != null, "The token shouldn't be null."); - if (await Tokens.IsRevokedAsync(token)) + if (await _tokenManager.IsRevokedAsync(token)) { - Logger.LogInformation("The token '{Identifier}' was not revoked because " + - "it was already marked as invalid.", identifier); + _logger.LogInformation("The token '{Identifier}' was not revoked because " + + "it was already marked as invalid.", identifier); context.Revoked = true; @@ -215,18 +214,18 @@ namespace OpenIddict.Server // will be returned to the client application. try { - await Tokens.RevokeAsync(token); + await _tokenManager.RevokeAsync(token); } catch (Exception exception) { - Logger.LogWarning(exception, "An exception occurred while trying to revoke the authorization " + - "associated with the token '{Identifier}'.", identifier); + _logger.LogWarning(exception, "An exception occurred while trying to revoke the authorization " + + "associated with the token '{Identifier}'.", identifier); return; } - Logger.LogInformation("The token '{Identifier}' was successfully revoked.", identifier); + _logger.LogInformation("The token '{Identifier}' was successfully revoked.", identifier); context.Revoked = true; } diff --git a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Serialization.cs b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Serialization.cs index dc62d97c..a39d2154 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Serialization.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Serialization.cs @@ -12,8 +12,7 @@ using JetBrains.Annotations; namespace OpenIddict.Server { - public partial class OpenIddictServerProvider : OpenIdConnectServerProvider - where TApplication : class where TAuthorization : class where TScope : class where TToken : class + public partial class OpenIddictServerProvider : OpenIdConnectServerProvider { public override async Task DeserializeAccessToken([NotNull] DeserializeAccessTokenContext context) { diff --git a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Session.cs b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Session.cs index 68148475..bbfbae00 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Session.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Session.cs @@ -22,8 +22,7 @@ using OpenIddict.Abstractions; namespace OpenIddict.Server { - public partial class OpenIddictServerProvider : OpenIdConnectServerProvider - where TApplication : class where TAuthorization : class where TScope : class where TToken : class + public partial class OpenIddictServerProvider : OpenIdConnectServerProvider { public override async Task ExtractLogoutRequest([NotNull] ExtractLogoutRequestContext context) { @@ -36,8 +35,7 @@ namespace OpenIddict.Server // Return an error if request caching support was not enabled. if (!options.EnableRequestCaching) { - Logger.LogError("The logout request was rejected because " + - "request caching support was not enabled."); + _logger.LogError("The logout request was rejected because request caching support was not enabled."); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -53,8 +51,8 @@ namespace OpenIddict.Server var payload = await options.Cache.GetAsync(key); if (payload == null) { - Logger.LogError("The logout request was rejected because an unknown " + - "or invalid request_id parameter was specified."); + _logger.LogError("The logout request was rejected because an unknown " + + "or invalid request_id parameter was specified."); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -87,8 +85,8 @@ namespace OpenIddict.Server { if (!Uri.TryCreate(context.PostLogoutRedirectUri, UriKind.Absolute, out Uri uri) || !uri.IsWellFormedOriginalString()) { - Logger.LogError("The logout request was rejected because the specified post_logout_redirect_uri was not " + - "a valid absolute URL: {PostLogoutRedirectUri}.", context.PostLogoutRedirectUri); + _logger.LogError("The logout request was rejected because the specified post_logout_redirect_uri was not " + + "a valid absolute URL: {PostLogoutRedirectUri}.", context.PostLogoutRedirectUri); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -99,8 +97,8 @@ namespace OpenIddict.Server if (!string.IsNullOrEmpty(uri.Fragment)) { - Logger.LogError("The logout request was rejected because the 'post_logout_redirect_uri' contained " + - "a URL fragment: {PostLogoutRedirectUri}.", context.PostLogoutRedirectUri); + _logger.LogError("The logout request was rejected because the 'post_logout_redirect_uri' contained " + + "a URL fragment: {PostLogoutRedirectUri}.", context.PostLogoutRedirectUri); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, @@ -109,10 +107,10 @@ namespace OpenIddict.Server return; } - if (!await Applications.ValidatePostLogoutRedirectUriAsync(context.PostLogoutRedirectUri)) + if (!await _applicationManager.ValidatePostLogoutRedirectUriAsync(context.PostLogoutRedirectUri)) { - Logger.LogError("The logout request was rejected because the specified post_logout_redirect_uri " + - "was unknown: {PostLogoutRedirectUri}.", context.PostLogoutRedirectUri); + _logger.LogError("The logout request was rejected because the specified post_logout_redirect_uri " + + "was unknown: {PostLogoutRedirectUri}.", context.PostLogoutRedirectUri); context.Reject( error: OpenIdConnectConstants.Errors.InvalidRequest, diff --git a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Userinfo.cs b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Userinfo.cs index 779c2d84..a3e21298 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Userinfo.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Userinfo.cs @@ -10,8 +10,7 @@ using JetBrains.Annotations; namespace OpenIddict.Server { - public partial class OpenIddictServerProvider : OpenIdConnectServerProvider - where TApplication : class where TAuthorization : class where TScope : class where TToken : class + public partial class OpenIddictServerProvider : OpenIdConnectServerProvider { public override Task ExtractUserinfoRequest([NotNull] ExtractUserinfoRequestContext context) { diff --git a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.cs b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.cs index 731b3b56..15559520 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.cs @@ -15,7 +15,6 @@ using JetBrains.Annotations; using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Logging; using OpenIddict.Abstractions; -using OpenIddict.Core; namespace OpenIddict.Server { @@ -23,51 +22,28 @@ namespace OpenIddict.Server /// Provides the logic necessary to extract, validate and handle OpenID Connect requests. /// [EditorBrowsable(EditorBrowsableState.Never)] - public partial class OpenIddictServerProvider : OpenIdConnectServerProvider - where TApplication : class where TAuthorization : class where TScope : class where TToken : class + public partial class OpenIddictServerProvider : OpenIdConnectServerProvider { - /// - /// Creates a new instance of the class. - /// + public readonly ILogger _logger; + public readonly IOpenIddictApplicationManager _applicationManager; + public readonly IOpenIddictAuthorizationManager _authorizationManager; + public readonly IOpenIddictScopeManager _scopeManager; + public readonly IOpenIddictTokenManager _tokenManager; + public OpenIddictServerProvider( - [NotNull] ILogger> logger, - [NotNull] OpenIddictApplicationManager applications, - [NotNull] OpenIddictAuthorizationManager authorizations, - [NotNull] OpenIddictScopeManager scopes, - [NotNull] OpenIddictTokenManager tokens) + [NotNull] ILogger logger, + [NotNull] IOpenIddictApplicationManager applicationManager, + [NotNull] IOpenIddictAuthorizationManager authorizationManager, + [NotNull] IOpenIddictScopeManager scopeManager, + [NotNull] IOpenIddictTokenManager tokenManager) { - Applications = applications; - Authorizations = authorizations; - Logger = logger; - Scopes = scopes; - Tokens = tokens; + _logger = logger; + _applicationManager = applicationManager; + _authorizationManager = authorizationManager; + _scopeManager = scopeManager; + _tokenManager = tokenManager; } - /// - /// Gets the applications manager. - /// - public OpenIddictApplicationManager Applications { get; } - - /// - /// Gets the authorizations manager. - /// - public OpenIddictAuthorizationManager Authorizations { get; } - - /// - /// Gets the logger associated with the current class. - /// - public ILogger Logger { get; } - - /// - /// Gets the scopes manager. - /// - public OpenIddictScopeManager Scopes { get; } - - /// - /// Gets the tokens manager. - /// - public OpenIddictTokenManager Tokens { get; } - public override Task ProcessChallengeResponse([NotNull] ProcessChallengeResponseContext context) { Debug.Assert(context.Request.IsAuthorizationRequest() || @@ -148,7 +124,7 @@ namespace OpenIddict.Server return; } - var token = context.Request.GetProperty($"{OpenIddictConstants.Properties.Token}:{context.Ticket.GetTokenId()}"); + var token = context.Request.GetProperty($"{OpenIddictConstants.Properties.Token}:{context.Ticket.GetTokenId()}"); Debug.Assert(token != null, "The token shouldn't be null."); // If rolling tokens are enabled or if the request is a grant_type=authorization_code request, diff --git a/src/OpenIddict.Server/OpenIddict.Server.csproj b/src/OpenIddict.Server/OpenIddict.Server.csproj index d7162d51..ce02ae8b 100644 --- a/src/OpenIddict.Server/OpenIddict.Server.csproj +++ b/src/OpenIddict.Server/OpenIddict.Server.csproj @@ -13,13 +13,14 @@ - + + diff --git a/src/OpenIddict.Server/OpenIddictServerBuilder.cs b/src/OpenIddict.Server/OpenIddictServerBuilder.cs index 5a58c62e..6bccc492 100644 --- a/src/OpenIddict.Server/OpenIddictServerBuilder.cs +++ b/src/OpenIddict.Server/OpenIddictServerBuilder.cs @@ -12,13 +12,11 @@ using System.IO; using System.Linq; using System.Reflection; using System.Security.Cryptography.X509Certificates; -using System.Threading; using AspNet.Security.OpenIdConnect.Primitives; using JetBrains.Annotations; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http; using Microsoft.IdentityModel.Tokens; -using OpenIddict.Core; using OpenIddict.Server; namespace Microsoft.Extensions.DependencyInjection @@ -453,8 +451,7 @@ namespace Microsoft.Extensions.DependencyInjection /// /// Rejects authorization and token requests that specify scopes that have not been - /// registered using or - /// . + /// registered using or the scope manager. /// /// The . public OpenIddictServerBuilder EnableScopeValidation() diff --git a/src/OpenIddict.Server/OpenIddictServerExtensions.cs b/src/OpenIddict.Server/OpenIddictServerExtensions.cs index 5dc99df8..07e5d30e 100644 --- a/src/OpenIddict.Server/OpenIddictServerExtensions.cs +++ b/src/OpenIddict.Server/OpenIddictServerExtensions.cs @@ -5,7 +5,6 @@ */ using System; -using System.Text; using AspNet.Security.OpenIdConnect.Server; using JetBrains.Annotations; using Microsoft.AspNetCore.Authentication; @@ -32,46 +31,15 @@ namespace Microsoft.Extensions.DependencyInjection builder.Services.AddAuthentication(); + builder.Services.TryAddScoped(); + builder.Services.TryAddScoped(); + // Register the options initializers used by the OpenID Connect server handler and OpenIddict. // Note: TryAddEnumerable() is used here to ensure the initializers are only registered once. builder.Services.TryAddEnumerable(new[] { - ServiceDescriptor.Singleton, - OpenIddictServerInitializer>(), - ServiceDescriptor.Singleton, - OpenIdConnectServerInitializer>() - }); - - // Register the OpenIddict handler/provider. - builder.Services.TryAddScoped(typeof(OpenIddictServerProvider<,,,>)); - builder.Services.TryAddScoped(); - builder.Services.TryAddScoped(provider => - { - var options = provider.GetRequiredService>() - .Get(OpenIddictServerDefaults.AuthenticationScheme); - - if (options == null) - { - throw new InvalidOperationException("The OpenIddict validation options cannot be resolved."); - } - - if (options.ApplicationType == null || options.AuthorizationType == null || - options.ScopeType == null || options.TokenType == null) - { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The entity types must be configured for the token server services to work correctly.") - .Append("To configure the entities, use either 'services.AddOpenIddict().AddCore().UseDefaultModels()' ") - .Append("or 'services.AddOpenIddict().AddCore().UseCustomModels()'.") - .ToString()); - } - - var type = typeof(OpenIddictServerProvider<,,,>).MakeGenericType( - /* TApplication: */ options.ApplicationType, - /* TAuthorization: */ options.AuthorizationType, - /* TScope: */ options.ScopeType, - /* TToken: */ options.TokenType); - - return (OpenIdConnectServerProvider) provider.GetRequiredService(type); + ServiceDescriptor.Singleton, OpenIddictServerInitializer>(), + ServiceDescriptor.Singleton, OpenIdConnectServerInitializer>() }); // Register the OpenID Connect server handler in the authentication options, diff --git a/src/OpenIddict.Server/OpenIddictServerOptions.cs b/src/OpenIddict.Server/OpenIddictServerOptions.cs index 9fdda579..a81072c2 100644 --- a/src/OpenIddict.Server/OpenIddictServerOptions.cs +++ b/src/OpenIddict.Server/OpenIddictServerOptions.cs @@ -14,7 +14,7 @@ using Microsoft.Extensions.Caching.Distributed; namespace OpenIddict.Server { /// - /// Provides various settings needed to configure OpenIddict. + /// Provides various settings needed to configure the OpenIddict server handler. /// public class OpenIddictServerOptions : OpenIdConnectServerOptions { @@ -23,22 +23,10 @@ namespace OpenIddict.Server /// public OpenIddictServerOptions() { - // Note: OpenIdConnectServerProvider is automatically mapped - // to the generic OpenIddictProvider class by the DI container. Provider = null; - ProviderType = typeof(OpenIdConnectServerProvider); + ProviderType = typeof(OpenIddictServerProvider); } - /// - /// Gets or sets the type corresponding to the Application entity. - /// - public Type ApplicationType { get; set; } - - /// - /// Gets or sets the type corresponding to the Authorization entity. - /// - public Type AuthorizationType { get; set; } - /// /// Gets or sets the distributed cache used by OpenIddict. If no cache is explicitly /// provided, the cache registered in the dependency injection container is used. @@ -103,16 +91,6 @@ namespace OpenIddict.Server OpenIdConnectConstants.Scopes.OpenId }; - /// - /// Gets or sets the type corresponding to the Scope entity. - /// - public Type ScopeType { get; set; } - - /// - /// Gets or sets the type corresponding to the Token entity. - /// - public Type TokenType { get; set; } - /// /// Gets or sets a boolean indicating whether reference tokens should be used. /// When set to true, authorization codes, access tokens and refresh tokens diff --git a/src/OpenIddict.Validation/Internal/OpenIddictValidationHandler.cs b/src/OpenIddict.Validation/Internal/OpenIddictValidationHandler.cs index e4f37de8..792caefb 100644 --- a/src/OpenIddict.Validation/Internal/OpenIddictValidationHandler.cs +++ b/src/OpenIddict.Validation/Internal/OpenIddictValidationHandler.cs @@ -7,6 +7,7 @@ using System; using System.ComponentModel; using System.Security.Claims; +using System.Text; using System.Text.Encodings.Web; using System.Threading.Tasks; using AspNet.Security.OAuth.Validation; @@ -18,25 +19,11 @@ using Microsoft.Extensions.Options; using Microsoft.Net.Http.Headers; using Newtonsoft.Json.Linq; using OpenIddict.Abstractions; -using OpenIddict.Core; namespace OpenIddict.Validation { [EditorBrowsable(EditorBrowsableState.Never)] public class OpenIddictValidationHandler : OAuthValidationHandler - { - public OpenIddictValidationHandler( - [NotNull] IOptionsMonitor options, - [NotNull] ILoggerFactory logger, - [NotNull] UrlEncoder encoder, - [NotNull] ISystemClock clock) - : base(options, logger, encoder, clock) - { - } - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public class OpenIddictValidationHandler : OpenIddictValidationHandler where TToken : class { public OpenIddictValidationHandler( [NotNull] IOptionsMonitor options, @@ -49,6 +36,11 @@ namespace OpenIddict.Validation protected override async Task HandleAuthenticateAsync() { + if (!Options.UseReferenceTokens) + { + return await base.HandleAuthenticateAsync(); + } + var context = new RetrieveTokenContext(Context, Scheme, Options); await Events.RetrieveToken(context); @@ -197,10 +189,15 @@ namespace OpenIddict.Validation private async Task CreateTicketAsync(string payload) { - var manager = Context.RequestServices.GetService>(); + // Note: the token manager is deliberately not injected using constructor injection + // to allow using the validation handler without having to register the core services. + var manager = Context.RequestServices.GetService(); if (manager == null) { - throw new InvalidOperationException("The token manager was not correctly registered."); + throw new InvalidOperationException(new StringBuilder() + .AppendLine("The core services must be registered when enabling reference tokens support.") + .Append("To register the OpenIddict core services, use 'services.AddOpenIddict().AddCore()'.") + .ToString()); } // Retrieve the token entry from the database. If it @@ -282,5 +279,7 @@ namespace OpenIddict.Validation } private new OAuthValidationEvents Events => (OAuthValidationEvents) base.Events; + + private new OpenIddictValidationOptions Options => (OpenIddictValidationOptions) base.Options; } } diff --git a/src/OpenIddict.Validation/Internal/OpenIddictValidationInitializer.cs b/src/OpenIddict.Validation/Internal/OpenIddictValidationInitializer.cs index a241ee33..8c4d618c 100644 --- a/src/OpenIddict.Validation/Internal/OpenIddictValidationInitializer.cs +++ b/src/OpenIddict.Validation/Internal/OpenIddictValidationInitializer.cs @@ -11,7 +11,6 @@ using JetBrains.Annotations; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.DataProtection; using Microsoft.Extensions.Options; -using OpenIddict.Core; namespace OpenIddict.Validation { @@ -23,17 +22,13 @@ namespace OpenIddict.Validation public class OpenIddictValidationInitializer : IPostConfigureOptions { private readonly IDataProtectionProvider _dataProtectionProvider; - private readonly IOptionsMonitor _options; /// /// Creates a new instance of the class. /// - public OpenIddictValidationInitializer( - [NotNull] IDataProtectionProvider dataProtectionProvider, - [NotNull] IOptionsMonitor options) + public OpenIddictValidationInitializer([NotNull] IDataProtectionProvider dataProtectionProvider) { _dataProtectionProvider = dataProtectionProvider; - _options = options; } /// @@ -73,11 +68,6 @@ namespace OpenIddict.Validation options.AccessTokenFormat = new TicketDataFormat(protector); } - - if (options.TokenType == null) - { - options.TokenType = _options.CurrentValue.DefaultTokenType; - } } } } diff --git a/src/OpenIddict.Validation/OpenIddict.Validation.csproj b/src/OpenIddict.Validation/OpenIddict.Validation.csproj index c9e71ee6..8be61717 100644 --- a/src/OpenIddict.Validation/OpenIddict.Validation.csproj +++ b/src/OpenIddict.Validation/OpenIddict.Validation.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/OpenIddict.Validation/OpenIddictValidationExtensions.cs b/src/OpenIddict.Validation/OpenIddictValidationExtensions.cs index d1145a6e..6c1d9647 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationExtensions.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationExtensions.cs @@ -5,13 +5,10 @@ */ using System; -using System.Text; -using System.Text.Encodings.Web; using AspNet.Security.OAuth.Validation; using JetBrains.Annotations; using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using OpenIddict.Validation; @@ -34,52 +31,15 @@ namespace Microsoft.Extensions.DependencyInjection builder.Services.AddAuthentication(); + builder.Services.TryAddScoped(); + // Note: TryAddEnumerable() is used here to ensure the initializer is only registered once. builder.Services.TryAddEnumerable(new[] { - ServiceDescriptor.Singleton, - OpenIddictValidationInitializer>(), - ServiceDescriptor.Singleton, - OAuthValidationInitializer>() + ServiceDescriptor.Singleton, OpenIddictValidationInitializer>(), + ServiceDescriptor.Singleton, OAuthValidationInitializer>() }); - builder.Services.TryAddScoped(typeof(OpenIddictValidationHandler<>)); - builder.Services.TryAddScoped(provider => - { - var options = provider.GetRequiredService>() - .Get(OpenIddictValidationDefaults.AuthenticationScheme); - - if (options == null) - { - throw new InvalidOperationException("The OpenIddict validation options cannot be resolved."); - } - - if (options.UseReferenceTokens) - { - if (options.TokenType == null) - { - throw new InvalidOperationException(new StringBuilder() - .AppendLine("The entity types must be configured for the token validation services to work correctly.") - .Append("To configure the entities, use either 'services.AddOpenIddict().AddCore().UseDefaultModels()' ") - .Append("or 'services.AddOpenIddict().AddCore().UseCustomModels()'.") - .ToString()); - } - - var type = typeof(OpenIddictValidationHandler<>).MakeGenericType(options.TokenType); - return (OpenIddictValidationHandler) provider.GetService(type); - } - - return new OpenIddictValidationHandler( - provider.GetRequiredService>(), - provider.GetRequiredService(), - provider.GetRequiredService(), - provider.GetRequiredService()); - }); - - builder.Services.TryAddEnumerable( - ServiceDescriptor.Singleton, - OAuthValidationInitializer>()); - // Register the OpenIddict validation handler in the authentication options, // so it can be discovered by the default authentication handler provider. builder.Services.Configure(options => diff --git a/src/OpenIddict.Validation/OpenIddictValidationOptions.cs b/src/OpenIddict.Validation/OpenIddictValidationOptions.cs index e520419c..3409cd77 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationOptions.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationOptions.cs @@ -4,18 +4,12 @@ * the license and the contributors participating to this project. */ -using System; using AspNet.Security.OAuth.Validation; namespace OpenIddict.Validation { public class OpenIddictValidationOptions : OAuthValidationOptions { - /// - /// Gets or sets the type corresponding to the Token entity. - /// - public Type TokenType { get; set; } - /// /// Gets or sets a boolean indicating whether reference tokens are used. /// diff --git a/src/OpenIddict/OpenIddict.csproj b/src/OpenIddict/OpenIddict.csproj index 996c49fb..19b1a3f6 100644 --- a/src/OpenIddict/OpenIddict.csproj +++ b/src/OpenIddict/OpenIddict.csproj @@ -13,6 +13,7 @@ +