Browse Source

Introduce new RevokeByApplicationIdAsync()/RevokeBySubjectAsync() APIs in the authorization/token managers/stores

pull/2197/head
Kévin Chalet 1 year ago
parent
commit
fcc0ddd99c
  1. 16
      src/OpenIddict.Abstractions/Managers/IOpenIddictAuthorizationManager.cs
  2. 16
      src/OpenIddict.Abstractions/Managers/IOpenIddictTokenManager.cs
  3. 16
      src/OpenIddict.Abstractions/Stores/IOpenIddictAuthorizationStore.cs
  4. 16
      src/OpenIddict.Abstractions/Stores/IOpenIddictTokenStore.cs
  5. 40
      src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
  6. 40
      src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
  7. 92
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs
  8. 92
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkTokenStore.cs
  9. 118
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreAuthorizationStore.cs
  10. 118
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreTokenStore.cs
  11. 36
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbAuthorizationStore.cs
  12. 36
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbTokenStore.cs

16
src/OpenIddict.Abstractions/Managers/IOpenIddictAuthorizationManager.cs

@ -394,6 +394,22 @@ public interface IOpenIddictAuthorizationManager
/// <returns>The number of authorizations that were removed.</returns>
ValueTask<long> PruneAsync(DateTimeOffset threshold, CancellationToken cancellationToken = default);
/// <summary>
/// Revokes all the authorizations associated with the specified application identifier.
/// </summary>
/// <param name="identifier">The application identifier associated with the authorizations.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The number of authorizations associated with the specified application that were marked as revoked.</returns>
ValueTask<long> RevokeByApplicationIdAsync(string identifier, CancellationToken cancellationToken = default);
/// <summary>
/// Revokes all the authorizations associated with the specified subject.
/// </summary>
/// <param name="subject">The subject associated with the authorizations.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The number of authorizations associated with the specified subject that were marked as revoked.</returns>
ValueTask<long> RevokeBySubjectAsync(string subject, CancellationToken cancellationToken = default);
/// <summary>
/// Tries to revoke an authorization.
/// </summary>

16
src/OpenIddict.Abstractions/Managers/IOpenIddictTokenManager.cs

@ -409,6 +409,14 @@ public interface IOpenIddictTokenManager
/// <returns>The number of tokens that were removed.</returns>
ValueTask<long> PruneAsync(DateTimeOffset threshold, CancellationToken cancellationToken = default);
/// <summary>
/// Revokes all the tokens associated with 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>The number of tokens associated with the specified application that were marked as revoked.</returns>
ValueTask<long> RevokeByApplicationIdAsync(string identifier, CancellationToken cancellationToken = default);
/// <summary>
/// Revokes all the tokens associated with the specified authorization identifier.
/// </summary>
@ -417,6 +425,14 @@ public interface IOpenIddictTokenManager
/// <returns>The number of tokens associated with the specified authorization that were marked as revoked.</returns>
ValueTask<long> RevokeByAuthorizationIdAsync(string identifier, CancellationToken cancellationToken = default);
/// <summary>
/// Revokes all the tokens associated with 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>The number of tokens associated with the specified subject that were marked as revoked.</returns>
ValueTask<long> RevokeBySubjectAsync(string subject, CancellationToken cancellationToken = default);
/// <summary>
/// Tries to redeem a token.
/// </summary>

16
src/OpenIddict.Abstractions/Stores/IOpenIddictAuthorizationStore.cs

