Browse Source

Backport the managers/stores changes to OpenIddict 1.x

pull/553/head
Kévin Chalet 9 years ago
parent
commit
42801802c4
  1. 55
      src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
  2. 51
      src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
  3. 35
      src/OpenIddict.Core/Stores/IOpenIddictAuthorizationStore.cs
  4. 36
      src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs
  5. 78
      src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs
  6. 74
      src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs
  7. 6
      src/OpenIddict.EntityFramework/OpenIddictExtensions.cs
  8. 46
      src/OpenIddict.EntityFramework/Stores/OpenIddictApplicationStore.cs
  9. 97
      src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs
  10. 112
      src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs
  11. 9
      src/OpenIddict.EntityFrameworkCore/OpenIddictExtensions.cs
  12. 46
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictApplicationStore.cs
  13. 65
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs
  14. 48
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs
  15. 7
      src/OpenIddict/OpenIddictProvider.Helpers.cs
  16. 4
      src/OpenIddict/OpenIddictProvider.Signin.cs

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

@ -201,6 +201,25 @@ namespace OpenIddict.Core
return Store.FindByIdAsync(identifier, cancellationToken); return Store.FindByIdAsync(identifier, cancellationToken);
} }
/// <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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the application identifier associated with the authorization.
/// </returns>
public virtual Task<string> GetApplicationIdAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization == null)
{
throw new ArgumentNullException(nameof(authorization));
}
return Store.GetApplicationIdAsync(authorization, cancellationToken);
}
/// <summary> /// <summary>
/// Executes the specified query. /// Executes the specified query.
/// </summary> /// </summary>
@ -338,6 +357,22 @@ namespace OpenIddict.Core
return Store.ListAsync(query, cancellationToken); return Store.ListAsync(query, cancellationToken);
} }
/// <summary>
/// Lists the ad-hoc authorizations that are marked as invalid or have no
/// valid token attached and that can be safely removed from the database.
/// </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>
public virtual Task<ImmutableArray<TAuthorization>> ListInvalidAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken)
{
return Store.ListInvalidAsync(count, offset, cancellationToken);
}
/// <summary> /// <summary>
/// Revokes an authorization. /// Revokes an authorization.
/// </summary> /// </summary>
@ -360,6 +395,26 @@ namespace OpenIddict.Core
} }
} }
/// <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>
public virtual async Task SetApplicationIdAsync([NotNull] TAuthorization authorization, [CanBeNull] string identifier, CancellationToken cancellationToken)
{
if (authorization == null)
{
throw new ArgumentNullException(nameof(authorization));
}
await Store.SetApplicationIdAsync(authorization, identifier, cancellationToken);
await UpdateAsync(authorization, cancellationToken);
}
/// <summary> /// <summary>
/// Updates an existing authorization. /// Updates an existing authorization.
/// </summary> /// </summary>

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

@ -236,6 +236,25 @@ namespace OpenIddict.Core
return Store.FindBySubjectAsync(subject, cancellationToken); return Store.FindBySubjectAsync(subject, cancellationToken);
} }
/// <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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the application identifier associated with the token.
/// </returns>
public virtual Task<string> GetApplicationIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
return Store.GetApplicationIdAsync(token, cancellationToken);
}
/// <summary> /// <summary>
/// Executes the specified query. /// Executes the specified query.
/// </summary> /// </summary>
@ -490,6 +509,22 @@ namespace OpenIddict.Core
return Store.ListAsync(query, cancellationToken); return Store.ListAsync(query, cancellationToken);
} }
/// <summary>
/// Lists the tokens that are marked as expired or invalid
/// and that can be safely removed from the database.
/// </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>
public virtual Task<ImmutableArray<TToken>> ListInvalidAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken)
{
return Store.ListInvalidAsync(count, offset, cancellationToken);
}
/// <summary> /// <summary>
/// Redeems a token. /// Redeems a token.
/// </summary> /// </summary>
@ -533,42 +568,42 @@ namespace OpenIddict.Core
} }
/// <summary> /// <summary>
/// Sets the authorization associated with a token. /// Sets the application identifier associated with a token.
/// </summary> /// </summary>
/// <param name="token">The token.</param> /// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with 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> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public virtual async Task SetAuthorizationAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken) public virtual async Task SetApplicationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
{ {
if (token == null) if (token == null)
{ {
throw new ArgumentNullException(nameof(token)); throw new ArgumentNullException(nameof(token));
} }
await Store.SetAuthorizationAsync(token, identifier, cancellationToken); await Store.SetApplicationIdAsync(token, identifier, cancellationToken);
await UpdateAsync(token, cancellationToken); await UpdateAsync(token, cancellationToken);
} }
/// <summary> /// <summary>
/// Sets the client application associated with a token. /// Sets the authorization identifier associated with a token.
/// </summary> /// </summary>
/// <param name="token">The token.</param> /// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the client application.</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> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public virtual async Task SetClientAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken) public virtual async Task SetAuthorizationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
{ {
if (token == null) if (token == null)
{ {
throw new ArgumentNullException(nameof(token)); throw new ArgumentNullException(nameof(token));
} }
await Store.SetClientAsync(token, identifier, cancellationToken); await Store.SetAuthorizationIdAsync(token, identifier, cancellationToken);
await UpdateAsync(token, cancellationToken); await UpdateAsync(token, cancellationToken);
} }

