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 42180ddf..ea3404f5 100644 --- a/src/OpenIddict.Abstractions/OpenIddict.Abstractions.csproj +++ b/src/OpenIddict.Abstractions/OpenIddict.Abstractions.csproj @@ -3,7 +3,7 @@ - netstandard1.0 + net451;netstandard1.3 @@ -17,7 +17,12 @@ + + + + + diff --git a/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs b/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs index 9d3a3c8e..16e0d78e 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. @@ -1360,5 +1358,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 02c44c61..8428d708 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 29accfec..f0d2817d 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 b7897064..58a68602 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 8adc43d6..231ce97f 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..5f216b2b 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>().Value; + 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>().Value; + 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>().Value; + 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>().Value; + 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 8a330466..db8cbf6b 100644 --- a/src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs +++ b/src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.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.EntityFramework/Stores/OpenIddictTokenStore.cs b/src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs index d1a141e3..df2fce99 100644 --- a/src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs +++ b/src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs @@ -303,7 +303,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 74365a4d..be6df87e 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs +++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs @@ -413,7 +413,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 a2a2c41a..cbcefcfe 100644 --- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs +++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs @@ -286,7 +286,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/OpenIddictServerProvider.Authentication.cs b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Authentication.cs index d7e89185..b433b9a9 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Authentication.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Authentication.cs @@ -21,18 +21,16 @@ using Newtonsoft.Json; using Newtonsoft.Json.Bson; 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 { public override async Task ExtractAuthorizationRequest([NotNull] ExtractAuthorizationRequestContext context) { var options = (OpenIddictServerOptions) context.Options; - var logger = context.HttpContext.RequestServices.GetRequiredService>>(); + var logger = context.HttpContext.RequestServices.GetRequiredService>(); // Reject requests using the unsupported request parameter. if (!string.IsNullOrEmpty(context.Request.Request)) @@ -115,9 +113,9 @@ namespace OpenIddict.Server { var options = (OpenIddictServerOptions) context.Options; - var applications = context.HttpContext.RequestServices.GetRequiredService>(); - var logger = context.HttpContext.RequestServices.GetRequiredService>>(); - var scopes = context.HttpContext.RequestServices.GetRequiredService>(); + var logger = context.HttpContext.RequestServices.GetRequiredService>(); + var applicationManager = context.HttpContext.RequestServices.GetRequiredService(); + var scopeManager = context.HttpContext.RequestServices.GetRequiredService(); // Note: the OpenID Connect server middleware supports authorization code, implicit, hybrid, // none and custom flows but OpenIddict uses a stricter policy rejecting none and custum flows. @@ -188,7 +186,7 @@ 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); @@ -278,7 +276,7 @@ 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 " + @@ -299,7 +297,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( @@ -310,7 +308,7 @@ 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); @@ -323,7 +321,7 @@ 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}' " + @@ -337,7 +335,7 @@ 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}' " + @@ -352,15 +350,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); 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; } @@ -368,7 +366,7 @@ 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); @@ -382,7 +380,7 @@ 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); @@ -404,7 +402,7 @@ 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); diff --git a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Discovery.cs b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Discovery.cs index bc1d943f..c9acb6e2 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Discovery.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Discovery.cs @@ -14,8 +14,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 HandleConfigurationRequest([NotNull] HandleConfigurationRequestContext context) { diff --git a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Exchange.cs b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Exchange.cs index b8a87b68..b662b374 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Exchange.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Exchange.cs @@ -14,20 +14,18 @@ using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; 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 { public override async Task ValidateTokenRequest([NotNull] ValidateTokenRequestContext context) { var options = (OpenIddictServerOptions) context.Options; - var applications = context.HttpContext.RequestServices.GetRequiredService>(); - var logger = context.HttpContext.RequestServices.GetRequiredService>>(); - var scopes = context.HttpContext.RequestServices.GetRequiredService>(); + var logger = context.HttpContext.RequestServices.GetRequiredService>(); + var applicationManager = context.HttpContext.RequestServices.GetRequiredService(); + var scopeManager = context.HttpContext.RequestServices.GetRequiredService(); // Reject token requests that don't specify a supported grant type. if (!options.GrantTypes.Contains(context.Request.GrantType)) @@ -86,7 +84,7 @@ 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); @@ -142,7 +140,7 @@ 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 " + @@ -160,7 +158,7 @@ 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); @@ -173,7 +171,7 @@ 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 " + @@ -186,7 +184,7 @@ 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()) @@ -238,7 +236,7 @@ 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); @@ -260,7 +258,7 @@ 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}' " + @@ -281,8 +279,8 @@ namespace OpenIddict.Server { var options = (OpenIddictServerOptions) context.Options; - var logger = context.HttpContext.RequestServices.GetRequiredService>>(); - var tokens = context.HttpContext.RequestServices.GetRequiredService>(); + var logger = context.HttpContext.RequestServices.GetRequiredService>(); + var tokenManager = context.HttpContext.RequestServices.GetRequiredService(); if (context.Ticket != null) { @@ -307,13 +305,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 @@ -335,7 +333,7 @@ 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); diff --git a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Helpers.cs b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Helpers.cs index 44fa02f8..662ede6a 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Helpers.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Helpers.cs @@ -21,20 +21,18 @@ 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] HttpContext context, [NotNull] OpenIdConnectRequest request) { - var applications = context.RequestServices.GetRequiredService>(); - var authorizations = context.RequestServices.GetRequiredService>(); - var logger = context.RequestServices.GetRequiredService>>(); + var logger = context.RequestServices.GetRequiredService>(); + var applicationManager = context.RequestServices.GetRequiredService(); + var authorizationManager = context.RequestServices.GetRequiredService(); var descriptor = new OpenIddictAuthorizationDescriptor { @@ -57,16 +55,16 @@ 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)) { @@ -101,9 +99,9 @@ namespace OpenIddict.Server type == OpenIdConnectConstants.TokenUsages.RefreshToken, "Only authorization codes, access and refresh tokens should be created using this method."); - var applications = context.RequestServices.GetRequiredService>(); - var logger = context.RequestServices.GetRequiredService>>(); - var tokens = context.RequestServices.GetRequiredService>(); + var logger = context.RequestServices.GetRequiredService>(); + var applicationManager = context.RequestServices.GetRequiredService(); + var tokenManager = context.RequestServices.GetRequiredService(); // When sliding expiration is disabled, the expiration date of generated refresh tokens is fixed // and must exactly match the expiration date of the refresh token used in the token request. @@ -167,7 +165,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. @@ -180,25 +178,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."); @@ -231,8 +228,8 @@ namespace OpenIddict.Server [NotNull] OpenIdConnectRequest request, [NotNull] ISecureDataFormat format) { - var logger = context.RequestServices.GetRequiredService>>(); - var tokens = context.RequestServices.GetRequiredService>(); + var logger = context.RequestServices.GetRequiredService>(); + var tokenManager = context.RequestServices.GetRequiredService(); Debug.Assert(type == OpenIdConnectConstants.TokenUsages.AccessToken || type == OpenIdConnectConstants.TokenUsages.AuthorizationCode || @@ -241,7 +238,7 @@ namespace OpenIddict.Server string identifier; AuthenticationTicket ticket; - TToken token; + object token; if (options.UseReferenceTokens) { @@ -252,14 +249,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); @@ -273,7 +270,7 @@ namespace OpenIddict.Server 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. " + @@ -284,7 +281,7 @@ namespace OpenIddict.Server // 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. " + @@ -298,7 +295,7 @@ namespace OpenIddict.Server { 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)); + await tokenManager.GetIdAsync(token)); return null; } @@ -333,14 +330,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); @@ -364,12 +361,12 @@ 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}.", @@ -380,8 +377,8 @@ namespace OpenIddict.Server private async Task TryRevokeAuthorizationAsync([NotNull] AuthenticationTicket ticket, [NotNull] HttpContext context) { - var authorizations = context.RequestServices.GetRequiredService>(); - var logger = context.RequestServices.GetRequiredService>>(); + var logger = context.RequestServices.GetRequiredService>(); + var authorizationManager = context.RequestServices.GetRequiredService(); // Note: if the authorization identifier or the authorization itself // cannot be found, return true as the authorization doesn't need @@ -392,7 +389,7 @@ namespace OpenIddict.Server return true; } - var authorization = await authorizations.FindByIdAsync(identifier); + var authorization = await authorizationManager.FindByIdAsync(identifier); if (authorization == null) { return true; @@ -402,7 +399,7 @@ 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); @@ -418,19 +415,19 @@ namespace OpenIddict.Server } } - private async Task TryRevokeTokenAsync([NotNull] TToken token, [NotNull] HttpContext context) + private async Task TryRevokeTokenAsync([NotNull] object token, [NotNull] HttpContext context) { - var logger = context.RequestServices.GetRequiredService>>(); - var tokens = context.RequestServices.GetRequiredService>(); + var logger = context.RequestServices.GetRequiredService>(); + var tokenManager = context.RequestServices.GetRequiredService(); - 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); @@ -448,7 +445,7 @@ namespace OpenIddict.Server private async Task TryRevokeTokensAsync([NotNull] AuthenticationTicket ticket, [NotNull] HttpContext context) { - var tokens = context.RequestServices.GetRequiredService>(); + var tokenManager = context.RequestServices.GetRequiredService(); // Note: if the authorization identifier is null, return true as no tokens need to be revoked. var identifier = ticket.GetProperty(OpenIddictConstants.Properties.AuthorizationId); @@ -459,10 +456,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; } @@ -473,20 +470,19 @@ namespace OpenIddict.Server return result; } - private async Task TryRedeemTokenAsync([NotNull] TToken token, [NotNull] HttpContext context) + private async Task TryRedeemTokenAsync([NotNull] object token, [NotNull] HttpContext context) { - var logger = context.RequestServices.GetRequiredService>>(); - var tokens = context.RequestServices.GetRequiredService>(); - - var identifier = await tokens.GetIdAsync(token); + var logger = context.RequestServices.GetRequiredService>(); + var tokenManager = context.RequestServices.GetRequiredService(); + 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); @@ -503,11 +499,11 @@ namespace OpenIddict.Server } private async Task TryExtendTokenAsync( - [NotNull] TToken token, [NotNull] AuthenticationTicket ticket, + [NotNull] object token, [NotNull] AuthenticationTicket ticket, [NotNull] HttpContext context, [NotNull] OpenIddictServerOptions options) { - var logger = context.RequestServices.GetRequiredService>>(); - var tokens = context.RequestServices.GetRequiredService>(); + var logger = context.RequestServices.GetRequiredService>(); + var tokenManager = context.RequestServices.GetRequiredService(); var identifier = ticket.GetTokenId(); Debug.Assert(!string.IsNullOrEmpty(identifier), "The token identifier shouldn't be null or empty."); @@ -520,7 +516,7 @@ 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); @@ -541,7 +537,7 @@ namespace OpenIddict.Server [NotNull] HttpContext context, [NotNull] OpenIdConnectRequest request, [NotNull] AuthenticationProperties properties) { - var logger = context.RequestServices.GetRequiredService>>(); + var logger = context.RequestServices.GetRequiredService>(); Debug.Assert(properties != null, "The authentication properties shouldn't be null."); diff --git a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Introspection.cs b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Introspection.cs index 896f1618..9b8753b7 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Introspection.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Introspection.cs @@ -14,12 +14,10 @@ using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; 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 { public override Task ExtractIntrospectionRequest([NotNull] ExtractIntrospectionRequestContext context) { @@ -39,8 +37,8 @@ namespace OpenIddict.Server public override async Task ValidateIntrospectionRequest([NotNull] ValidateIntrospectionRequestContext context) { - var applications = context.HttpContext.RequestServices.GetRequiredService>(); - var logger = context.HttpContext.RequestServices.GetRequiredService>>(); + var logger = context.HttpContext.RequestServices.GetRequiredService>(); + var applicationManager = context.HttpContext.RequestServices.GetRequiredService(); // Note: the OpenID Connect server middleware supports unauthenticated introspection requests // but OpenIddict uses a stricter policy preventing unauthenticated/public applications @@ -56,7 +54,7 @@ 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 " + @@ -74,7 +72,7 @@ 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); @@ -87,7 +85,7 @@ 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); @@ -100,7 +98,7 @@ 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); @@ -119,8 +117,8 @@ namespace OpenIddict.Server { var options = (OpenIddictServerOptions) context.Options; - var logger = context.HttpContext.RequestServices.GetRequiredService>>(); - var tokens = context.HttpContext.RequestServices.GetRequiredService>(); + var logger = context.HttpContext.RequestServices.GetRequiredService>(); + var tokenManager = context.HttpContext.RequestServices.GetRequiredService(); Debug.Assert(context.Ticket != null, "The authentication ticket shouldn't be null."); Debug.Assert(!string.IsNullOrEmpty(context.Request.ClientId), "The client_id parameter shouldn't be null."); @@ -170,10 +168,10 @@ 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); diff --git a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Revocation.cs b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Revocation.cs index aedfac50..02a39b86 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Revocation.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Revocation.cs @@ -14,19 +14,17 @@ using JetBrains.Annotations; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; 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 { public override async Task ValidateRevocationRequest([NotNull] ValidateRevocationRequestContext context) { var options = (OpenIddictServerOptions) context.Options; - var applications = context.HttpContext.RequestServices.GetRequiredService>(); - var logger = context.HttpContext.RequestServices.GetRequiredService>>(); + var logger = context.HttpContext.RequestServices.GetRequiredService>(); + var applicationManager = context.HttpContext.RequestServices.GetRequiredService(); Debug.Assert(!options.DisableTokenRevocation, "Token revocation support shouldn't be disabled at this stage."); @@ -82,7 +80,7 @@ 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 " + @@ -100,7 +98,7 @@ 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); @@ -113,7 +111,7 @@ 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)) { @@ -151,7 +149,7 @@ 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); @@ -170,8 +168,8 @@ namespace OpenIddict.Server { var options = (OpenIddictServerOptions) context.Options; - var logger = context.HttpContext.RequestServices.GetRequiredService>>(); - var tokens = context.HttpContext.RequestServices.GetRequiredService>(); + var logger = context.HttpContext.RequestServices.GetRequiredService>(); + var tokenManager = context.HttpContext.RequestServices.GetRequiredService(); Debug.Assert(context.Ticket != null, "The authentication ticket shouldn't be null."); @@ -205,10 +203,10 @@ 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); @@ -223,7 +221,7 @@ namespace OpenIddict.Server // will be returned to the client application. try { - await tokens.RevokeAsync(token); + await tokenManager.RevokeAsync(token); } catch (Exception exception) diff --git a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Serialization.cs b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Serialization.cs index 55b08392..d1bbcc58 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 160a4d85..55ca1f78 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Session.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Session.cs @@ -20,18 +20,16 @@ using Newtonsoft.Json; using Newtonsoft.Json.Bson; 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 { public override async Task ExtractLogoutRequest([NotNull] ExtractLogoutRequestContext context) { var options = (OpenIddictServerOptions) context.Options; - var logger = context.HttpContext.RequestServices.GetRequiredService>>(); + var logger = context.HttpContext.RequestServices.GetRequiredService>(); // If a request_id parameter can be found in the logout request, // restore the complete logout request from the distributed cache. @@ -86,8 +84,8 @@ namespace OpenIddict.Server public override async Task ValidateLogoutRequest([NotNull] ValidateLogoutRequestContext context) { - var applications = context.HttpContext.RequestServices.GetRequiredService>(); - var logger = context.HttpContext.RequestServices.GetRequiredService>>(); + var logger = context.HttpContext.RequestServices.GetRequiredService>(); + var applicationManager = context.HttpContext.RequestServices.GetRequiredService(); // If an optional post_logout_redirect_uri was provided, validate it. if (!string.IsNullOrEmpty(context.PostLogoutRedirectUri)) @@ -116,7 +114,7 @@ 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); diff --git a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Userinfo.cs b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.Userinfo.cs index 7a72921a..23348b99 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 9e264241..0f2c0f35 100644 --- a/src/OpenIddict.Server/Internal/OpenIddictServerProvider.cs +++ b/src/OpenIddict.Server/Internal/OpenIddictServerProvider.cs @@ -18,8 +18,7 @@ using OpenIddict.Abstractions; namespace OpenIddict.Server { [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 { public override Task ProcessChallengeResponse([NotNull] ProcessChallengeResponseContext context) { @@ -101,7 +100,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 34988f67..b8454913 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 366134fd..a676f425 100644 --- a/src/OpenIddict.Server/OpenIddictServerBuilder.cs +++ b/src/OpenIddict.Server/OpenIddictServerBuilder.cs @@ -12,14 +12,12 @@ 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.Builder; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http; using Microsoft.IdentityModel.Tokens; -using OpenIddict.Core; using OpenIddict.Server; namespace Microsoft.Extensions.DependencyInjection @@ -415,8 +413,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 7c5d01d9..0e5dcaf9 100644 --- a/src/OpenIddict.Server/OpenIddictServerExtensions.cs +++ b/src/OpenIddict.Server/OpenIddictServerExtensions.cs @@ -6,7 +6,6 @@ using System; using System.Linq; -using System.Text; using AspNet.Security.OpenIdConnect.Primitives; using AspNet.Security.OpenIdConnect.Server; using JetBrains.Annotations; @@ -16,7 +15,6 @@ using Microsoft.AspNetCore.DataProtection; using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; -using OpenIddict.Core; using OpenIddict.Server; namespace Microsoft.Extensions.DependencyInjection @@ -79,54 +77,9 @@ namespace Microsoft.Extensions.DependencyInjection throw new ArgumentNullException(nameof(app)); } - var configuration = app.ApplicationServices.GetRequiredService>().Value; - - // Resolve the OpenIddict options from the DI container. - var options = app.ApplicationServices.GetRequiredService>().Value; - if (options.ApplicationType == null) - { - options.ApplicationType = configuration.DefaultApplicationType; - } - - if (options.AuthorizationType == null) - { - options.AuthorizationType = configuration.DefaultAuthorizationType; - } - - if (options.ScopeType == null) - { - options.ScopeType = configuration.DefaultScopeType; - } - - if (options.TokenType == null) - { - options.TokenType = configuration.DefaultTokenType; - } - - 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()); - } - - // When no authorization provider has been registered in the options, - // create a new OpenIddictProvider instance using the specified entities. - if (options.Provider == null) - { - options.Provider = (OpenIdConnectServerProvider) Activator.CreateInstance( - typeof(OpenIddictServerProvider<,,,>).MakeGenericType( - /* TApplication: */ options.ApplicationType, - /* TAuthorization: */ options.AuthorizationType, - /* TScope: */ options.ScopeType, - /* TToken: */ options.TokenType)); - } - // When no distributed cache has been registered in the options, use the // global instance registered in the dependency injection container. + var options = app.ApplicationServices.GetRequiredService>().Value; if (options.Cache == null) { options.Cache = app.ApplicationServices.GetRequiredService(); diff --git a/src/OpenIddict.Server/OpenIddictServerOptions.cs b/src/OpenIddict.Server/OpenIddictServerOptions.cs index 27b984eb..2affbb71 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,19 +23,9 @@ namespace OpenIddict.Server /// public OpenIddictServerOptions() { - Provider = null; + Provider = new 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. @@ -100,16 +90,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 68b62aea..37cb1d82 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.Threading.Tasks; using AspNet.Security.OAuth.Validation; using Microsoft.AspNetCore.Authentication; @@ -15,18 +16,19 @@ using Microsoft.Extensions.Logging; 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 { } - - [EditorBrowsable(EditorBrowsableState.Never)] - public class OpenIddictValidationHandler : OpenIddictValidationHandler where TToken : class + public class OpenIddictValidationHandler : OAuthValidationHandler { protected override async Task HandleAuthenticateAsync() { + if (!Options.UseReferenceTokens) + { + return await base.HandleAuthenticateAsync(); + } + var context = new RetrieveTokenContext(Context, Options); await Options.Events.RetrieveToken(context); @@ -199,10 +201,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 @@ -283,5 +290,7 @@ namespace OpenIddict.Validation return AuthenticateResult.Success(notification.Ticket); } + + private new OpenIddictValidationOptions Options => (OpenIddictValidationOptions) base.Options; } } diff --git a/src/OpenIddict.Validation/Internal/OpenIddictValidationMiddleware.cs b/src/OpenIddict.Validation/Internal/OpenIddictValidationMiddleware.cs index 8f06da9f..b8cf5822 100644 --- a/src/OpenIddict.Validation/Internal/OpenIddictValidationMiddleware.cs +++ b/src/OpenIddict.Validation/Internal/OpenIddictValidationMiddleware.cs @@ -32,21 +32,4 @@ namespace OpenIddict.Validation protected override AuthenticationHandler CreateHandler() => new OpenIddictValidationHandler(); } - - [EditorBrowsable(EditorBrowsableState.Never)] - public class OpenIddictValidationMiddleware : OpenIddictValidationMiddleware where TToken : class - { - public OpenIddictValidationMiddleware( - [NotNull] RequestDelegate next, - [NotNull] IOptions options, - [NotNull] ILoggerFactory loggerFactory, - [NotNull] UrlEncoder encoder, - [NotNull] IDataProtectionProvider dataProtectionProvider) - : base(next, options, loggerFactory, encoder, dataProtectionProvider) - { - } - - protected override AuthenticationHandler CreateHandler() - => new OpenIddictValidationHandler(); - } } diff --git a/src/OpenIddict.Validation/OpenIddict.Validation.csproj b/src/OpenIddict.Validation/OpenIddict.Validation.csproj index fc006f24..ba95e9eb 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 e06f0185..fe64f6d5 100644 --- a/src/OpenIddict.Validation/OpenIddictValidationExtensions.cs +++ b/src/OpenIddict.Validation/OpenIddictValidationExtensions.cs @@ -5,14 +5,11 @@ */ using System; -using System.Text; -using AspNet.Security.OAuth.Validation; using JetBrains.Annotations; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.DataProtection; using Microsoft.Extensions.Options; -using OpenIddict.Core; using OpenIddict.Validation; namespace Microsoft.Extensions.DependencyInjection @@ -75,14 +72,7 @@ namespace Microsoft.Extensions.DependencyInjection throw new ArgumentNullException(nameof(app)); } - var configuration = app.ApplicationServices.GetRequiredService>().Value; - var options = app.ApplicationServices.GetRequiredService>().Value; - if (options.Events == null) - { - options.Events = new OAuthValidationEvents(); - } - if (options.DataProtectionProvider == null) { options.DataProtectionProvider = app.ApplicationServices.GetDataProtectionProvider(); @@ -98,26 +88,6 @@ namespace Microsoft.Extensions.DependencyInjection options.AccessTokenFormat = new TicketDataFormat(protector); } - if (options.TokenType == null) - { - options.TokenType = configuration.DefaultTokenType; - } - - 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()); - } - - return app.UseMiddleware(typeof(OpenIddictValidationMiddleware<>) - .MakeGenericType(options.TokenType), new OptionsWrapper(options)); - } - return app.UseMiddleware(new OptionsWrapper(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 c0d428eb..e8a7122f 100644 --- a/src/OpenIddict/OpenIddict.csproj +++ b/src/OpenIddict/OpenIddict.csproj @@ -13,6 +13,7 @@ +