@ -279,6 +279,22 @@ public interface IOpenIddictAuthorizationStore<TAuthorization> where TAuthorizat
/// <returns>The number of authorizations that were removed.</returns>
ValueTask<long> PruneAsync(DateTimeOffset threshold, CancellationToken cancellationToken);
/// <summary>
/// Revokes all the authorizations associated with the specified application identifier.
/// </summary>
/// <param name="identifier">The application identifier associated with the authorizations.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The number of authorizations associated with the specified application that were marked as revoked.</returns>
ValueTask<long> RevokeByApplicationIdAsync(string identifier, CancellationToken cancellationToken = default);
/// <summary>
/// Revokes all the authorizations associated with the specified subject.
/// </summary>
/// <param name="subject">The subject associated with the authorizations.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The number of authorizations associated with the specified subject that were marked as revoked.</returns>
ValueTask<long> RevokeBySubjectAsync(string subject, CancellationToken cancellationToken = default);
/// <summary>
/// Sets the application identifier associated with an authorization.
/// </summary>

16
src/OpenIddict.Abstractions/Stores/IOpenIddictTokenStore.cs

@ -326,6 +326,14 @@ public interface IOpenIddictTokenStore<TToken> where TToken : class
/// <returns>The number of tokens that were removed.</returns>
ValueTask<long> PruneAsync(DateTimeOffset threshold, CancellationToken cancellationToken);
/// <summary>
/// Revokes all the tokens associated with 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>The number of tokens associated with the specified application that were marked as revoked.</returns>
ValueTask<long> RevokeByApplicationIdAsync(string identifier, CancellationToken cancellationToken = default);
/// <summary>
/// Revokes all the tokens associated with the specified authorization identifier.
/// </summary>
@ -334,6 +342,14 @@ public interface IOpenIddictTokenStore<TToken> where TToken : class
/// <returns>The number of tokens associated with the specified authorization that were marked as revoked.</returns>
ValueTask<long> RevokeByAuthorizationIdAsync(string identifier, CancellationToken cancellationToken);
/// <summary>
/// Revokes all the tokens associated with 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>The number of tokens associated with the specified subject that were marked as revoked.</returns>
ValueTask<long> RevokeBySubjectAsync(string subject, CancellationToken cancellationToken = default);
/// <summary>
/// Sets the application identifier associated with a token.
/// </summary>

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

@ -1028,6 +1028,38 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
public virtual ValueTask<long> PruneAsync(DateTimeOffset threshold, CancellationToken cancellationToken = default)
=> Store.PruneAsync(threshold, cancellationToken);
/// <summary>
/// Revokes all the authorizations associated with the specified application identifier.
/// </summary>
/// <param name="identifier">The application identifier associated with the authorizations.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The number of authorizations associated with the specified application that were marked as revoked.</returns>
public virtual ValueTask<long> RevokeByApplicationIdAsync(string identifier, CancellationToken cancellationToken = default)
{
if (string.IsNullOrEmpty(identifier))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(identifier));
}
return Store.RevokeByApplicationIdAsync(identifier, cancellationToken);
}
/// <summary>
/// Revokes all the authorizations associated with the specified subject.
/// </summary>
/// <param name="subject">The subject associated with the authorizations.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The number of authorizations associated with the specified subject that were marked as revoked.</returns>
public virtual ValueTask<long> RevokeBySubjectAsync(string subject, CancellationToken cancellationToken = default)
{
if (string.IsNullOrEmpty(subject))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(subject));
}
return Store.RevokeBySubjectAsync(subject, cancellationToken);
}
/// <summary>
/// Tries to revoke an authorization.
/// </summary>
@ -1337,6 +1369,14 @@ public class OpenIddictAuthorizationManager<TAuthorization> : IOpenIddictAuthori
ValueTask<long> IOpenIddictAuthorizationManager.PruneAsync(DateTimeOffset threshold, CancellationToken cancellationToken)
=> PruneAsync(threshold, cancellationToken);
/// <inheritdoc/>
ValueTask<long> IOpenIddictAuthorizationManager.RevokeByApplicationIdAsync(string identifier, CancellationToken cancellationToken)
=> RevokeByApplicationIdAsync(identifier, cancellationToken);
/// <inheritdoc/>
ValueTask<long> IOpenIddictAuthorizationManager.RevokeBySubjectAsync(string subject, CancellationToken cancellationToken)
=> RevokeBySubjectAsync(subject, cancellationToken);
/// <inheritdoc/>
ValueTask<bool> IOpenIddictAuthorizationManager.TryRevokeAsync(object authorization, CancellationToken cancellationToken)
=> TryRevokeAsync((TAuthorization) authorization, cancellationToken);

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