35
src/OpenIddict.Core/Stores/IOpenIddictAuthorizationStore.cs

@ -94,6 +94,17 @@ namespace OpenIddict.Core
/// </returns> /// </returns>
Task<TAuthorization> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken); Task<TAuthorization> FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken);
/// <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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the application identifier associated with the authorization.
/// </returns>
Task<string> GetApplicationIdAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Executes the specified query. /// Executes the specified query.
/// </summary> /// </summary>
@ -174,6 +185,30 @@ namespace OpenIddict.Core
/// </returns> /// </returns>
Task<ImmutableArray<TResult>> ListAsync<TResult>([NotNull] Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken); Task<ImmutableArray<TResult>> ListAsync<TResult>([NotNull] Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary>
/// Lists the ad-hoc authorizations that are marked as invalid or have no
/// valid token attached and that can be safely removed from the database.
/// </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<TAuthorization>> ListInvalidAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken);
/// <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] TAuthorization authorization, [CanBeNull] string identifier, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Sets the status associated with an authorization. /// Sets the status associated with an authorization.
/// </summary> /// </summary>

36
src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs

@ -113,6 +113,17 @@ namespace OpenIddict.Core
/// </returns> /// </returns>
Task<ImmutableArray<TToken>> FindBySubjectAsync([NotNull] string subject, CancellationToken cancellationToken); Task<ImmutableArray<TToken>> FindBySubjectAsync([NotNull] string subject, CancellationToken cancellationToken);
/// <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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the application identifier associated with the token.
/// </returns>
Task<string> GetApplicationIdAsync([NotNull] TToken token, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Executes the specified query. /// Executes the specified query.
/// </summary> /// </summary>
@ -249,26 +260,39 @@ namespace OpenIddict.Core
Task<ImmutableArray<TResult>> ListAsync<TResult>([NotNull] Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken); Task<ImmutableArray<TResult>> ListAsync<TResult>([NotNull] Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Sets the authorization associated with a token. /// Lists the tokens that are marked as expired or invalid
/// and that can be safely removed from the database.
/// </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<TToken>> ListInvalidAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken);
/// <summary>
/// Sets the application identifier associated with a token.
/// </summary> /// </summary>
/// <param name="token">The token.</param> /// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with 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> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
Task SetAuthorizationAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken); Task SetApplicationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Sets the client application associated with a token. /// Sets the authorization identifier associated with a token.
/// </summary> /// </summary>
/// <param name="token">The token.</param> /// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the client application.</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> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
Task SetClientAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken); Task SetAuthorizationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Sets the expiration date associated with a token. /// Sets the expiration date associated with a token.

78
src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs

@ -136,6 +136,35 @@ namespace OpenIddict.Core
return GetAsync(authorizations => authorizations.Where(authorization => authorization.Id.Equals(key)), cancellationToken); return GetAsync(authorizations => authorizations.Where(authorization => authorization.Id.Equals(key)), cancellationToken);
} }
/// <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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the application identifier associated with the authorization.
/// </returns>
public virtual async Task<string> GetApplicationIdAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization == null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (authorization.Application != null)
{
return ConvertIdentifierToString(authorization.Application.Id);
}
var key = await GetAsync(authorizations =>
from element in authorizations
where element.Id.Equals(authorization.Id)
select element.Application.Id, cancellationToken);
return ConvertIdentifierToString(key);
}
/// <summary> /// <summary>
/// Executes the specified query. /// Executes the specified query.
/// </summary> /// </summary>
@ -263,6 +292,55 @@ namespace OpenIddict.Core
/// </returns> /// </returns>
public abstract Task<ImmutableArray<TResult>> ListAsync<TResult>([NotNull] Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken); public abstract Task<ImmutableArray<TResult>> ListAsync<TResult>([NotNull] Func<IQueryable<TAuthorization>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary>
/// Lists the ad-hoc authorizations that are marked as invalid or have no
/// valid token attached and that can be safely removed from the database.
/// </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>
public virtual Task<ImmutableArray<TAuthorization>> ListInvalidAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken)
{
IQueryable<TAuthorization> Query(IQueryable<TAuthorization> authorizations)
{
var query = (from authorization in authorizations
where authorization.Status != OpenIddictConstants.Statuses.Valid ||
(authorization.Type == OpenIddictConstants.AuthorizationTypes.AdHoc &&
!authorization.Tokens.Any(token => token.Status == OpenIddictConstants.Statuses.Valid))
orderby authorization.Id
select authorization).AsQueryable();
if (offset.HasValue)
{
query = query.Skip(offset.Value);
}
if (count.HasValue)
{
query = query.Take(count.Value);
}
return query;
}
return ListAsync(Query, cancellationToken);
}
/// <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>
public abstract Task SetApplicationIdAsync([NotNull] TAuthorization authorization, [CanBeNull] string identifier, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Sets the status associated with an authorization. /// Sets the status associated with an authorization.
/// </summary> /// </summary>

74
src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs

@ -174,6 +174,35 @@ namespace OpenIddict.Core
/// </returns> /// </returns>
public abstract Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken); public abstract Task<TResult> GetAsync<TResult>([NotNull] Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the application identifier associated with the token.
/// </returns>
public virtual async Task<string> GetApplicationIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
if (token.Application != null)
{
return ConvertIdentifierToString(token.Application.Id);
}
var key = await GetAsync(tokens =>
from element in tokens
where element.Id.Equals(token.Id)
select element.Application.Id, cancellationToken);
return ConvertIdentifierToString(key);
}
/// <summary> /// <summary>
/// Retrieves the optional authorization identifier associated with a token. /// Retrieves the optional authorization identifier associated with a token.
/// </summary> /// </summary>
@ -400,7 +429,44 @@ namespace OpenIddict.Core
public abstract Task<ImmutableArray<TResult>> ListAsync<TResult>([NotNull] Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken); public abstract Task<ImmutableArray<TResult>> ListAsync<TResult>([NotNull] Func<IQueryable<TToken>, IQueryable<TResult>> query, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Sets the authorization associated with a token. /// Lists the tokens that are marked as expired or invalid
/// and that can be safely removed from the database.
/// </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>
public virtual Task<ImmutableArray<TToken>> ListInvalidAsync([CanBeNull] int? count, [CanBeNull] int? offset, CancellationToken cancellationToken)
{
IQueryable<TToken> Query(IQueryable<TToken> tokens)
{
var query = (from token in tokens
where token.ExpirationDate < DateTimeOffset.UtcNow ||
token.Status != OpenIddictConstants.Statuses.Valid
orderby token.Id
select token).AsQueryable();
if (offset.HasValue)
{
query = query.Skip(offset.Value);
}
if (count.HasValue)
{
query = query.Take(count.Value);
}
return query;
}
return ListAsync(Query, cancellationToken);
}
/// <summary>
/// Sets the authorization identifier associated with a token.
/// </summary> /// </summary>
/// <param name="token">The token.</param> /// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the authorization.</param> /// <param name="identifier">The unique identifier associated with the authorization.</param>
@ -408,10 +474,10 @@ namespace OpenIddict.Core
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public abstract Task SetAuthorizationAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken); public abstract Task SetAuthorizationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Sets the client application associated with a token. /// Sets the application identifier associated with a token.
/// </summary> /// </summary>
/// <param name="token">The token.</param> /// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the client application.</param> /// <param name="identifier">The unique identifier associated with the client application.</param>
@ -419,7 +485,7 @@ namespace OpenIddict.Core
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public abstract Task SetClientAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken); public abstract Task SetApplicationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Sets the expiration date associated with a token. /// Sets the expiration date associated with a token.

