Browse Source

Backport the manager interfaces to OpenIddict 1.x

pull/670/head
Kévin Chalet 9 years ago
parent
commit
5d21c1d210
  1. 2
      src/OpenIddict.Abstractions/Descriptors/OpenIddictApplicationDescriptor.cs
  2. 2
      src/OpenIddict.Abstractions/Descriptors/OpenIddictAuthorizationDescriptor.cs
  3. 2
      src/OpenIddict.Abstractions/Descriptors/OpenIddictScopeDescriptor.cs
  4. 2
      src/OpenIddict.Abstractions/Descriptors/OpenIddictTokenDescriptor.cs
  5. 421
      src/OpenIddict.Abstractions/Managers/IOpenIddictApplicationManager.cs
  6. 419
      src/OpenIddict.Abstractions/Managers/IOpenIddictAuthorizationManager.cs
  7. 290
      src/OpenIddict.Abstractions/Managers/IOpenIddictScopeManager.cs
  8. 452
      src/OpenIddict.Abstractions/Managers/IOpenIddictTokenManager.cs
  9. 7
      src/OpenIddict.Abstractions/OpenIddict.Abstractions.csproj
  10. 114
      src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs
  11. 114
      src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
  12. 78
      src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs
  13. 126
      src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
  14. 5
      src/OpenIddict.Core/OpenIddict.Core.csproj
  15. 66
      src/OpenIddict.Core/OpenIddictCoreExtensions.cs
  16. 12
      src/OpenIddict.Core/OpenIddictCoreOptions.cs
  17. 2
      src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs
  18. 2
      src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs
  19. 2
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs
  20. 2
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs
  21. 36
      src/OpenIddict.Server/Internal/OpenIddictServerProvider.Authentication.cs
  22. 3
      src/OpenIddict.Server/Internal/OpenIddictServerProvider.Discovery.cs
  23. 34
      src/OpenIddict.Server/Internal/OpenIddictServerProvider.Exchange.cs
  24. 106
      src/OpenIddict.Server/Internal/OpenIddictServerProvider.Helpers.cs
  25. 24
      src/OpenIddict.Server/Internal/OpenIddictServerProvider.Introspection.cs
  26. 26
      src/OpenIddict.Server/Internal/OpenIddictServerProvider.Revocation.cs
  27. 3
      src/OpenIddict.Server/Internal/OpenIddictServerProvider.Serialization.cs
  28. 12
      src/OpenIddict.Server/Internal/OpenIddictServerProvider.Session.cs
  29. 3
      src/OpenIddict.Server/Internal/OpenIddictServerProvider.Userinfo.cs
  30. 5
      src/OpenIddict.Server/Internal/OpenIddictServerProvider.cs
  31. 3
      src/OpenIddict.Server/OpenIddict.Server.csproj
  32. 5
      src/OpenIddict.Server/OpenIddictServerBuilder.cs
  33. 49
      src/OpenIddict.Server/OpenIddictServerExtensions.cs
  34. 24
      src/OpenIddict.Server/OpenIddictServerOptions.cs
  35. 23
      src/OpenIddict.Validation/Internal/OpenIddictValidationHandler.cs
  36. 17
      src/OpenIddict.Validation/Internal/OpenIddictValidationMiddleware.cs
  37. 2
      src/OpenIddict.Validation/OpenIddict.Validation.csproj
  38. 30
      src/OpenIddict.Validation/OpenIddictValidationExtensions.cs
  39. 6
      src/OpenIddict.Validation/OpenIddictValidationOptions.cs
  40. 1
      src/OpenIddict/OpenIddict.csproj

2
src/OpenIddict.Core/Descriptors/OpenIddictApplicationDescriptor.cs → src/OpenIddict.Abstractions/Descriptors/OpenIddictApplicationDescriptor.cs