@ -1055,6 +1055,22 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
public virtual ValueTask<long> PruneAsync(DateTimeOffset threshold, CancellationToken cancellationToken = default)
=> Store.PruneAsync(threshold, cancellationToken);
/// <summary>
/// Revokes all the tokens associated with 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>The number of tokens associated with the specified application that were marked as revoked.</returns>
public virtual ValueTask<long> RevokeByApplicationIdAsync(string identifier, CancellationToken cancellationToken = default)
{
if (string.IsNullOrEmpty(identifier))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(identifier));
}
return Store.RevokeByApplicationIdAsync(identifier, cancellationToken);
}
/// <summary>
/// Revokes all the tokens associated with the specified authorization identifier.
/// </summary>
@ -1071,6 +1087,22 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
return Store.RevokeByAuthorizationIdAsync(identifier, cancellationToken);
}
/// <summary>
/// Revokes all the tokens associated with 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>The number of tokens associated with the specified subject that were marked as revoked.</returns>
public virtual ValueTask<long> RevokeBySubjectAsync(string subject, CancellationToken cancellationToken = default)
{
if (string.IsNullOrEmpty(subject))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(subject));
}
return Store.RevokeBySubjectAsync(subject, cancellationToken);
}
/// <summary>
/// Tries to redeem a token.
/// </summary>
@ -1501,10 +1533,18 @@ public class OpenIddictTokenManager<TToken> : IOpenIddictTokenManager where TTok
ValueTask<long> IOpenIddictTokenManager.PruneAsync(DateTimeOffset threshold, CancellationToken cancellationToken)
=> PruneAsync(threshold, cancellationToken);
/// <inheritdoc/>
ValueTask<long> IOpenIddictTokenManager.RevokeByApplicationIdAsync(string identifier, CancellationToken cancellationToken)
=> RevokeByApplicationIdAsync(identifier, cancellationToken);
/// <inheritdoc/>
ValueTask<long> IOpenIddictTokenManager.RevokeByAuthorizationIdAsync(string identifier, CancellationToken cancellationToken)
=> RevokeByAuthorizationIdAsync(identifier, cancellationToken);
/// <inheritdoc/>
ValueTask<long> IOpenIddictTokenManager.RevokeBySubjectAsync(string subject, CancellationToken cancellationToken)
=> RevokeBySubjectAsync(subject, cancellationToken);
/// <inheritdoc/>
ValueTask<bool> IOpenIddictTokenManager.TryRedeemAsync(object token, CancellationToken cancellationToken)
=> TryRedeemAsync((TToken) token, cancellationToken);

92
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs

@ -658,6 +658,98 @@ public class OpenIddictEntityFrameworkAuthorizationStore<TAuthorization, TApplic
return result;
}
/// <inheritdoc/>
public virtual async ValueTask<long> RevokeByApplicationIdAsync(string identifier, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(identifier))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(identifier));
}
var key = ConvertIdentifierFromString(identifier);
List<Exception>? exceptions = null;
var result = 0L;
foreach (var authorization in await (from authorization in Authorizations
where authorization.Application!.Id!.Equals(key)
select authorization).ToListAsync(cancellationToken))
{
authorization.Status = Statuses.Revoked;
try
{
await Context.SaveChangesAsync(cancellationToken);
}
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
Context.Entry(authorization).State = EntityState.Unchanged;
exceptions ??= [];
exceptions.Add(exception);
continue;
}
result++;
}
if (exceptions is not null)
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
return result;
}
/// <inheritdoc/>
public virtual async ValueTask<long> RevokeBySubjectAsync(string subject, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(subject))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(subject));
}
List<Exception>? exceptions = null;
var result = 0L;
foreach (var authorization in await (from authorization in Authorizations
where authorization.Subject == subject
select authorization).ToListAsync(cancellationToken))
{
authorization.Status = Statuses.Revoked;
try
{
await Context.SaveChangesAsync(cancellationToken);
}
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
Context.Entry(authorization).State = EntityState.Unchanged;
exceptions ??= [];
exceptions.Add(exception);
continue;
}
result++;
}
if (exceptions is not null)
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
return result;
}
/// <inheritdoc/>
public virtual async ValueTask SetApplicationIdAsync(TAuthorization authorization,
string? identifier, CancellationToken cancellationToken)