6
src/OpenIddict.EntityFramework/OpenIddictExtensions.cs

@ -210,7 +210,8 @@ namespace Microsoft.Extensions.DependencyInjection
builder.Entity<TApplication>() builder.Entity<TApplication>()
.HasMany(application => application.Tokens) .HasMany(application => application.Tokens)
.WithOptional(token => token.Application) .WithOptional(token => token.Application)
.Map(association => association.MapKey("ApplicationId")); .Map(association => association.MapKey("ApplicationId"))
.WillCascadeOnDelete();
builder.Entity<TApplication>() builder.Entity<TApplication>()
.ToTable("OpenIddictApplications"); .ToTable("OpenIddictApplications");
@ -240,7 +241,8 @@ namespace Microsoft.Extensions.DependencyInjection
builder.Entity<TAuthorization>() builder.Entity<TAuthorization>()
.HasMany(application => application.Tokens) .HasMany(application => application.Tokens)
.WithOptional(token => token.Authorization) .WithOptional(token => token.Authorization)
.Map(association => association.MapKey("AuthorizationId")); .Map(association => association.MapKey("AuthorizationId"))
.WillCascadeOnDelete();
builder.Entity<TAuthorization>() builder.Entity<TAuthorization>()
.ToTable("OpenIddictAuthorizations"); .ToTable("OpenIddictAuthorizations");