@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
namespace OpenIddict.Core
namespace OpenIddict.Abstractions
{
/// <summary>
/// Represents an OpenIddict application descriptor.

2
src/OpenIddict.Core/Descriptors/OpenIddictAuthorizationDescriptor.cs → src/OpenIddict.Abstractions/Descriptors/OpenIddictAuthorizationDescriptor.cs

@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Security.Claims;
namespace OpenIddict.Core
namespace OpenIddict.Abstractions
{
/// <summary>
/// Represents an OpenIddict authorization descriptor.

2
src/OpenIddict.Core/Descriptors/OpenIddictScopeDescriptor.cs → src/OpenIddict.Abstractions/Descriptors/OpenIddictScopeDescriptor.cs

@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
namespace OpenIddict.Core
namespace OpenIddict.Abstractions
{
/// <summary>
/// Represents an OpenIddict scope descriptor.

2
src/OpenIddict.Core/Descriptors/OpenIddictTokenDescriptor.cs → src/OpenIddict.Abstractions/Descriptors/OpenIddictTokenDescriptor.cs

@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Security.Claims;
namespace OpenIddict.Core
namespace OpenIddict.Abstractions
{
/// <summary>
/// Represents an OpenIddict token descriptor.

421
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
{
/// <summary>
/// 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.
/// </summary>
public interface IOpenIddictApplicationManager
{
/// <summary>
/// Determines the number of applications that exist in the database.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the number of applications in the database.
/// </returns>
Task<long> CountAsync(CancellationToken cancellationToken = default);
/// <summary>
/// Determines the number of applications that match the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the number of applications that match the specified query.
/// </returns>
Task<long> CountAsync<TResult>([NotNull] Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken = default);
/// <summary>
/// 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.
/// </summary>
/// <param name="descriptor">The application descriptor.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the unique identifier associated with the application.
/// </returns>
Task<object> CreateAsync([NotNull] OpenIddictApplicationDescriptor descriptor, CancellationToken cancellationToken = default);
/// <summary>
/// Creates a new application.
/// </summary>
/// <param name="application">The application to create.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task CreateAsync([NotNull] object application, CancellationToken cancellationToken = default);
/// <summary>
/// Creates a new application.
/// Note: the default implementation automatically hashes the client
/// secret before storing it in the database, for security reasons.
/// </summary>
/// <param name="application">The application to create.</param>
/// <param name="secret">The client secret associated with the application, if applicable.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task CreateAsync([NotNull] object application, [CanBeNull] string secret, CancellationToken cancellationToken = default);
/// <summary>
/// Removes an existing application.
/// </summary>
/// <param name="application">The application to delete.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task DeleteAsync([NotNull] object application, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves an application using its client identifier.
/// </summary>
/// <param name="identifier">The client identifier associated with the application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the client application corresponding to the identifier.
/// </returns>
Task<object> FindByClientIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves an application using its unique identifier.
/// </summary>
/// <param name="identifier">The unique identifier associated with the application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the client application corresponding to the identifier.
/// </returns>
Task<object> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves all the applications associated with the specified post_logout_redirect_uri.
/// </summary>
/// <param name="address">The post_logout_redirect_uri associated with the applications.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation, whose result
/// returns the client applications corresponding to the specified post_logout_redirect_uri.
/// </returns>
Task<ImmutableArray<object>> FindByPostLogoutRedirectUriAsync([NotNull] string address, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves all the applications associated with the specified redirect_uri.
/// </summary>
/// <param name="address">The redirect_uri associated with the applications.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation, whose result
/// returns the client applications corresponding to the specified redirect_uri.
/// </returns>
Task<ImmutableArray<object>> FindByRedirectUriAsync([NotNull] string address, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns the first element.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the first element returned when executing the query.
/// </returns>
Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns the first element.
/// </summary>
/// <typeparam name="TState">The state type.</typeparam>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="state">The optional state.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the first element returned when executing the query.
/// </returns>
Task<TResult> GetAsync<TState, TResult>([NotNull] Func<IQueryable<object>, TState, IQueryable<TResult>> query, [CanBeNull] TState state, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the client identifier associated with an application.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the client identifier associated with the application.
/// </returns>
ValueTask<string> GetClientIdAsync([NotNull] object application, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the client type associated with an application.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the client type of the application (by default, "public").
/// </returns>
ValueTask<string> GetClientTypeAsync([NotNull] object application, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the consent type associated with an application.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the consent type of the application (by default, "explicit").
/// </returns>
ValueTask<string> GetConsentTypeAsync([NotNull] object application, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the display name associated with an application.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the display name associated with the application.
/// </returns>
ValueTask<string> GetDisplayNameAsync([NotNull] object application, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the unique identifier associated with an application.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the unique identifier associated with the application.
/// </returns>
ValueTask<string> GetIdAsync([NotNull] object application, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the permissions associated with an application.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns all the permissions associated with the application.
/// </returns>
ValueTask<ImmutableArray<string>> GetPermissionsAsync([NotNull] object application, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the logout callback addresses associated with an application.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns all the post_logout_redirect_uri associated with the application.
/// </returns>
ValueTask<ImmutableArray<string>> GetPostLogoutRedirectUrisAsync([NotNull] object application, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the callback addresses associated with an application.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns all the redirect_uri associated with the application.
/// </returns>
ValueTask<ImmutableArray<string>> GetRedirectUrisAsync([NotNull] object application, CancellationToken cancellationToken = default);
/// <summary>
/// Determines whether the specified permission has been granted to the application.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="permission">The permission.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><c>true</c> if the application has been granted the specified permission, <c>false</c> otherwise.</returns>
Task<bool> HasPermissionAsync([NotNull] object application, [NotNull] string permission, CancellationToken cancellationToken = default);
/// <summary>
/// Determines whether an application is a confidential client.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><c>true</c> if the application is a confidential client, <c>false</c> otherwise.</returns>
Task<bool> IsConfidentialAsync([NotNull] object application, CancellationToken cancellationToken = default);
/// <summary>
/// Determines whether an application is a hybrid client.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><c>true</c> if the application is a hybrid client, <c>false</c> otherwise.</returns>
Task<bool> IsHybridAsync([NotNull] object application, CancellationToken cancellationToken = default);
/// <summary>
/// Determines whether an application is a public client.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><c>true</c> if the application is a public client, <c>false</c> otherwise.</returns>
Task<bool> IsPublicAsync([NotNull] object application, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns all the corresponding elements.
/// </summary>
/// <param name="count">The number of results to return.</param>
/// <param name="offset">The number of results to skip.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
Task<ImmutableArray<object>> ListAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns all the corresponding elements.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
Task<ImmutableArray<TResult>> ListAsync<TResult>([NotNull] Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns all the corresponding elements.
/// </summary>
/// <typeparam name="TState">The state type.</typeparam>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="state">The optional state.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
Task<ImmutableArray<TResult>> ListAsync<TState, TResult>([NotNull] Func<IQueryable<object>, TState, IQueryable<TResult>> query, [CanBeNull] TState state, CancellationToken cancellationToken = default);
/// <summary>
/// Populates the specified descriptor using the properties exposed by the application.
/// </summary>
/// <param name="descriptor">The descriptor.</param>
/// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task PopulateAsync([NotNull] OpenIddictApplicationDescriptor descriptor, [NotNull] object application, CancellationToken cancellationToken = default);
/// <summary>
/// Populates the application using the specified descriptor.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="descriptor">The descriptor.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task PopulateAsync([NotNull] object application, [NotNull] OpenIddictApplicationDescriptor descriptor, CancellationToken cancellationToken = default);
/// <summary>
/// Updates an existing application.
/// </summary>
/// <param name="application">The application to update.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task UpdateAsync([NotNull] object application, CancellationToken cancellationToken = default);
/// <summary>
/// Updates an existing application.
/// </summary>
/// <param name="application">The application to update.</param>
/// <param name="descriptor">The descriptor used to update the application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task UpdateAsync([NotNull] object application, [NotNull] OpenIddictApplicationDescriptor descriptor, CancellationToken cancellationToken = default);
/// <summary>
/// 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.
/// </summary>
/// <param name="application">The application to update.</param>
/// <param name="secret">The client secret associated with the application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task UpdateAsync([NotNull] object application, [CanBeNull] string secret, CancellationToken cancellationToken = default);
/// <summary>
/// Validates the application to ensure it's in a consistent state.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the validation error encountered when validating the application.
/// </returns>
Task<ImmutableArray<ValidationResult>> ValidateAsync([NotNull] object application, CancellationToken cancellationToken = default);
/// <summary>
/// Validates the client_secret associated with an application.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="secret">The secret that should be compared to the client_secret stored in the database.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns a boolean indicating whether the client secret was valid.
/// </returns>
Task<bool> ValidateClientSecretAsync([NotNull] object application, string secret, CancellationToken cancellationToken = default);
/// <summary>
/// Validates the specified post_logout_redirect_uri.
/// </summary>
/// <param name="address">The address that should be compared to the post_logout_redirect_uri stored in the database.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation, whose result
/// returns a boolean indicating whether the post_logout_redirect_uri was valid.
/// </returns>
Task<bool> ValidatePostLogoutRedirectUriAsync([NotNull] string address, CancellationToken cancellationToken = default);
/// <summary>
/// Validates the redirect_uri to ensure it's associated with an application.
/// </summary>
/// <param name="application">The application.</param>
/// <param name="address">The address that should be compared to one of the redirect_uri stored in the database.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns a boolean indicating whether the redirect_uri was valid.
/// </returns>
Task<bool> ValidateRedirectUriAsync([NotNull] object application, [NotNull] string address, CancellationToken cancellationToken = default);
}
}

419
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
{
/// <summary>
/// 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.
/// </summary>
public interface IOpenIddictAuthorizationManager
{
/// <summary>
/// Determines the number of authorizations that exist in the database.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the number of authorizations in the database.
/// </returns>
Task<long> CountAsync(CancellationToken cancellationToken = default);
/// <summary>
/// Determines the number of authorizations that match the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the number of authorizations that match the specified query.
/// </returns>
Task<long> CountAsync<TResult>([NotNull] Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken = default);
/// <summary>
/// Creates a new permanent authorization based on the specified parameters.
/// </summary>
/// <param name="principal">The principal associated with the authorization.</param>
/// <param name="subject">The subject associated with the authorization.</param>
/// <param name="client">The client associated with the authorization.</param>
/// <param name="type">The authorization type.</param>
/// <param name="scopes">The minimal scopes associated with the authorization.</param>
/// <param name="properties">The authentication properties associated with the authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation, whose result returns the authorization.
/// </returns>
Task<object> CreateAsync([NotNull] ClaimsPrincipal principal, [NotNull] string subject, [NotNull] string client, [NotNull] string type, ImmutableArray<string> scopes, [CanBeNull] ImmutableDictionary<string, string> properties, CancellationToken cancellationToken = default);
/// <summary>
/// Creates a new authorization based on the specified descriptor.
/// </summary>
/// <param name="descriptor">The authorization descriptor.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation, whose result returns the authorization.
/// </returns>
Task<object> CreateAsync([NotNull] OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken = default);
/// <summary>
/// Creates a new authorization.
/// </summary>
/// <param name="authorization">The application to create.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task CreateAsync([NotNull] object authorization, CancellationToken cancellationToken = default);
/// <summary>
/// Removes an existing authorization.
/// </summary>
/// <param name="authorization">The authorization to delete.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task DeleteAsync([NotNull] object authorization, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the authorizations corresponding to the specified
/// subject and associated with the application identifier.
/// </summary>
/// <param name="subject">The subject associated with the authorization.</param>
/// <param name="client">The client associated with the authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the authorizations corresponding to the subject/client.
/// </returns>
Task<ImmutableArray<object>> FindAsync([NotNull] string subject, [NotNull] string client, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the authorizations matching the specified parameters.
/// </summary>
/// <param name="subject">The subject associated with the authorization.</param>
/// <param name="client">The client associated with the authorization.</param>
/// <param name="status">The authorization status.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the authorizations corresponding to the criteria.
/// </returns>
Task<ImmutableArray<object>> FindAsync([NotNull] string subject, [NotNull] string client, [NotNull] string status, CancellationToken cancellationToken);
/// <summary>
/// Retrieves the authorizations matching the specified parameters.
/// </summary>
/// <param name="subject">The subject associated with the authorization.</param>
/// <param name="client">The client associated with the authorization.</param>
/// <param name="status">The authorization status.</param>
/// <param name="type">The authorization type.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the authorizations corresponding to the criteria.
/// </returns>
Task<ImmutableArray<object>> FindAsync([NotNull] string subject, [NotNull] string client, [NotNull] string status, [NotNull] string type, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the authorizations matching the specified parameters.
/// </summary>
/// <param name="subject">The subject associated with the authorization.</param>
/// <param name="client">The client associated with the authorization.</param>
/// <param name="status">The authorization status.</param>
/// <param name="type">The authorization type.</param>
/// <param name="scopes">The minimal scopes associated with the authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the authorizations corresponding to the criteria.
/// </returns>
Task<ImmutableArray<object>> FindAsync([NotNull] string subject, [NotNull] string client, [NotNull] string status, [NotNull] string type, ImmutableArray<string> scopes, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves an authorization using its unique identifier.
/// </summary>
/// <param name="identifier">The unique identifier associated with the authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the authorization corresponding to the identifier.
/// </returns>
Task<object> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves all the authorizations corresponding to the specified subject.
/// </summary>
/// <param name="subject">The subject associated with the authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the authorizations corresponding to the specified subject.
/// </returns>
Task<ImmutableArray<object>> FindBySubjectAsync([NotNull] string subject, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the optional application identifier associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the application identifier associated with the authorization.
/// </returns>
ValueTask<string> GetApplicationIdAsync([NotNull] object authorization, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns the first element.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the first element returned when executing the query.
/// </returns>
Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns the first element.
/// </summary>
/// <typeparam name="TState">The state type.</typeparam>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="state">The optional state.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the first element returned when executing the query.
/// </returns>
Task<TResult> GetAsync<TState, TResult>([NotNull] Func<IQueryable<object>, TState, IQueryable<TResult>> query, [CanBeNull] TState state, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the unique identifier associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the unique identifier associated with the authorization.
/// </returns>
ValueTask<string> GetIdAsync([NotNull] object authorization, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the scopes associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the scopes associated with the specified authorization.
/// </returns>
ValueTask<ImmutableArray<string>> GetScopesAsync([NotNull] object authorization, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the status associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the status associated with the specified authorization.
/// </returns>
ValueTask<string> GetStatusAsync([NotNull] object authorization, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the subject associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the subject associated with the specified authorization.
/// </returns>
ValueTask<string> GetSubjectAsync([NotNull] object authorization, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the type associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the type associated with the specified authorization.
/// </returns>
ValueTask<string> GetTypeAsync([NotNull] object authorization, CancellationToken cancellationToken = default);
/// <summary>
/// Determines whether the specified scopes are included in the authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="scopes">The scopes.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><c>true</c> if the scopes are included in the authorization, <c>false</c> otherwise.</returns>
Task<bool> HasScopesAsync([NotNull] object authorization, ImmutableArray<string> scopes, CancellationToken cancellationToken = default);
/// <summary>
/// Determines whether a given authorization is ad hoc.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><c>true</c> if the authorization is ad hoc, <c>false</c> otherwise.</returns>
Task<bool> IsAdHocAsync([NotNull] object authorization, CancellationToken cancellationToken = default);
/// <summary>
/// Determines whether a given authorization is permanent.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><c>true</c> if the authorization is permanent, <c>false</c> otherwise.</returns>
Task<bool> IsPermanentAsync([NotNull] object authorization, CancellationToken cancellationToken = default);
/// <summary>
/// Determines whether a given authorization has been revoked.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><c>true</c> if the authorization has been revoked, <c>false</c> otherwise.</returns>
Task<bool> IsRevokedAsync([NotNull] object authorization, CancellationToken cancellationToken = default);
/// <summary>
/// Determines whether a given authorization is valid.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><c>true</c> if the authorization is valid, <c>false</c> otherwise.</returns>
Task<bool> IsValidAsync([NotNull] object authorization, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns all the corresponding elements.
/// </summary>
/// <param name="count">The number of results to return.</param>
/// <param name="offset">The number of results to skip.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
Task<ImmutableArray<object>> ListAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns all the corresponding elements.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
Task<ImmutableArray<TResult>> ListAsync<TResult>([NotNull] Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns all the corresponding elements.
/// </summary>
/// <typeparam name="TState">The state type.</typeparam>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="state">The optional state.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
Task<ImmutableArray<TResult>> ListAsync<TState, TResult>([NotNull] Func<IQueryable<object>, TState, IQueryable<TResult>> query, [CanBeNull] TState state, CancellationToken cancellationToken = default);
/// <summary>
/// Populates the specified descriptor using the properties exposed by the authorization.
/// </summary>
/// <param name="descriptor">The descriptor.</param>
/// <param name="authorization">The authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task PopulateAsync([NotNull] OpenIddictAuthorizationDescriptor descriptor, [NotNull] object authorization, CancellationToken cancellationToken = default);
/// <summary>
/// Populates the authorization using the specified descriptor.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="descriptor">The descriptor.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task PopulateAsync([NotNull] object authorization, [NotNull] OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken = default);
/// <summary>
/// Removes the ad-hoc authorizations that are marked as invalid or have no valid token attached.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task PruneAsync(CancellationToken cancellationToken = default);
/// <summary>
/// Revokes an authorization.
/// </summary>
/// <param name="authorization">The authorization to revoke.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
Task RevokeAsync([NotNull] object authorization, CancellationToken cancellationToken = default);
/// <summary>
/// Sets the application identifier associated with an authorization.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="identifier">The unique identifier associated with the client application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task SetApplicationIdAsync([NotNull] object authorization, [CanBeNull] string identifier, CancellationToken cancellationToken = default);
/// <summary>
/// Updates an existing authorization.
/// </summary>
/// <param name="authorization">The authorization to update.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task UpdateAsync([NotNull] object authorization, CancellationToken cancellationToken = default);
/// <summary>
/// Updates an existing authorization.
/// </summary>
/// <param name="authorization">The authorization to update.</param>
/// <param name="descriptor">The descriptor used to update the authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task UpdateAsync([NotNull] object authorization, [NotNull] OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken = default);
/// <summary>
/// Validates the authorization to ensure it's in a consistent state.
/// </summary>
/// <param name="authorization">The authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the validation error encountered when validating the authorization.
/// </returns>
Task<ImmutableArray<ValidationResult>> ValidateAsync([NotNull] object authorization, CancellationToken cancellationToken = default);
}
}

290
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
{
/// <summary>
/// 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.
/// </summary>
public interface IOpenIddictScopeManager
{
/// <summary>
/// Determines the number of scopes that exist in the database.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the number of scopes in the database.
/// </returns>
Task<long> CountAsync(CancellationToken cancellationToken = default);
/// <summary>
/// Determines the number of scopes that match the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the number of scopes that match the specified query.
/// </returns>
Task<long> CountAsync<TResult>([NotNull] Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken = default);
/// <summary>
/// Creates a new scope based on the specified descriptor.
/// </summary>
/// <param name="descriptor">The scope descriptor.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation, whose result returns the scope.
/// </returns>
Task<object> CreateAsync([NotNull] OpenIddictScopeDescriptor descriptor, CancellationToken cancellationToken = default);
/// <summary>
/// Creates a new scope.
/// </summary>
/// <param name="scope">The scope to create.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task CreateAsync([NotNull] object scope, CancellationToken cancellationToken = default);
/// <summary>
/// Removes an existing scope.
/// </summary>
/// <param name="scope">The scope to delete.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task DeleteAsync([NotNull] object scope, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves a scope using its unique identifier.
/// </summary>
/// <param name="identifier">The unique identifier associated with the scope.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the scope corresponding to the identifier.
/// </returns>
Task<object> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves a scope using its name.
/// </summary>
/// <param name="name">The name associated with the scope.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the scope corresponding to the specified name.
/// </returns>
Task<object> FindByNameAsync([NotNull] string name, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves a list of scopes using their name.
/// </summary>
/// <param name="names">The names associated with the scopes.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the scopes corresponding to the specified names.
/// </returns>
Task<ImmutableArray<object>> FindByNamesAsync(ImmutableArray<string> names, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns the first element.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the first element returned when executing the query.
/// </returns>
Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns the first element.
/// </summary>
/// <typeparam name="TState">The state type.</typeparam>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="state">The optional state.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the first element returned when executing the query.
/// </returns>
Task<TResult> GetAsync<TState, TResult>([NotNull] Func<IQueryable<object>, TState, IQueryable<TResult>> query, [CanBeNull] TState state, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the description associated with a scope.
/// </summary>
/// <param name="scope">The scope.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the description associated with the specified scope.
/// </returns>
ValueTask<string> GetDescriptionAsync([NotNull] object scope, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the display name associated with a scope.
/// </summary>
/// <param name="scope">The scope.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the display name associated with the scope.
/// </returns>
ValueTask<string> GetDisplayNameAsync([NotNull] object scope, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the unique identifier associated with a scope.
/// </summary>
/// <param name="scope">The scope.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the unique identifier associated with the scope.
/// </returns>
ValueTask<string> GetIdAsync([NotNull] object scope, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the name associated with a scope.
/// </summary>
/// <param name="scope">The scope.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the name associated with the specified scope.
/// </returns>
ValueTask<string> GetNameAsync([NotNull] object scope, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the resources associated with a scope.
/// </summary>
/// <param name="scope">The scope.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns all the resources associated with the scope.
/// </returns>
ValueTask<ImmutableArray<string>> GetResourcesAsync([NotNull] object scope, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns all the corresponding elements.
/// </summary>
/// <param name="count">The number of results to return.</param>
/// <param name="offset">The number of results to skip.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
Task<ImmutableArray<object>> ListAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns all the corresponding elements.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
Task<ImmutableArray<TResult>> ListAsync<TResult>([NotNull] Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns all the corresponding elements.
/// </summary>
/// <typeparam name="TState">The state type.</typeparam>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="state">The optional state.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
Task<ImmutableArray<TResult>> ListAsync<TState, TResult>([NotNull] Func<IQueryable<object>, TState, IQueryable<TResult>> query, [CanBeNull] TState state, CancellationToken cancellationToken = default);
/// <summary>
/// Lists all the resources associated with the specified scopes.
/// </summary>
/// <param name="scopes">The scopes.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns all the resources associated with the specified scopes.
/// </returns>
Task<ImmutableArray<string>> ListResourcesAsync(ImmutableArray<string> scopes, CancellationToken cancellationToken = default);
/// <summary>
/// Populates the specified descriptor using the properties exposed by the scope.
/// </summary>
/// <param name="descriptor">The descriptor.</param>
/// <param name="scope">The scope.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task PopulateAsync([NotNull] OpenIddictScopeDescriptor descriptor, [NotNull] object scope, CancellationToken cancellationToken = default);
/// <summary>
/// Populates the scope using the specified descriptor.
/// </summary>
/// <param name="scope">The scope.</param>
/// <param name="descriptor">The descriptor.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task PopulateAsync([NotNull] object scope, [NotNull] OpenIddictScopeDescriptor descriptor, CancellationToken cancellationToken = default);
/// <summary>
/// Updates an existing scope.
/// </summary>
/// <param name="scope">The scope to update.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task UpdateAsync([NotNull] object scope, CancellationToken cancellationToken = default);
/// <summary>
/// Updates an existing scope.
/// </summary>
/// <param name="scope">The scope to update.</param>
/// <param name="descriptor">The descriptor used to update the scope.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task UpdateAsync([NotNull] object scope, [NotNull] OpenIddictScopeDescriptor descriptor, CancellationToken cancellationToken = default);
/// <summary>
/// Validates the scope to ensure it's in a consistent state.
/// </summary>
/// <param name="scope">The scope.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the validation error encountered when validating the scope.
/// </returns>
Task<ImmutableArray<ValidationResult>> ValidateAsync([NotNull] object scope, CancellationToken cancellationToken = default);
}
}

452
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
{
/// <summary>
/// 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.
/// </summary>
public interface IOpenIddictTokenManager
{
/// <summary>
/// Determines the number of tokens that exist in the database.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the number of tokens in the database.
/// </returns>
Task<long> CountAsync(CancellationToken cancellationToken = default);
/// <summary>
/// Determines the number of tokens that match the specified query.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the number of tokens that match the specified query.
/// </returns>
Task<long> CountAsync<TResult>([NotNull] Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken = default);
/// <summary>
/// Creates a new token based on the specified descriptor.
/// </summary>
/// <param name="descriptor">The token descriptor.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation, whose result returns the token.
/// </returns>
Task<object> CreateAsync([NotNull] OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken = default);
/// <summary>
/// Creates a new token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task CreateAsync([NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// Removes an existing token.
/// </summary>
/// <param name="token">The token to delete.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task DeleteAsync([NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// Extends the specified token by replacing its expiration date.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="date">The date on which the token will no longer be considered valid.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task ExtendAsync([NotNull] object token, [CanBeNull] DateTimeOffset? date, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the list of tokens corresponding to the specified application identifier.
/// </summary>
/// <param name="identifier">The application identifier associated with the tokens.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the tokens corresponding to the specified application.
/// </returns>
Task<ImmutableArray<object>> FindByApplicationIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the list of tokens corresponding to the specified authorization identifier.
/// </summary>
/// <param name="identifier">The authorization identifier associated with the tokens.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the tokens corresponding to the specified authorization.
/// </returns>
Task<ImmutableArray<object>> FindByAuthorizationIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves a token using its unique identifier.
/// </summary>
/// <param name="identifier">The unique identifier associated with the token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the token corresponding to the unique identifier.
/// </returns>
Task<object> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the list of tokens corresponding to the specified reference identifier.
/// Note: the reference identifier may be hashed or encrypted for security reasons.
/// </summary>
/// <param name="identifier">The reference identifier associated with the tokens.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the tokens corresponding to the specified reference identifier.
/// </returns>
Task<object> FindByReferenceIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the list of tokens corresponding to the specified subject.
/// </summary>
/// <param name="subject">The subject associated with the tokens.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the tokens corresponding to the specified subject.
/// </returns>
Task<ImmutableArray<object>> FindBySubjectAsync([NotNull] string subject, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the optional application identifier associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the application identifier associated with the token.
/// </returns>
ValueTask<string> GetApplicationIdAsync([NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns the first element.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the first element returned when executing the query.
/// </returns>
Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns the first element.
/// </summary>
/// <typeparam name="TState">The state type.</typeparam>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="state">The optional state.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the first element returned when executing the query.
/// </returns>
Task<TResult> GetAsync<TState, TResult>([NotNull] Func<IQueryable<object>, TState, IQueryable<TResult>> query, [CanBeNull] TState state, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the optional authorization identifier associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the authorization identifier associated with the token.
/// </returns>
ValueTask<string> GetAuthorizationIdAsync([NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the creation date associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the creation date associated with the specified token.
/// </returns>
ValueTask<DateTimeOffset?> GetCreationDateAsync([NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the expiration date associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the expiration date associated with the specified token.
/// </returns>
ValueTask<DateTimeOffset?> GetExpirationDateAsync([NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the unique identifier associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the unique identifier associated with the token.
/// </returns>
ValueTask<string> GetIdAsync([NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the payload associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the payload associated with the specified token.
/// </returns>
ValueTask<string> GetPayloadAsync([NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// 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.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the reference identifier associated with the specified token.
/// </returns>
ValueTask<string> GetReferenceIdAsync([NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the status associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the status associated with the specified token.
/// </returns>
ValueTask<string> GetStatusAsync([NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the subject associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the subject associated with the specified token.
/// </returns>
ValueTask<string> GetSubjectAsync([NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// Retrieves the token type associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the token type associated with the specified token.
/// </returns>
ValueTask<string> GetTokenTypeAsync([NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// Determines whether a given token has already been redemeed.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><c>true</c> if the token has already been redemeed, <c>false</c> otherwise.</returns>
Task<bool> IsRedeemedAsync([NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// Determines whether a given token has been revoked.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><c>true</c> if the token has been revoked, <c>false</c> otherwise.</returns>
Task<bool> IsRevokedAsync([NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// Determines whether a given token is valid.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><c>true</c> if the token is valid, <c>false</c> otherwise.</returns>
Task<bool> IsValidAsync([NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns all the corresponding elements.
/// </summary>
/// <param name="count">The number of results to return.</param>
/// <param name="offset">The number of results to skip.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
Task<ImmutableArray<object>> ListAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns all the corresponding elements.
/// </summary>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
Task<ImmutableArray<TResult>> ListAsync<TResult>([NotNull] Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken = default);
/// <summary>
/// Executes the specified query and returns all the corresponding elements.
/// </summary>
/// <typeparam name="TState">The state type.</typeparam>
/// <typeparam name="TResult">The result type.</typeparam>
/// <param name="query">The query to execute.</param>
/// <param name="state">The optional state.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns all the elements returned when executing the specified query.
/// </returns>
Task<ImmutableArray<TResult>> ListAsync<TState, TResult>([NotNull] Func<IQueryable<object>, TState, IQueryable<TResult>> query, [CanBeNull] TState state, CancellationToken cancellationToken = default);
/// <summary>
/// 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.
/// </summary>
/// <param name="identifier">The client identifier.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task<string> ObfuscateReferenceIdAsync([NotNull] string identifier, CancellationToken cancellationToken = default);
/// <summary>
/// Populates the specified descriptor using the properties exposed by the token.
/// </summary>
/// <param name="descriptor">The descriptor.</param>
/// <param name="token">The token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task PopulateAsync([NotNull] OpenIddictTokenDescriptor descriptor, [NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// Populates the token using the specified descriptor.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="descriptor">The descriptor.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task PopulateAsync([NotNull] object token, [NotNull] OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken = default);
/// <summary>
/// Removes the tokens that are marked as expired or invalid.
/// </summary>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task PruneAsync(CancellationToken cancellationToken = default);
/// <summary>
/// Redeems a token.
/// </summary>
/// <param name="token">The token to redeem.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
Task RedeemAsync([NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// Revokes a token.
/// </summary>
/// <param name="token">The token to revoke.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>A <see cref="Task"/> that can be used to monitor the asynchronous operation.</returns>
Task RevokeAsync([NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// Sets the application identifier associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the client application.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task SetApplicationIdAsync([NotNull] object token, [CanBeNull] string identifier, CancellationToken cancellationToken = default);
/// <summary>
/// Sets the authorization identifier associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the authorization.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task SetAuthorizationIdAsync([NotNull] object token, [CanBeNull] string identifier, CancellationToken cancellationToken = default);
/// <summary>
/// Updates an existing token.
/// </summary>
/// <param name="token">The token to update.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task UpdateAsync([NotNull] object token, CancellationToken cancellationToken = default);
/// <summary>
/// Updates an existing token.
/// </summary>
/// <param name="token">The token to update.</param>
/// <param name="descriptor">The descriptor used to update the token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
Task UpdateAsync([NotNull] object token, [NotNull] OpenIddictTokenDescriptor descriptor, CancellationToken cancellationToken = default);
/// <summary>
/// Validates the token to ensure it's in a consistent state.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the validation error encountered when validating the token.
/// </returns>
Task<ImmutableArray<ValidationResult>> ValidateAsync([NotNull] object token, CancellationToken cancellationToken = default);
}
}

7
src/OpenIddict.Abstractions/OpenIddict.Abstractions.csproj

@ -3,7 +3,7 @@
<Import Project="..\..\build\packages.props" />
<PropertyGroup>
<TargetFramework>netstandard1.0</TargetFramework>
<TargetFrameworks>net451;netstandard1.3</TargetFrameworks>
</PropertyGroup>
<PropertyGroup>
@ -17,7 +17,12 @@
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Newtonsoft.Json" Version="$(JsonNetVersion)" />
<PackageReference Include="System.Collections.Immutable" Version="$(ImmutableCollectionsVersion)" />
<PackageReference Include="System.ComponentModel.Annotations" Version="$(DataAnnotationsVersion)" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="$(TasksExtensionsVersion)" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="System.Security.Claims" Version="$(ClaimsVersion)" />
</ItemGroup>
</Project>

114
src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs

@ -22,7 +22,7 @@ namespace OpenIddict.Core
/// Provides methods allowing to manage the applications stored in the store.
/// </summary>
/// <typeparam name="TApplication">The type of the Application entity.</typeparam>
public class OpenIddictApplicationManager<TApplication> where TApplication : class
public class OpenIddictApplicationManager<TApplication> : 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.
/// </returns>
public virtual Task<long> CountAsync(CancellationToken cancellationToken = default)
{
return Store.CountAsync(cancellationToken);
}
=> Store.CountAsync(cancellationToken);
/// <summary>
/// Determines the number of applications that match the specified query.
@ -1360,5 +1358,113 @@ namespace OpenIddict.Core
return Task.FromResult(false);
}
}
Task<long> IOpenIddictApplicationManager.CountAsync(CancellationToken cancellationToken)
=> CountAsync(cancellationToken);
Task<long> IOpenIddictApplicationManager.CountAsync<TResult>(Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken)
=> CountAsync(query, cancellationToken);
async Task<object> 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<object> IOpenIddictApplicationManager.FindByClientIdAsync(string identifier, CancellationToken cancellationToken)
=> await FindByClientIdAsync(identifier, cancellationToken);
async Task<object> IOpenIddictApplicationManager.FindByIdAsync(string identifier, CancellationToken cancellationToken)
=> await FindByIdAsync(identifier, cancellationToken);
async Task<ImmutableArray<object>> IOpenIddictApplicationManager.FindByPostLogoutRedirectUriAsync(string address, CancellationToken cancellationToken)
=> (await FindByPostLogoutRedirectUriAsync(address, cancellationToken)).CastArray<object>();
async Task<ImmutableArray<object>> IOpenIddictApplicationManager.FindByRedirectUriAsync(string address, CancellationToken cancellationToken)
=> (await FindByRedirectUriAsync(address, cancellationToken)).CastArray<object>();
Task<TResult> IOpenIddictApplicationManager.GetAsync<TResult>(Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken)
=> GetAsync(query, cancellationToken);
Task<TResult> IOpenIddictApplicationManager.GetAsync<TState, TResult>(Func<IQueryable<object>, TState, IQueryable<TResult>> query, TState state, CancellationToken cancellationToken)
=> GetAsync(query, state, cancellationToken);
ValueTask<string> IOpenIddictApplicationManager.GetClientIdAsync(object application, CancellationToken cancellationToken)
=> GetClientIdAsync((TApplication) application, cancellationToken);
ValueTask<string> IOpenIddictApplicationManager.GetClientTypeAsync(object application, CancellationToken cancellationToken)
=> GetClientTypeAsync((TApplication) application, cancellationToken);
ValueTask<string> IOpenIddictApplicationManager.GetConsentTypeAsync(object application, CancellationToken cancellationToken)
=> GetConsentTypeAsync((TApplication) application, cancellationToken);
ValueTask<string> IOpenIddictApplicationManager.GetDisplayNameAsync(object application, CancellationToken cancellationToken)
=> GetDisplayNameAsync((TApplication) application, cancellationToken);
ValueTask<string> IOpenIddictApplicationManager.GetIdAsync(object application, CancellationToken cancellationToken)
=> GetIdAsync((TApplication) application, cancellationToken);
ValueTask<ImmutableArray<string>> IOpenIddictApplicationManager.GetPermissionsAsync(object application, CancellationToken cancellationToken)
=> GetPermissionsAsync((TApplication) application, cancellationToken);
ValueTask<ImmutableArray<string>> IOpenIddictApplicationManager.GetPostLogoutRedirectUrisAsync(object application, CancellationToken cancellationToken)
=> GetPostLogoutRedirectUrisAsync((TApplication) application, cancellationToken);
ValueTask<ImmutableArray<string>> IOpenIddictApplicationManager.GetRedirectUrisAsync(object application, CancellationToken cancellationToken)
=> GetRedirectUrisAsync((TApplication) application, cancellationToken);
Task<bool> IOpenIddictApplicationManager.HasPermissionAsync(object application, string permission, CancellationToken cancellationToken)
=> HasPermissionAsync((TApplication) application, permission, cancellationToken);
Task<bool> IOpenIddictApplicationManager.IsConfidentialAsync(object application, CancellationToken cancellationToken)
=> IsConfidentialAsync((TApplication) application, cancellationToken);
Task<bool> IOpenIddictApplicationManager.IsHybridAsync(object application, CancellationToken cancellationToken)
=> IsHybridAsync((TApplication) application, cancellationToken);
Task<bool> IOpenIddictApplicationManager.IsPublicAsync(object application, CancellationToken cancellationToken)
=> IsPublicAsync((TApplication) application, cancellationToken);
async Task<ImmutableArray<object>> IOpenIddictApplicationManager.ListAsync(int? count, int? offset, CancellationToken cancellationToken)
=> (await ListAsync(count, offset, cancellationToken)).CastArray<object>();
Task<ImmutableArray<TResult>> IOpenIddictApplicationManager.ListAsync<TResult>(Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken)
=> ListAsync(query, cancellationToken);
Task<ImmutableArray<TResult>> IOpenIddictApplicationManager.ListAsync<TState, TResult>(Func<IQueryable<object>, TState, IQueryable<TResult>> 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<ImmutableArray<ValidationResult>> IOpenIddictApplicationManager.ValidateAsync(object application, CancellationToken cancellationToken)
=> ValidateAsync((TApplication) application, cancellationToken);
Task<bool> IOpenIddictApplicationManager.ValidateClientSecretAsync(object application, string secret, CancellationToken cancellationToken)
=> ValidateClientSecretAsync((TApplication) application, secret, cancellationToken);
Task<bool> IOpenIddictApplicationManager.ValidatePostLogoutRedirectUriAsync(string address, CancellationToken cancellationToken)
=> ValidatePostLogoutRedirectUriAsync(address, cancellationToken);
Task<bool> IOpenIddictApplicationManager.ValidateRedirectUriAsync(object application, string address, CancellationToken cancellationToken)
=> ValidateRedirectUriAsync((TApplication) application, address, cancellationToken);
}
}

114
src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs

@ -22,7 +22,7 @@ namespace OpenIddict.Core
/// Provides methods allowing to manage the authorizations stored in the store.
/// </summary>
/// <typeparam name="TAuthorization">The type of the Authorization entity.</typeparam>
public class OpenIddictAuthorizationManager<TAuthorization> where TAuthorization : class
public class OpenIddictAuthorizationManager<TAuthorization> : 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.
/// </returns>
public virtual Task<long> CountAsync(CancellationToken cancellationToken = default)
{
return Store.CountAsync(cancellationToken);
}
=> Store.CountAsync(cancellationToken);
/// <summary>
/// Determines the number of authorizations that match the specified query.
@ -1035,5 +1033,113 @@ namespace OpenIddict.Core
builder.MoveToImmutable() :
builder.ToImmutable();
}
Task<long> IOpenIddictAuthorizationManager.CountAsync(CancellationToken cancellationToken)
=> CountAsync(cancellationToken);
Task<long> IOpenIddictAuthorizationManager.CountAsync<TResult>(Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken)
=> CountAsync(query, cancellationToken);
async Task<object> IOpenIddictAuthorizationManager.CreateAsync(ClaimsPrincipal principal, string subject, string client, string type, ImmutableArray<string> scopes, ImmutableDictionary<string, string> properties, CancellationToken cancellationToken)
=> await CreateAsync(principal, subject, client, type, scopes, properties, cancellationToken);
async Task<object> 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<ImmutableArray<object>> IOpenIddictAuthorizationManager.FindAsync(string subject, string client, CancellationToken cancellationToken)
=> (await FindAsync(subject, client, cancellationToken)).CastArray<object>();
async Task<ImmutableArray<object>> IOpenIddictAuthorizationManager.FindAsync(string subject, string client, string status, CancellationToken cancellationToken)
=> (await FindAsync(subject, client, status, cancellationToken)).CastArray<object>();
async Task<ImmutableArray<object>> IOpenIddictAuthorizationManager.FindAsync(string subject, string client, string status, string type, CancellationToken cancellationToken)
=> (await FindAsync(subject, client, status, type, cancellationToken)).CastArray<object>();
async Task<ImmutableArray<object>> IOpenIddictAuthorizationManager.FindAsync(string subject, string client, string status, string type, ImmutableArray<string> scopes, CancellationToken cancellationToken)
=> (await FindAsync(subject, client, status, type, scopes, cancellationToken)).CastArray<object>();
async Task<object> IOpenIddictAuthorizationManager.FindByIdAsync(string identifier, CancellationToken cancellationToken)
=> await FindByIdAsync(identifier, cancellationToken);
async Task<ImmutableArray<object>> IOpenIddictAuthorizationManager.FindBySubjectAsync(string subject, CancellationToken cancellationToken)
=> (await FindBySubjectAsync(subject, cancellationToken)).CastArray<object>();
ValueTask<string> IOpenIddictAuthorizationManager.GetApplicationIdAsync(object authorization, CancellationToken cancellationToken)
=> GetApplicationIdAsync((TAuthorization) authorization, cancellationToken);
Task<TResult> IOpenIddictAuthorizationManager.GetAsync<TResult>(Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken)
=> GetAsync(query, cancellationToken);
Task<TResult> IOpenIddictAuthorizationManager.GetAsync<TState, TResult>(Func<IQueryable<object>, TState, IQueryable<TResult>> query, TState state, CancellationToken cancellationToken)
=> GetAsync(query, state, cancellationToken);
ValueTask<string> IOpenIddictAuthorizationManager.GetIdAsync(object authorization, CancellationToken cancellationToken)
=> GetIdAsync((TAuthorization) authorization, cancellationToken);
ValueTask<ImmutableArray<string>> IOpenIddictAuthorizationManager.GetScopesAsync(object authorization, CancellationToken cancellationToken)
=> GetScopesAsync((TAuthorization) authorization, cancellationToken);
ValueTask<string> IOpenIddictAuthorizationManager.GetStatusAsync(object authorization, CancellationToken cancellationToken)
=> GetStatusAsync((TAuthorization) authorization, cancellationToken);
ValueTask<string> IOpenIddictAuthorizationManager.GetSubjectAsync(object authorization, CancellationToken cancellationToken)
=> GetSubjectAsync((TAuthorization) authorization, cancellationToken);
ValueTask<string> IOpenIddictAuthorizationManager.GetTypeAsync(object authorization, CancellationToken cancellationToken)
=> GetTypeAsync((TAuthorization) authorization, cancellationToken);
Task<bool> IOpenIddictAuthorizationManager.HasScopesAsync(object authorization, ImmutableArray<string> scopes, CancellationToken cancellationToken)
=> HasScopesAsync((TAuthorization) authorization, scopes, cancellationToken);
Task<bool> IOpenIddictAuthorizationManager.IsAdHocAsync(object authorization, CancellationToken cancellationToken)
=> IsAdHocAsync((TAuthorization) authorization, cancellationToken);
Task<bool> IOpenIddictAuthorizationManager.IsPermanentAsync(object authorization, CancellationToken cancellationToken)
=> IsPermanentAsync((TAuthorization) authorization, cancellationToken);
Task<bool> IOpenIddictAuthorizationManager.IsRevokedAsync(object authorization, CancellationToken cancellationToken)
=> IsRevokedAsync((TAuthorization) authorization, cancellationToken);
Task<bool> IOpenIddictAuthorizationManager.IsValidAsync(object authorization, CancellationToken cancellationToken)
=> IsValidAsync((TAuthorization) authorization, cancellationToken);
async Task<ImmutableArray<object>> IOpenIddictAuthorizationManager.ListAsync(int? count, int? offset, CancellationToken cancellationToken)
=> (await ListAsync(count, offset, cancellationToken)).CastArray<object>();
Task<ImmutableArray<TResult>> IOpenIddictAuthorizationManager.ListAsync<TResult>(Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken)
=> ListAsync(query, cancellationToken);
Task<ImmutableArray<TResult>> IOpenIddictAuthorizationManager.ListAsync<TState, TResult>(Func<IQueryable<object>, TState, IQueryable<TResult>> 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<ImmutableArray<ValidationResult>> IOpenIddictAuthorizationManager.ValidateAsync(object authorization, CancellationToken cancellationToken)
=> ValidateAsync((TAuthorization) authorization, cancellationToken);
}
}

78
src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs

@ -22,7 +22,7 @@ namespace OpenIddict.Core
/// Provides methods allowing to manage the scopes stored in the store.
/// </summary>
/// <typeparam name="TScope">The type of the Scope entity.</typeparam>
public class OpenIddictScopeManager<TScope> where TScope : class
public class OpenIddictScopeManager<TScope> : 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.
/// </returns>
public virtual Task<long> CountAsync(CancellationToken cancellationToken = default)
{
return Store.CountAsync(cancellationToken);
}
=> Store.CountAsync(cancellationToken);
/// <summary>
/// Determines the number of scopes that match the specified query.
@ -627,5 +625,77 @@ namespace OpenIddict.Core
builder.MoveToImmutable() :
builder.ToImmutable();
}
Task<long> IOpenIddictScopeManager.CountAsync(CancellationToken cancellationToken)
=> CountAsync(cancellationToken);
Task<long> IOpenIddictScopeManager.CountAsync<TResult>(Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken)
=> CountAsync(query, cancellationToken);
async Task<object> 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<object> IOpenIddictScopeManager.FindByIdAsync(string identifier, CancellationToken cancellationToken)
=> await FindByIdAsync(identifier, cancellationToken);
async Task<object> IOpenIddictScopeManager.FindByNameAsync(string name, CancellationToken cancellationToken)
=> await FindByNameAsync(name, cancellationToken);
async Task<ImmutableArray<object>> IOpenIddictScopeManager.FindByNamesAsync(ImmutableArray<string> names, CancellationToken cancellationToken)
=> (await FindByNamesAsync(names, cancellationToken)).CastArray<object>();
Task<TResult> IOpenIddictScopeManager.GetAsync<TResult>(Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken)
=> GetAsync(query, cancellationToken);
Task<TResult> IOpenIddictScopeManager.GetAsync<TState, TResult>(Func<IQueryable<object>, TState, IQueryable<TResult>> query, TState state, CancellationToken cancellationToken)
=> GetAsync(query, state, cancellationToken);
ValueTask<string> IOpenIddictScopeManager.GetDescriptionAsync(object scope, CancellationToken cancellationToken)
=> GetDescriptionAsync((TScope) scope, cancellationToken);
ValueTask<string> IOpenIddictScopeManager.GetDisplayNameAsync(object scope, CancellationToken cancellationToken)
=> GetDisplayNameAsync((TScope) scope, cancellationToken);
ValueTask<string> IOpenIddictScopeManager.GetIdAsync(object scope, CancellationToken cancellationToken)
=> GetIdAsync((TScope) scope, cancellationToken);
ValueTask<string> IOpenIddictScopeManager.GetNameAsync(object scope, CancellationToken cancellationToken)
=> GetNameAsync((TScope) scope, cancellationToken);
ValueTask<ImmutableArray<string>> IOpenIddictScopeManager.GetResourcesAsync(object scope, CancellationToken cancellationToken)
=> GetResourcesAsync((TScope) scope, cancellationToken);
async Task<ImmutableArray<object>> IOpenIddictScopeManager.ListAsync(int? count, int? offset, CancellationToken cancellationToken)
=> (await ListAsync(count, offset, cancellationToken)).CastArray<object>();
Task<ImmutableArray<TResult>> IOpenIddictScopeManager.ListAsync<TResult>(Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken)
=> ListAsync(query, cancellationToken);
Task<ImmutableArray<TResult>> IOpenIddictScopeManager.ListAsync<TState, TResult>(Func<IQueryable<object>, TState, IQueryable<TResult>> query, TState state, CancellationToken cancellationToken)
=> ListAsync(query, state, cancellationToken);
Task<ImmutableArray<string>> IOpenIddictScopeManager.ListResourcesAsync(ImmutableArray<string> 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<ImmutableArray<ValidationResult>> IOpenIddictScopeManager.ValidateAsync(object scope, CancellationToken cancellationToken)
=> ValidateAsync((TScope) scope, cancellationToken);
}
}

126
src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs

@ -23,7 +23,7 @@ namespace OpenIddict.Core
/// Provides methods allowing to manage the tokens stored in the store.
/// </summary>
/// <typeparam name="TToken">The type of the Token entity.</typeparam>
public class OpenIddictTokenManager<TToken> where TToken : class
public class OpenIddictTokenManager<TToken> : 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.
/// </returns>
public virtual Task<long> CountAsync(CancellationToken cancellationToken = default)
{
return Store.CountAsync(cancellationToken);
}
=> Store.CountAsync(cancellationToken);
/// <summary>
/// Determines the number of tokens that match the specified query.
@ -968,5 +966,125 @@ namespace OpenIddict.Core
builder.MoveToImmutable() :
builder.ToImmutable();
}
Task<long> IOpenIddictTokenManager.CountAsync(CancellationToken cancellationToken)
=> CountAsync(cancellationToken);
Task<long> IOpenIddictTokenManager.CountAsync<TResult>(Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken)
=> CountAsync(query, cancellationToken);
async Task<object> 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<ImmutableArray<object>> IOpenIddictTokenManager.FindByApplicationIdAsync(string identifier, CancellationToken cancellationToken)
=> (await FindByApplicationIdAsync(identifier, cancellationToken)).CastArray<object>();
async Task<ImmutableArray<object>> IOpenIddictTokenManager.FindByAuthorizationIdAsync(string identifier, CancellationToken cancellationToken)
=> (await FindByAuthorizationIdAsync(identifier, cancellationToken)).CastArray<object>();
async Task<object> IOpenIddictTokenManager.FindByIdAsync(string identifier, CancellationToken cancellationToken)
=> await FindByIdAsync(identifier, cancellationToken);
async Task<object> IOpenIddictTokenManager.FindByReferenceIdAsync(string identifier, CancellationToken cancellationToken)
=> await FindByReferenceIdAsync(identifier, cancellationToken);
async Task<ImmutableArray<object>> IOpenIddictTokenManager.FindBySubjectAsync(string subject, CancellationToken cancellationToken)
=> (await FindBySubjectAsync(subject, cancellationToken)).CastArray<object>();
ValueTask<string> IOpenIddictTokenManager.GetApplicationIdAsync(object token, CancellationToken cancellationToken)
=> GetApplicationIdAsync((TToken) token, cancellationToken);
Task<TResult> IOpenIddictTokenManager.GetAsync<TResult>(Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken)
=> GetAsync(query, cancellationToken);
Task<TResult> IOpenIddictTokenManager.GetAsync<TState, TResult>(Func<IQueryable<object>, TState, IQueryable<TResult>> query, TState state, CancellationToken cancellationToken)
=> GetAsync(query, state, cancellationToken);
ValueTask<string> IOpenIddictTokenManager.GetAuthorizationIdAsync(object token, CancellationToken cancellationToken)
=> GetAuthorizationIdAsync((TToken) token, cancellationToken);
ValueTask<DateTimeOffset?> IOpenIddictTokenManager.GetCreationDateAsync(object token, CancellationToken cancellationToken)
=> GetCreationDateAsync((TToken) token, cancellationToken);
ValueTask<DateTimeOffset?> IOpenIddictTokenManager.GetExpirationDateAsync(object token, CancellationToken cancellationToken)
=> GetExpirationDateAsync((TToken) token, cancellationToken);
ValueTask<string> IOpenIddictTokenManager.GetIdAsync(object token, CancellationToken cancellationToken)
=> GetIdAsync((TToken) token, cancellationToken);
ValueTask<string> IOpenIddictTokenManager.GetPayloadAsync(object token, CancellationToken cancellationToken)
=> GetPayloadAsync((TToken) token, cancellationToken);
ValueTask<string> IOpenIddictTokenManager.GetReferenceIdAsync(object token, CancellationToken cancellationToken)
=> GetReferenceIdAsync((TToken) token, cancellationToken);
ValueTask<string> IOpenIddictTokenManager.GetStatusAsync(object token, CancellationToken cancellationToken)
=> GetStatusAsync((TToken) token, cancellationToken);
ValueTask<string> IOpenIddictTokenManager.GetSubjectAsync(object token, CancellationToken cancellationToken)
=> GetSubjectAsync((TToken) token, cancellationToken);
ValueTask<string> IOpenIddictTokenManager.GetTokenTypeAsync(object token, CancellationToken cancellationToken)
=> GetTokenTypeAsync((TToken) token, cancellationToken);
Task<bool> IOpenIddictTokenManager.IsRedeemedAsync(object token, CancellationToken cancellationToken)
=> IsRedeemedAsync((TToken) token, cancellationToken);
Task<bool> IOpenIddictTokenManager.IsRevokedAsync(object token, CancellationToken cancellationToken)
=> IsRevokedAsync((TToken) token, cancellationToken);
Task<bool> IOpenIddictTokenManager.IsValidAsync(object token, CancellationToken cancellationToken)
=> IsValidAsync((TToken) token, cancellationToken);
async Task<ImmutableArray<object>> IOpenIddictTokenManager.ListAsync(int? count, int? offset, CancellationToken cancellationToken)
=> (await ListAsync(count, offset, cancellationToken)).CastArray<object>();
Task<ImmutableArray<TResult>> IOpenIddictTokenManager.ListAsync<TResult>(Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken)
=> ListAsync(query, cancellationToken);
Task<ImmutableArray<TResult>> IOpenIddictTokenManager.ListAsync<TState, TResult>(Func<IQueryable<object>, TState, IQueryable<TResult>> query, TState state, CancellationToken cancellationToken)
=> ListAsync(query, state, cancellationToken);
Task<string> 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<ImmutableArray<ValidationResult>> IOpenIddictTokenManager.ValidateAsync(object token, CancellationToken cancellationToken)
=> ValidateAsync((TToken) token, cancellationToken);
}
}

5
src/OpenIddict.Core/OpenIddict.Core.csproj

@ -20,12 +20,7 @@
<PackageReference Include="CryptoHelper" Version="$(CryptoHelperVersion)" />
<PackageReference Include="JetBrains.Annotations" Version="$(JetBrainsVersion)" PrivateAssets="All" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Newtonsoft.Json" Version="$(JsonNetVersion)" />
<PackageReference Include="System.Collections.Immutable" Version="$(ImmutableCollectionsVersion)" />
<PackageReference Include="System.ComponentModel.Annotations" Version="$(DataAnnotationsVersion)" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="$(TasksExtensionsVersion)" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">

66
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<IOpenIddictScopeStoreResolver, OpenIddictScopeStoreResolver>();
builder.Services.TryAddScoped<IOpenIddictTokenStoreResolver, OpenIddictTokenStoreResolver>();
builder.Services.TryAddScoped(provider =>
{
var options = provider.GetRequiredService<IOptions<OpenIddictCoreOptions>>().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<IOptions<OpenIddictCoreOptions>>().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<IOptions<OpenIddictCoreOptions>>().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<IOptions<OpenIddictCoreOptions>>().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);
}

12
src/OpenIddict.Core/OpenIddictCoreOptions.cs

@ -11,22 +11,26 @@ namespace OpenIddict.Core
public class OpenIddictCoreOptions
{
/// <summary>
/// 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.
/// </summary>
public Type DefaultApplicationType { get; set; }
/// <summary>
/// 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.
/// </summary>
public Type DefaultAuthorizationType { get; set; }
/// <summary>
/// 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.
/// </summary>
public Type DefaultScopeType { get; set; }
/// <summary>
/// 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.
/// </summary>
public Type DefaultTokenType { get; set; }
}

2
src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs

@ -291,7 +291,7 @@ namespace OpenIddict.EntityFramework
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
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.

2
src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs

@ -303,7 +303,7 @@ namespace OpenIddict.EntityFramework
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
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.

2
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs

@ -413,7 +413,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
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.

2
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs

@ -286,7 +286,7 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns>
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.

36
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<TApplication, TAuthorization, TScope, TToken> : 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<ILogger<OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken>>>();
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider>>();
// 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<OpenIddictApplicationManager<TApplication>>();
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken>>>();
var scopes = context.HttpContext.RequestServices.GetRequiredService<OpenIddictScopeManager<TScope>>();
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider>>();
var applicationManager = context.HttpContext.RequestServices.GetRequiredService<IOpenIddictApplicationManager>();
var scopeManager = context.HttpContext.RequestServices.GetRequiredService<IOpenIddictScopeManager>();
// 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);

3
src/OpenIddict.Server/Internal/OpenIddictServerProvider.Discovery.cs

@ -14,8 +14,7 @@ using OpenIddict.Abstractions;
namespace OpenIddict.Server
{
public partial class OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken> : 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)
{

34
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<TApplication, TAuthorization, TScope, TToken> : 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<OpenIddictApplicationManager<TApplication>>();
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken>>>();
var scopes = context.HttpContext.RequestServices.GetRequiredService<OpenIddictScopeManager<TScope>>();
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider>>();
var applicationManager = context.HttpContext.RequestServices.GetRequiredService<IOpenIddictApplicationManager>();
var scopeManager = context.HttpContext.RequestServices.GetRequiredService<IOpenIddictScopeManager>();
// 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<ILogger<OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken>>>();
var tokens = context.HttpContext.RequestServices.GetRequiredService<OpenIddictTokenManager<TToken>>();
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider>>();
var tokenManager = context.HttpContext.RequestServices.GetRequiredService<IOpenIddictTokenManager>();
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<TToken>($"{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);

106
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<TApplication, TAuthorization, TScope, TToken> : 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<OpenIddictApplicationManager<TApplication>>();
var authorizations = context.RequestServices.GetRequiredService<OpenIddictAuthorizationManager<TAuthorization>>();
var logger = context.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken>>>();
var logger = context.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider>>();
var applicationManager = context.RequestServices.GetRequiredService<IOpenIddictApplicationManager>();
var authorizationManager = context.RequestServices.GetRequiredService<IOpenIddictAuthorizationManager>();
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<TApplication>($"{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<OpenIddictApplicationManager<TApplication>>();
var logger = context.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken>>>();
var tokens = context.RequestServices.GetRequiredService<OpenIddictTokenManager<TToken>>();
var logger = context.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider>>();
var applicationManager = context.RequestServices.GetRequiredService<IOpenIddictApplicationManager>();
var tokenManager = context.RequestServices.GetRequiredService<IOpenIddictTokenManager>();
// 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<TApplication>($"{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<AuthenticationTicket> format)
{
var logger = context.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken>>>();
var tokens = context.RequestServices.GetRequiredService<OpenIddictTokenManager<TToken>>();
var logger = context.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider>>();
var tokenManager = context.RequestServices.GetRequiredService<IOpenIddictTokenManager>();
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<TToken>($"{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<TToken>($"{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<bool> TryRevokeAuthorizationAsync([NotNull] AuthenticationTicket ticket, [NotNull] HttpContext context)
{
var authorizations = context.RequestServices.GetRequiredService<OpenIddictAuthorizationManager<TAuthorization>>();
var logger = context.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken>>>();
var logger = context.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider>>();
var authorizationManager = context.RequestServices.GetRequiredService<IOpenIddictAuthorizationManager>();
// 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<bool> TryRevokeTokenAsync([NotNull] TToken token, [NotNull] HttpContext context)
private async Task<bool> TryRevokeTokenAsync([NotNull] object token, [NotNull] HttpContext context)
{
var logger = context.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken>>>();
var tokens = context.RequestServices.GetRequiredService<OpenIddictTokenManager<TToken>>();
var logger = context.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider>>();
var tokenManager = context.RequestServices.GetRequiredService<IOpenIddictTokenManager>();
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<bool> TryRevokeTokensAsync([NotNull] AuthenticationTicket ticket, [NotNull] HttpContext context)
{
var tokens = context.RequestServices.GetRequiredService<OpenIddictTokenManager<TToken>>();
var tokenManager = context.RequestServices.GetRequiredService<IOpenIddictTokenManager>();
// 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<bool> TryRedeemTokenAsync([NotNull] TToken token, [NotNull] HttpContext context)
private async Task<bool> TryRedeemTokenAsync([NotNull] object token, [NotNull] HttpContext context)
{
var logger = context.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken>>>();
var tokens = context.RequestServices.GetRequiredService<OpenIddictTokenManager<TToken>>();
var identifier = await tokens.GetIdAsync(token);
var logger = context.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider>>();
var tokenManager = context.RequestServices.GetRequiredService<IOpenIddictTokenManager>();
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<bool> TryExtendTokenAsync(
[NotNull] TToken token, [NotNull] AuthenticationTicket ticket,
[NotNull] object token, [NotNull] AuthenticationTicket ticket,
[NotNull] HttpContext context, [NotNull] OpenIddictServerOptions options)
{
var logger = context.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken>>>();
var tokens = context.RequestServices.GetRequiredService<OpenIddictTokenManager<TToken>>();
var logger = context.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider>>();
var tokenManager = context.RequestServices.GetRequiredService<IOpenIddictTokenManager>();
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<ILogger<OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken>>>();
var logger = context.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider>>();
Debug.Assert(properties != null, "The authentication properties shouldn't be null.");

24
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<TApplication, TAuthorization, TScope, TToken> : 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<OpenIddictApplicationManager<TApplication>>();
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken>>>();
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider>>();
var applicationManager = context.HttpContext.RequestServices.GetRequiredService<IOpenIddictApplicationManager>();
// 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<ILogger<OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken>>>();
var tokens = context.HttpContext.RequestServices.GetRequiredService<OpenIddictTokenManager<TToken>>();
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider>>();
var tokenManager = context.HttpContext.RequestServices.GetRequiredService<IOpenIddictTokenManager>();
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<TToken>($"{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);

26
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<TApplication, TAuthorization, TScope, TToken> : 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<OpenIddictApplicationManager<TApplication>>();
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken>>>();
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider>>();
var applicationManager = context.HttpContext.RequestServices.GetRequiredService<IOpenIddictApplicationManager>();
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<ILogger<OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken>>>();
var tokens = context.HttpContext.RequestServices.GetRequiredService<OpenIddictTokenManager<TToken>>();
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider>>();
var tokenManager = context.HttpContext.RequestServices.GetRequiredService<IOpenIddictTokenManager>();
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<TToken>($"{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)

3
src/OpenIddict.Server/Internal/OpenIddictServerProvider.Serialization.cs

@ -12,8 +12,7 @@ using JetBrains.Annotations;
namespace OpenIddict.Server
{
public partial class OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken> : 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)
{

12
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<TApplication, TAuthorization, TScope, TToken> : 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<ILogger<OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken>>>();
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider>>();
// 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<OpenIddictApplicationManager<TApplication>>();
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken>>>();
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<OpenIddictServerProvider>>();
var applicationManager = context.HttpContext.RequestServices.GetRequiredService<IOpenIddictApplicationManager>();
// 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);

3
src/OpenIddict.Server/Internal/OpenIddictServerProvider.Userinfo.cs

@ -10,8 +10,7 @@ using JetBrains.Annotations;
namespace OpenIddict.Server
{
public partial class OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken> : 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)
{

5
src/OpenIddict.Server/Internal/OpenIddictServerProvider.cs

@ -18,8 +18,7 @@ using OpenIddict.Abstractions;
namespace OpenIddict.Server
{
[EditorBrowsable(EditorBrowsableState.Never)]
public partial class OpenIddictServerProvider<TApplication, TAuthorization, TScope, TToken> : 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<TToken>($"{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,

3
src/OpenIddict.Server/OpenIddict.Server.csproj

@ -13,13 +13,14 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\OpenIddict.Core\OpenIddict.Core.csproj" />
<ProjectReference Include="..\OpenIddict.Abstractions\OpenIddict.Abstractions.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AspNet.Security.OpenIdConnect.Server" Version="$(AspNetContribOpenIdServerVersion)" />
<PackageReference Include="JetBrains.Annotations" Version="$(JetBrainsVersion)" PrivateAssets="All" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="$(AspNetCoreVersion)" />
</ItemGroup>
</Project>

5
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
/// <summary>
/// Rejects authorization and token requests that specify scopes that have not been
/// registered using <see cref="RegisterScopes(string[])"/> or
/// <see cref="OpenIddictScopeManager{TScope}.CreateAsync(TScope, CancellationToken)"/>.
/// registered using <see cref="RegisterScopes(string[])"/> or the scope manager.
/// </summary>
/// <returns>The <see cref="OpenIddictServerBuilder"/>.</returns>
public OpenIddictServerBuilder EnableScopeValidation()

49
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<IOptions<OpenIddictCoreOptions>>().Value;
// Resolve the OpenIddict options from the DI container.
var options = app.ApplicationServices.GetRequiredService<IOptions<OpenIddictServerOptions>>().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<IOptions<OpenIddictServerOptions>>().Value;
if (options.Cache == null)
{
options.Cache = app.ApplicationServices.GetRequiredService<IDistributedCache>();

24
src/OpenIddict.Server/OpenIddictServerOptions.cs

@ -14,7 +14,7 @@ using Microsoft.Extensions.Caching.Distributed;
namespace OpenIddict.Server
{
/// <summary>
/// Provides various settings needed to configure OpenIddict.
/// Provides various settings needed to configure the OpenIddict server handler.
/// </summary>
public class OpenIddictServerOptions : OpenIdConnectServerOptions
{
@ -23,19 +23,9 @@ namespace OpenIddict.Server
/// </summary>
public OpenIddictServerOptions()
{
Provider = null;
Provider = new OpenIddictServerProvider();
}
/// <summary>
/// Gets or sets the type corresponding to the Application entity.
/// </summary>
public Type ApplicationType { get; set; }
/// <summary>
/// Gets or sets the type corresponding to the Authorization entity.
/// </summary>
public Type AuthorizationType { get; set; }
/// <summary>
/// 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
};
/// <summary>
/// Gets or sets the type corresponding to the Scope entity.
/// </summary>
public Type ScopeType { get; set; }
/// <summary>
/// Gets or sets the type corresponding to the Token entity.
/// </summary>
public Type TokenType { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether reference tokens should be used.
/// When set to <c>true</c>, authorization codes, access tokens and refresh tokens

23
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<TToken> : OpenIddictValidationHandler where TToken : class
public class OpenIddictValidationHandler : OAuthValidationHandler
{
protected override async Task<AuthenticateResult> 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<AuthenticateResult> CreateTicketAsync(string payload)
{
var manager = Context.RequestServices.GetService<OpenIddictTokenManager<TToken>>();
// 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<IOpenIddictTokenManager>();
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;
}
}

17
src/OpenIddict.Validation/Internal/OpenIddictValidationMiddleware.cs

@ -32,21 +32,4 @@ namespace OpenIddict.Validation
protected override AuthenticationHandler<OAuthValidationOptions> CreateHandler()
=> new OpenIddictValidationHandler();
}
[EditorBrowsable(EditorBrowsableState.Never)]
public class OpenIddictValidationMiddleware<TToken> : OpenIddictValidationMiddleware where TToken : class
{
public OpenIddictValidationMiddleware(
[NotNull] RequestDelegate next,
[NotNull] IOptions<OpenIddictValidationOptions> options,
[NotNull] ILoggerFactory loggerFactory,
[NotNull] UrlEncoder encoder,
[NotNull] IDataProtectionProvider dataProtectionProvider)
: base(next, options, loggerFactory, encoder, dataProtectionProvider)
{
}
protected override AuthenticationHandler<OAuthValidationOptions> CreateHandler()
=> new OpenIddictValidationHandler<TToken>();
}
}

2
src/OpenIddict.Validation/OpenIddict.Validation.csproj

@ -13,7 +13,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\OpenIddict.Core\OpenIddict.Core.csproj" />
<ProjectReference Include="..\OpenIddict.Abstractions\OpenIddict.Abstractions.csproj" />
</ItemGroup>
<ItemGroup>

30
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<IOptions<OpenIddictCoreOptions>>().Value;
var options = app.ApplicationServices.GetRequiredService<IOptions<OpenIddictValidationOptions>>().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<OpenIddictValidationOptions>(options));
}
return app.UseMiddleware<OpenIddictValidationMiddleware>(new OptionsWrapper<OpenIddictValidationOptions>(options));
}
}

6
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
{
/// <summary>
/// Gets or sets the type corresponding to the Token entity.
/// </summary>
public Type TokenType { get; set; }
/// <summary>
/// Gets or sets a boolean indicating whether reference tokens are used.
/// </summary>

1
src/OpenIddict/OpenIddict.csproj

@ -13,6 +13,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\OpenIddict.Core\OpenIddict.Core.csproj" />
<ProjectReference Include="..\OpenIddict.Models\OpenIddict.Models.csproj" />
<ProjectReference Include="..\OpenIddict.Server\OpenIddict.Server.csproj" />
<ProjectReference Include="..\OpenIddict.Validation\OpenIddict.Validation.csproj" />

Loading…
Cancel
Save