92
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkTokenStore.cs

@ -659,6 +659,53 @@ public class OpenIddictEntityFrameworkTokenStore<TToken, TApplication, TAuthoriz
return result;
}
/// <inheritdoc/>
public virtual async ValueTask<long> RevokeByApplicationIdAsync(string identifier, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(identifier))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(identifier));
}
var key = ConvertIdentifierFromString(identifier);
List<Exception>? exceptions = null;
var result = 0L;
foreach (var token in await (from token in Tokens
where token.Application!.Id!.Equals(key)
select token).ToListAsync(cancellationToken))
{
token.Status = Statuses.Revoked;
try
{
await Context.SaveChangesAsync(cancellationToken);
}
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
Context.Entry(token).State = EntityState.Unchanged;
exceptions ??= [];
exceptions.Add(exception);
continue;
}
result++;
}
if (exceptions is not null)
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
return result;
}
/// <inheritdoc/>
public virtual async ValueTask<long> RevokeByAuthorizationIdAsync(string identifier, CancellationToken cancellationToken)
{
@ -706,6 +753,51 @@ public class OpenIddictEntityFrameworkTokenStore<TToken, TApplication, TAuthoriz
return result;
}
/// <inheritdoc/>
public virtual async ValueTask<long> RevokeBySubjectAsync(string subject, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(subject))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(subject));
}
List<Exception>? exceptions = null;
var result = 0L;
foreach (var token in await (from token in Tokens
where token.Subject == subject
select token).ToListAsync(cancellationToken))
{
token.Status = Statuses.Revoked;
try
{
await Context.SaveChangesAsync(cancellationToken);
}
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
Context.Entry(token).State = EntityState.Unchanged;
exceptions ??= [];
exceptions.Add(exception);
continue;
}
result++;
}
if (exceptions is not null)
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
return result;
}
/// <inheritdoc/>
public virtual async ValueTask SetApplicationIdAsync(TToken token, string? identifier, CancellationToken cancellationToken)
{

118
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreAuthorizationStore.cs

@ -799,6 +799,124 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<TAuthorization, TAp
return result;
}
/// <inheritdoc/>
public virtual async ValueTask<long> RevokeByApplicationIdAsync(string identifier, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(identifier))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(identifier));
}
var key = ConvertIdentifierFromString(identifier);
#if SUPPORTS_BULK_DBSET_OPERATIONS
if (!Options.CurrentValue.DisableBulkOperations)
{
return await (
from authorization in Authorizations
where authorization.Application!.Id!.Equals(key)
select authorization).ExecuteUpdateAsync(entity => entity.SetProperty(
authorization => authorization.Status, Statuses.Revoked), cancellationToken);
// Note: calling DbContext.SaveChangesAsync() is not necessary
// with bulk update operations as they are executed immediately.
}
#endif
List<Exception>? exceptions = null;
var result = 0L;
foreach (var authorization in await (from authorization in Authorizations
where authorization.Application!.Id!.Equals(key)
select authorization).ToListAsync(cancellationToken))
{
authorization.Status = Statuses.Revoked;
try
{
await Context.SaveChangesAsync(cancellationToken);
}
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
Context.Entry(authorization).State = EntityState.Unchanged;
exceptions ??= [];
exceptions.Add(exception);
continue;
}
result++;
}
if (exceptions is not null)
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
return result;
}
/// <inheritdoc/>
public virtual async ValueTask<long> RevokeBySubjectAsync(string subject, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(subject))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(subject));
}
#if SUPPORTS_BULK_DBSET_OPERATIONS
if (!Options.CurrentValue.DisableBulkOperations)
{
return await (
from authorization in Authorizations
where authorization.Subject == subject
select authorization).ExecuteUpdateAsync(entity => entity.SetProperty(
authorization => authorization.Status, Statuses.Revoked), cancellationToken);
// Note: calling DbContext.SaveChangesAsync() is not necessary
// with bulk update operations as they are executed immediately.
}
#endif
List<Exception>? exceptions = null;
var result = 0L;
foreach (var authorization in await (from authorization in Authorizations
where authorization.Subject == subject
select authorization).ToListAsync(cancellationToken))
{
authorization.Status = Statuses.Revoked;
try
{
await Context.SaveChangesAsync(cancellationToken);
}
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
Context.Entry(authorization).State = EntityState.Unchanged;
exceptions ??= [];
exceptions.Add(exception);
continue;
}
result++;
}
if (exceptions is not null)
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
return result;
}
/// <inheritdoc/>
public virtual async ValueTask SetApplicationIdAsync(TAuthorization authorization,
string? identifier, CancellationToken cancellationToken)