46
src/OpenIddict.EntityFramework/Stores/OpenIddictApplicationStore.cs

@ -81,6 +81,16 @@ namespace OpenIddict.EntityFramework
/// </summary> /// </summary>
protected DbSet<TApplication> Applications => Context.Set<TApplication>(); protected DbSet<TApplication> Applications => Context.Set<TApplication>();
/// <summary>
/// Gets the database set corresponding to the <typeparamref name="TAuthorization"/> entity.
/// </summary>
protected DbSet<TAuthorization> Authorizations => Context.Set<TAuthorization>();
/// <summary>
/// Gets the database set corresponding to the <typeparamref name="TToken"/> entity.
/// </summary>
protected DbSet<TToken> Tokens => Context.Set<TToken>();
/// <summary> /// <summary>
/// Determines the number of applications that match the specified query. /// Determines the number of applications that match the specified query.
/// </summary> /// </summary>
@ -171,16 +181,48 @@ namespace OpenIddict.EntityFramework
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public override Task DeleteAsync([NotNull] TApplication application, CancellationToken cancellationToken) public override async Task DeleteAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{ {
if (application == null) if (application == null)
{ {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
} }
Task<TAuthorization[]> ListAuthorizationsAsync()
{
return (from authorization in Authorizations.Include(authorization => authorization.Tokens)
where authorization.Application.Id.Equals(application.Id)
select authorization).ToArrayAsync(cancellationToken);
}
Task<TToken[]> ListTokensAsync()
{
return (from token in Tokens
where token.Application.Id.Equals(application.Id)
select token).ToArrayAsync(cancellationToken);
}
// Remove all the authorizations associated with the application and
// the tokens attached to these implicit or explicit authorizations.
foreach (var authorization in await ListAuthorizationsAsync())
{
foreach (var token in authorization.Tokens)
{
Tokens.Remove(token);
}
Authorizations.Remove(authorization);
}
// Remove all the tokens associated with the application.
foreach (var token in await ListTokensAsync())
{
Tokens.Remove(token);
}
Applications.Remove(application); Applications.Remove(application);
return Context.SaveChangesAsync(cancellationToken); await Context.SaveChangesAsync(cancellationToken);
} }
/// <summary> /// <summary>

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

@ -86,6 +86,11 @@ namespace OpenIddict.EntityFramework
/// </summary> /// </summary>
protected DbSet<TAuthorization> Authorizations => Context.Set<TAuthorization>(); protected DbSet<TAuthorization> Authorizations => Context.Set<TAuthorization>();
/// <summary>
/// Gets the database set corresponding to the <typeparamref name="TToken"/> entity.
/// </summary>
protected DbSet<TToken> Tokens => Context.Set<TToken>();
/// <summary> /// <summary>
/// Determines the number of authorizations that match the specified query. /// Determines the number of authorizations that match the specified query.
/// </summary> /// </summary>
@ -178,16 +183,29 @@ namespace OpenIddict.EntityFramework
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public override Task DeleteAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) public override async Task DeleteAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
{ {
if (authorization == null) if (authorization == null)
{ {
throw new ArgumentNullException(nameof(authorization)); throw new ArgumentNullException(nameof(authorization));
} }
Task<TToken[]> ListTokensAsync()
{
return (from token in Tokens
where token.Application.Id.Equals(authorization.Id)
select token).ToArrayAsync(cancellationToken);
}
// Remove all the tokens associated with the application.
foreach (var token in await ListTokensAsync())
{
Tokens.Remove(token);
}
Authorizations.Remove(authorization); Authorizations.Remove(authorization);
return Context.SaveChangesAsync(cancellationToken); await Context.SaveChangesAsync(cancellationToken);
} }
/// <summary> /// <summary>
@ -209,6 +227,38 @@ namespace OpenIddict.EntityFramework
return Authorizations.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier)); return Authorizations.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier));
} }
/// <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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the application identifier associated with the authorization.
/// </returns>
public override async Task<string> GetApplicationIdAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
{
if (authorization == null)
{
throw new ArgumentNullException(nameof(authorization));
}
// If the application is not attached to the authorization instance (which is expected
// if the token was retrieved using the default FindBy*Async APIs as they don't
// eagerly load the application from the database), try to load it manually.
if (authorization.Application == null)
{
return ConvertIdentifierToString(
await Context.Entry(authorization)
.Reference(entry => entry.Application)
.Query()
.Select(application => application.Id)
.FirstOrDefaultAsync());
}
return ConvertIdentifierToString(authorization.Application.Id);
}
/// <summary> /// <summary>
/// Executes the specified query. /// Executes the specified query.
/// </summary> /// </summary>
@ -249,6 +299,47 @@ namespace OpenIddict.EntityFramework
return ImmutableArray.Create(await query.Invoke(Authorizations).ToArrayAsync(cancellationToken)); return ImmutableArray.Create(await query.Invoke(Authorizations).ToArrayAsync(cancellationToken));
} }
/// <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>
public override async Task SetApplicationIdAsync([NotNull] TAuthorization authorization, [CanBeNull] string identifier, CancellationToken cancellationToken)
{
if (authorization == null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (!string.IsNullOrEmpty(identifier))
{
var application = await Applications.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier));
if (application == null)
{
throw new InvalidOperationException("The application associated with the authorization cannot be found.");
}
authorization.Application = application;
}
else
{
var key = await GetIdAsync(authorization, cancellationToken);
// Try to retrieve the application associated with the authorization.
// If none can be found, assume that no application is attached.
var application = await Applications.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key)));
if (application != null)
{
application.Authorizations.Remove(authorization);
}
}
}
/// <summary> /// <summary>
/// Updates an existing authorization. /// Updates an existing authorization.
/// </summary> /// </summary>

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