118
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreTokenStore.cs

@ -748,6 +748,66 @@ public class OpenIddictEntityFrameworkCoreTokenStore<TToken, TApplication, TAuth
return result;
}
/// <inheritdoc/>
public virtual async ValueTask<long> RevokeByApplicationIdAsync(string identifier, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(identifier))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(identifier));
}
var key = ConvertIdentifierFromString(identifier);
#if SUPPORTS_BULK_DBSET_OPERATIONS
if (!Options.CurrentValue.DisableBulkOperations)
{
return await (
from token in Tokens
where token.Application!.Id!.Equals(key)
select token).ExecuteUpdateAsync(entity => entity.SetProperty(
token => token.Status, Statuses.Revoked), cancellationToken);
// Note: calling DbContext.SaveChangesAsync() is not necessary
// with bulk update operations as they are executed immediately.
}
#endif
List<Exception>? exceptions = null;
var result = 0L;
foreach (var token in await (from token in Tokens
where token.Application!.Id!.Equals(key)
select token).ToListAsync(cancellationToken))
{
token.Status = Statuses.Revoked;
try
{
await Context.SaveChangesAsync(cancellationToken);
}
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
Context.Entry(token).State = EntityState.Unchanged;
exceptions ??= [];
exceptions.Add(exception);
continue;
}
result++;
}
if (exceptions is not null)
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
return result;
}
/// <inheritdoc/>
public virtual async ValueTask<long> RevokeByAuthorizationIdAsync(string identifier, CancellationToken cancellationToken)
{
@ -808,6 +868,64 @@ public class OpenIddictEntityFrameworkCoreTokenStore<TToken, TApplication, TAuth
return result;
}
/// <inheritdoc/>
public virtual async ValueTask<long> RevokeBySubjectAsync(string subject, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(subject))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(subject));
}
#if SUPPORTS_BULK_DBSET_OPERATIONS
if (!Options.CurrentValue.DisableBulkOperations)
{
return await (
from token in Tokens
where token.Subject == subject
select token).ExecuteUpdateAsync(entity => entity.SetProperty(
token => token.Status, Statuses.Revoked), cancellationToken);
// Note: calling DbContext.SaveChangesAsync() is not necessary
// with bulk update operations as they are executed immediately.
}
#endif
List<Exception>? exceptions = null;
var result = 0L;
foreach (var token in await (from token in Tokens
where token.Subject == subject
select token).ToListAsync(cancellationToken))
{
token.Status = Statuses.Revoked;
try
{
await Context.SaveChangesAsync(cancellationToken);
}
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
Context.Entry(token).State = EntityState.Unchanged;
exceptions ??= [];
exceptions.Add(exception);
continue;
}
result++;
}
if (exceptions is not null)
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
return result;
}
/// <inheritdoc/>
public virtual async ValueTask SetApplicationIdAsync(TToken token, string? identifier, CancellationToken cancellationToken)
{

36
src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbAuthorizationStore.cs

@ -549,6 +549,42 @@ public class OpenIddictMongoDbAuthorizationStore<TAuthorization> : IOpenIddictAu
return result;
}
/// <inheritdoc/>
public virtual async ValueTask<long> RevokeByApplicationIdAsync(string identifier, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(identifier))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(identifier));
}
var database = await Context.GetDatabaseAsync(cancellationToken);
var collection = database.GetCollection<TAuthorization>(Options.CurrentValue.AuthorizationsCollectionName);
return (await collection.UpdateManyAsync(
filter : authorization => authorization.ApplicationId == ObjectId.Parse(identifier),
update : Builders<TAuthorization>.Update.Set(authorization => authorization.Status, Statuses.Revoked),
options : null,
cancellationToken: cancellationToken)).MatchedCount;
}
/// <inheritdoc/>
public virtual async ValueTask<long> RevokeBySubjectAsync(string subject, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(subject))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(subject));
}
var database = await Context.GetDatabaseAsync(cancellationToken);
var collection = database.GetCollection<TAuthorization>(Options.CurrentValue.AuthorizationsCollectionName);
return (await collection.UpdateManyAsync(
filter : authorization => authorization.Subject == subject,
update : Builders<TAuthorization>.Update.Set(authorization => authorization.Status, Statuses.Revoked),
options : null,
cancellationToken: cancellationToken)).MatchedCount;
}
/// <inheritdoc/>
public virtual ValueTask SetApplicationIdAsync(TAuthorization authorization,
string? identifier, CancellationToken cancellationToken)