@ -223,6 +223,38 @@ namespace OpenIddict.EntityFramework
return Tokens.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier)); return Tokens.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier));
} }
/// <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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the application identifier associated with the token.
/// </returns>
public override async Task<string> GetApplicationIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
// If the application is not attached to the token instance (which is expected
// if the token was retrieved using the default FindBy*Async APIs as they don't
// eagerly load the application from the database), try to load it manually.
if (token.Application == null)
{
return ConvertIdentifierToString(
await Context.Entry(token)
.Reference(entry => entry.Application)
.Query()
.Select(application => application.Id)
.FirstOrDefaultAsync());
}
return ConvertIdentifierToString(token.Application.Id);
}
/// <summary> /// <summary>
/// Executes the specified query. /// Executes the specified query.
/// </summary> /// </summary>
@ -243,6 +275,38 @@ namespace OpenIddict.EntityFramework
return query.Invoke(Tokens).SingleOrDefaultAsync(cancellationToken); return query.Invoke(Tokens).SingleOrDefaultAsync(cancellationToken);
} }
/// <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="Task"/> that can be used to monitor the asynchronous operation,
/// whose result returns the authorization identifier associated with the token.
/// </returns>
public override async Task<string> GetAuthorizationIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
// If the authorization is not attached to the token instance (which is expected
// if the token was retrieved using the default FindBy*Async APIs as they don't
// eagerly load the authorization from the database), try to load it manually.
if (token.Authorization == null)
{
return ConvertIdentifierToString(
await Context.Entry(token)
.Reference(entry => entry.Authorization)
.Query()
.Select(authorization => authorization.Id)
.FirstOrDefaultAsync());
}
return ConvertIdentifierToString(token.Authorization.Id);
}
/// <summary> /// <summary>
/// Executes the specified query. /// Executes the specified query.
/// </summary> /// </summary>
@ -264,15 +328,15 @@ namespace OpenIddict.EntityFramework
} }
/// <summary> /// <summary>
/// Sets the authorization associated with a token. /// Sets the application identifier associated with a token.
/// </summary> /// </summary>
/// <param name="token">The token.</param> /// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with 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> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public override async Task SetAuthorizationAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken) public override async Task SetApplicationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
{ {
if (token == null) if (token == null)
{ {
@ -281,39 +345,39 @@ namespace OpenIddict.EntityFramework
if (!string.IsNullOrEmpty(identifier)) if (!string.IsNullOrEmpty(identifier))
{ {
var authorization = await Authorizations.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier)); var application = await Applications.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier));
if (authorization == null) if (application == null)
{ {
throw new InvalidOperationException("The authorization associated with the token cannot be found."); throw new InvalidOperationException("The application associated with the token cannot be found.");
} }
token.Authorization = authorization; token.Application = application;
} }
else else
{ {
var key = await GetIdAsync(token, cancellationToken); var key = await GetIdAsync(token, cancellationToken);
// Try to retrieve the authorization associated with the token. // Try to retrieve the application associated with the token.
// If none can be found, assume that no authorization is attached. // If none can be found, assume that no application is attached.
var authorization = await Authorizations.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key))); var application = await Applications.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key)));
if (authorization != null) if (application != null)
{ {
authorization.Tokens.Remove(token); application.Tokens.Remove(token);
} }
} }
} }
/// <summary> /// <summary>
/// Sets the client application associated with a token. /// Sets the authorization identifier associated with a token.
/// </summary> /// </summary>
/// <param name="token">The token.</param> /// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the client application.</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> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public override async Task SetClientAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken) public override async Task SetAuthorizationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
{ {
if (token == null) if (token == null)
{ {
@ -322,25 +386,25 @@ namespace OpenIddict.EntityFramework
if (!string.IsNullOrEmpty(identifier)) if (!string.IsNullOrEmpty(identifier))
{ {
var application = await Applications.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier)); var authorization = await Authorizations.FindAsync(cancellationToken, ConvertIdentifierFromString(identifier));
if (application == null) if (authorization == null)
{ {
throw new InvalidOperationException("The application associated with the token cannot be found."); throw new InvalidOperationException("The authorization associated with the token cannot be found.");
} }
token.Application = application; token.Authorization = authorization;
} }
else else
{ {
var key = await GetIdAsync(token, cancellationToken); var key = await GetIdAsync(token, cancellationToken);
// Try to retrieve the application associated with the token. // Try to retrieve the authorization associated with the token.
// If none can be found, assume that no application is attached. // If none can be found, assume that no authorization is attached.
var application = await Applications.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key))); var authorization = await Authorizations.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key)));
if (application != null) if (authorization != null)
{ {
application.Tokens.Remove(token); authorization.Tokens.Remove(token);
} }
} }
} }

9
src/OpenIddict.EntityFrameworkCore/OpenIddictExtensions.cs

@ -11,6 +11,7 @@ using System.Reflection;
using JetBrains.Annotations; using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.DependencyInjection.Extensions;
using OpenIddict.Core; using OpenIddict.Core;
using OpenIddict.EntityFrameworkCore; using OpenIddict.EntityFrameworkCore;
@ -243,7 +244,8 @@ namespace Microsoft.Extensions.DependencyInjection
entity.HasMany(application => application.Tokens) entity.HasMany(application => application.Tokens)
.WithOne(token => token.Application) .WithOne(token => token.Application)
.HasForeignKey("ApplicationId") .HasForeignKey("ApplicationId")
.IsRequired(required: false); .IsRequired(required: false)
.OnDelete(DeleteBehavior.Cascade);
entity.ToTable("OpenIddictApplications"); entity.ToTable("OpenIddictApplications");
}); });
@ -266,10 +268,11 @@ namespace Microsoft.Extensions.DependencyInjection
entity.Property(authorization => authorization.Type) entity.Property(authorization => authorization.Type)
.IsRequired(); .IsRequired();
entity.HasMany(application => application.Tokens) entity.HasMany(authorization => authorization.Tokens)
.WithOne(token => token.Authorization) .WithOne(token => token.Authorization)
.HasForeignKey("AuthorizationId") .HasForeignKey("AuthorizationId")
.IsRequired(required: false); .IsRequired(required: false)
.OnDelete(DeleteBehavior.Cascade);
entity.ToTable("OpenIddictAuthorizations"); entity.ToTable("OpenIddictAuthorizations");
}); });

46
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictApplicationStore.cs

@ -81,6 +81,16 @@ namespace OpenIddict.EntityFrameworkCore
/// </summary> /// </summary>
protected DbSet<TApplication> Applications => Context.Set<TApplication>(); protected DbSet<TApplication> Applications => Context.Set<TApplication>();
/// <summary>
/// Gets the database set corresponding to the <typeparamref name="TAuthorization"/> entity.
/// </summary>
protected DbSet<TAuthorization> Authorizations => Context.Set<TAuthorization>();
/// <summary>
/// Gets the database set corresponding to the <typeparamref name="TToken"/> entity.
/// </summary>
protected DbSet<TToken> Tokens => Context.Set<TToken>();
/// <summary> /// <summary>
/// Determines the number of applications that match the specified query. /// Determines the number of applications that match the specified query.
/// </summary> /// </summary>
@ -171,16 +181,48 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public override Task DeleteAsync([NotNull] TApplication application, CancellationToken cancellationToken) public override async Task DeleteAsync([NotNull] TApplication application, CancellationToken cancellationToken)
{ {
if (application == null) if (application == null)
{ {
throw new ArgumentNullException(nameof(application)); throw new ArgumentNullException(nameof(application));
} }
Task<TAuthorization[]> ListAuthorizationsAsync()
{
return (from authorization in Authorizations.Include(authorization => authorization.Tokens)
where authorization.Application.Id.Equals(application.Id)
select authorization).ToArrayAsync(cancellationToken);
}
Task<TToken[]> ListTokensAsync()
{
return (from token in Tokens
where token.Application.Id.Equals(application.Id)
select token).ToArrayAsync(cancellationToken);
}
// Remove all the authorizations associated with the application and
// the tokens attached to these implicit or explicit authorizations.
foreach (var authorization in await ListAuthorizationsAsync())
{
foreach (var token in authorization.Tokens)
{
Context.Remove(token);
}
Context.Remove(authorization);
}
// Remove all the tokens associated with the application.
foreach (var token in await ListTokensAsync())
{
Context.Remove(token);
}
Context.Remove(application); Context.Remove(application);
return Context.SaveChangesAsync(cancellationToken); await Context.SaveChangesAsync(cancellationToken);
} }
/// <summary> /// <summary>

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