36
src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbTokenStore.cs

@ -586,6 +586,24 @@ public class OpenIddictMongoDbTokenStore<TToken> : IOpenIddictTokenStore<TToken>
return result;
}
/// <inheritdoc/>
public virtual async ValueTask<long> RevokeByApplicationIdAsync(string identifier, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(identifier))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(identifier));
}
var database = await Context.GetDatabaseAsync(cancellationToken);
var collection = database.GetCollection<TToken>(Options.CurrentValue.TokensCollectionName);
return (await collection.UpdateManyAsync(
filter : token => token.ApplicationId == ObjectId.Parse(identifier),
update : Builders<TToken>.Update.Set(token => token.Status, Statuses.Revoked),
options : null,
cancellationToken: cancellationToken)).MatchedCount;
}
/// <inheritdoc/>
public virtual async ValueTask<long> RevokeByAuthorizationIdAsync(string identifier, CancellationToken cancellationToken)
{
@ -604,6 +622,24 @@ public class OpenIddictMongoDbTokenStore<TToken> : IOpenIddictTokenStore<TToken>
cancellationToken: cancellationToken)).MatchedCount;
}
/// <inheritdoc/>
public virtual async ValueTask<long> RevokeBySubjectAsync(string subject, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(subject))
{
throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(subject));
}
var database = await Context.GetDatabaseAsync(cancellationToken);
var collection = database.GetCollection<TToken>(Options.CurrentValue.TokensCollectionName);
return (await collection.UpdateManyAsync(
filter : token => token.Subject == subject,
update : Builders<TToken>.Update.Set(token => token.Status, Statuses.Revoked),
options : null,
cancellationToken: cancellationToken)).MatchedCount;
}
/// <inheritdoc/>
public virtual ValueTask SetApplicationIdAsync(TToken token, string? identifier, CancellationToken cancellationToken)
{

Loading…
Cancel
Save