@ -86,6 +86,11 @@ namespace OpenIddict.EntityFrameworkCore
/// </summary> /// </summary>
protected DbSet<TAuthorization> Authorizations => Context.Set<TAuthorization>(); protected DbSet<TAuthorization> Authorizations => Context.Set<TAuthorization>();
/// <summary>
/// Gets the database set corresponding to the <typeparamref name="TToken"/> entity.
/// </summary>
protected DbSet<TToken> Tokens => Context.Set<TToken>();
/// <summary> /// <summary>
/// Determines the number of authorizations that match the specified query. /// Determines the number of authorizations that match the specified query.
/// </summary> /// </summary>
@ -180,16 +185,29 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public override Task DeleteAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) public override async Task DeleteAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
{ {
if (authorization == null) if (authorization == null)
{ {
throw new ArgumentNullException(nameof(authorization)); throw new ArgumentNullException(nameof(authorization));
} }
Task<TToken[]> ListTokensAsync()
{
return (from token in Tokens
where token.Application.Id.Equals(authorization.Id)
select token).ToArrayAsync(cancellationToken);
}
// Remove all the tokens associated with the application.
foreach (var token in await ListTokensAsync())
{
Context.Remove(token);
}
Context.Remove(authorization); Context.Remove(authorization);
return Context.SaveChangesAsync(cancellationToken); await Context.SaveChangesAsync(cancellationToken);
} }
/// <summary> /// <summary>
@ -232,6 +250,49 @@ namespace OpenIddict.EntityFrameworkCore
return ImmutableArray.Create(await query.Invoke(Authorizations).ToArrayAsync(cancellationToken)); return ImmutableArray.Create(await query.Invoke(Authorizations).ToArrayAsync(cancellationToken));
} }
/// <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>
public override async Task SetApplicationIdAsync([NotNull] TAuthorization authorization, [CanBeNull] string identifier, CancellationToken cancellationToken)
{
if (authorization == null)
{
throw new ArgumentNullException(nameof(authorization));
}
if (!string.IsNullOrEmpty(identifier))
{
var key = ConvertIdentifierFromString(identifier);
var application = await Applications.SingleOrDefaultAsync(element => element.Id.Equals(key), cancellationToken);
if (application == null)
{
throw new InvalidOperationException("The application associated with the authorization cannot be found.");
}
authorization.Application = application;
}
else
{
var key = await GetIdAsync(authorization, cancellationToken);
// Try to retrieve the application associated with the authorization.
// If none can be found, assume that no application is attached.
var application = await Applications.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key)));
if (application != null)
{
application.Authorizations.Remove(authorization);
}
}
}
/// <summary> /// <summary>
/// Updates an existing authorization. /// Updates an existing authorization.
/// </summary> /// </summary>

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

@ -249,15 +249,15 @@ namespace OpenIddict.EntityFrameworkCore
} }
/// <summary> /// <summary>
/// Sets the authorization associated with a token. /// Sets the application identifier associated with a token.
/// </summary> /// </summary>
/// <param name="token">The token.</param> /// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with 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> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public override async Task SetAuthorizationAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken) public override async Task SetApplicationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
{ {
if (token == null) if (token == null)
{ {
@ -268,39 +268,39 @@ namespace OpenIddict.EntityFrameworkCore
{ {
var key = ConvertIdentifierFromString(identifier); var key = ConvertIdentifierFromString(identifier);
var authorization = await Authorizations.SingleOrDefaultAsync(element => element.Id.Equals(key)); var application = await Applications.SingleOrDefaultAsync(element => element.Id.Equals(key), cancellationToken);
if (authorization == null) if (application == null)
{ {
throw new InvalidOperationException("The authorization associated with the token cannot be found."); throw new InvalidOperationException("The application associated with the token cannot be found.");
} }
token.Authorization = authorization; token.Application = application;
} }
else else
{ {
var key = await GetIdAsync(token, cancellationToken); var key = await GetIdAsync(token, cancellationToken);
// Try to retrieve the authorization associated with the token. // Try to retrieve the application associated with the token.
// If none can be found, assume that no authorization is attached. // If none can be found, assume that no application is attached.
var authorization = await Authorizations.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key))); var application = await Applications.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key)));
if (authorization != null) if (application != null)
{ {
authorization.Tokens.Remove(token); application.Tokens.Remove(token);
} }
} }
} }
/// <summary> /// <summary>
/// Sets the client application associated with a token. /// Sets the authorization identifier associated with a token.
/// </summary> /// </summary>
/// <param name="token">The token.</param> /// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the client application.</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> /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public override async Task SetClientAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken) public override async Task SetAuthorizationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
{ {
if (token == null) if (token == null)
{ {
@ -311,25 +311,25 @@ namespace OpenIddict.EntityFrameworkCore
{ {
var key = ConvertIdentifierFromString(identifier); var key = ConvertIdentifierFromString(identifier);
var application = await Applications.SingleOrDefaultAsync(element => element.Id.Equals(key)); var authorization = await Authorizations.SingleOrDefaultAsync(element => element.Id.Equals(key), cancellationToken);
if (application == null) if (authorization == null)
{ {
throw new InvalidOperationException("The application associated with the token cannot be found."); throw new InvalidOperationException("The authorization associated with the token cannot be found.");
} }
token.Application = application; token.Authorization = authorization;
} }
else else
{ {
var key = await GetIdAsync(token, cancellationToken); var key = await GetIdAsync(token, cancellationToken);
// Try to retrieve the application associated with the token. // Try to retrieve the authorization associated with the token.
// If none can be found, assume that no application is attached. // If none can be found, assume that no authorization is attached.
var application = await Applications.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key))); var authorization = await Authorizations.FirstOrDefaultAsync(element => element.Tokens.Any(t => t.Id.Equals(key)));
if (application != null) if (authorization != null)
{ {
application.Tokens.Remove(token); authorization.Tokens.Remove(token);
} }
} }
} }

7
src/OpenIddict/OpenIddictProvider.Helpers.cs

@ -206,12 +206,11 @@ namespace OpenIddict
ticket.SetTokenId(identifier); ticket.SetTokenId(identifier);
// Dynamically set the creation and expiration dates. // Dynamically set the creation and expiration dates.
ticket.Properties.IssuedUtc = await tokens.GetCreationDateAsync(token, context.RequestAborted); ticket.Properties.IssuedUtc = descriptor.CreationDate;
ticket.Properties.ExpiresUtc = await tokens.GetExpirationDateAsync(token, context.RequestAborted); ticket.Properties.ExpiresUtc = descriptor.ExpirationDate;
// Restore the authorization identifier using the identifier attached with the database entry. // Restore the authorization identifier using the identifier attached with the database entry.
ticket.SetProperty(OpenIddictConstants.Properties.AuthorizationId, ticket.SetProperty(OpenIddictConstants.Properties.AuthorizationId, descriptor.AuthorizationId);
await tokens.GetAuthorizationIdAsync(token, context.RequestAborted));
if (!string.IsNullOrEmpty(result)) if (!string.IsNullOrEmpty(result))
{ {

4
src/OpenIddict/OpenIddictProvider.Signin.cs

@ -29,8 +29,8 @@ namespace OpenIddict
// the OpenID Connect server middleware allows creating authentication tickets // the OpenID Connect server middleware allows creating authentication tickets
// that are completely disconnected from the original code or refresh token ticket. // that are completely disconnected from the original code or refresh token ticket.
// This scenario is deliberately not supported in OpenIddict and all the tickets // This scenario is deliberately not supported in OpenIddict and all the tickets
// must be linked. To ensure the properties are preserved from an authorization code // must be linked. To ensure the properties are flowed from the authorization code
// or a refresh token to the new ticket, they are manually restored if necessary. // or the refresh token to the new ticket, they are manually restored if necessary.
// Retrieve the original authentication ticket from the request properties. // Retrieve the original authentication ticket from the request properties.
var ticket = context.Request.GetProperty<AuthenticationTicket>( var ticket = context.Request.GetProperty<AuthenticationTicket>(

Loading…
Cancel
Save