diff --git a/src/OpenIddict.Core/Descriptors/OpenIddictTokenDescriptor.cs b/src/OpenIddict.Core/Descriptors/OpenIddictTokenDescriptor.cs
index 370ccd07..53fdb819 100644
--- a/src/OpenIddict.Core/Descriptors/OpenIddictTokenDescriptor.cs
+++ b/src/OpenIddict.Core/Descriptors/OpenIddictTokenDescriptor.cs
@@ -19,11 +19,6 @@ namespace OpenIddict.Core
///
public string AuthorizationId { get; set; }
- ///
- /// Gets or sets the encrypted payload associated with the token.
- ///
- public string Ciphertext { get; set; }
-
///
/// Gets or sets the creation date associated with the token.
///
@@ -35,9 +30,9 @@ namespace OpenIddict.Core
public DateTimeOffset? ExpirationDate { get; set; }
///
- /// Gets or sets the cryptographic hash associated with the token.
+ /// Gets or sets the payload associated with the token.
///
- public string Hash { get; set; }
+ public string Payload { get; set; }
///
/// Gets or sets the optional principal associated with the token.
@@ -52,6 +47,11 @@ namespace OpenIddict.Core
public IDictionary Properties { get; } =
new Dictionary(StringComparer.Ordinal);
+ ///
+ /// Gets or sets the reference identifier associated with the token.
+ ///
+ public string ReferenceId { get; set; }
+
///
/// Gets or sets the status associated with the token.
///
diff --git a/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs b/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
index 46db936f..f469652e 100644
--- a/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
+++ b/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
@@ -7,6 +7,8 @@
using System;
using System.Collections.Immutable;
using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
@@ -213,22 +215,24 @@ namespace OpenIddict.Core
}
///
- /// Retrieves the list of tokens corresponding to the specified hash.
+ /// Retrieves the list of tokens corresponding to the specified reference identifier.
+ /// Note: the reference identifier may be hashed or encrypted for security reasons.
///
- /// The hashed crypto-secure random identifier associated with the tokens.
+ /// The reference identifier associated with the tokens.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the tokens corresponding to the specified hash.
+ /// whose result returns the tokens corresponding to the specified reference identifier.
///
- public virtual Task FindByHashAsync([NotNull] string hash, CancellationToken cancellationToken)
+ public virtual async Task FindByReferenceIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
{
- if (string.IsNullOrEmpty(hash))
+ if (string.IsNullOrEmpty(identifier))
{
- throw new ArgumentException("The hash cannot be null or empty.", nameof(hash));
+ throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
- return Store.FindByHashAsync(hash, cancellationToken);
+ identifier = await ObfuscateReferenceIdAsync(identifier, cancellationToken);
+ return await Store.FindByReferenceIdAsync(identifier, cancellationToken);
}
///
@@ -347,98 +351,100 @@ namespace OpenIddict.Core
}
///
- /// Retrieves the ciphertext associated with a token.
+ /// Retrieves the creation date associated with a token.
///
/// The token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the ciphertext associated with the specified token.
+ /// whose result returns the creation date associated with the specified token.
///
- public virtual Task GetCiphertextAsync([NotNull] TToken token, CancellationToken cancellationToken)
+ public virtual Task GetCreationDateAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
- return Store.GetCiphertextAsync(token, cancellationToken);
+ return Store.GetCreationDateAsync(token, cancellationToken);
}
///
- /// Retrieves the creation date associated with a token.
+ /// Retrieves the expiration date associated with a token.
///
/// The token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the creation date associated with the specified token.
+ /// whose result returns the expiration date associated with the specified token.
///
- public virtual Task GetCreationDateAsync([NotNull] TToken token, CancellationToken cancellationToken)
+ public virtual Task GetExpirationDateAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
- return Store.GetCreationDateAsync(token, cancellationToken);
+ return Store.GetExpirationDateAsync(token, cancellationToken);
}
///
- /// Retrieves the expiration date associated with a token.
+ /// Retrieves the reference identifier associated with a token.
+ /// Note: depending on the manager used to create the token,
+ /// the reference identifier may be hashed for security reasons.
///
/// The token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the expiration date associated with the specified token.
+ /// whose result returns the reference identifier associated with the specified token.
///
- public virtual Task GetExpirationDateAsync([NotNull] TToken token, CancellationToken cancellationToken)
+ public virtual Task GetReferenceIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
- return Store.GetExpirationDateAsync(token, cancellationToken);
+ return Store.GetReferenceIdAsync(token, cancellationToken);
}
///
- /// Retrieves the hashed identifier associated with a token.
+ /// Retrieves the unique identifier associated with a token.
///
/// The token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the hashed identifier associated with the specified token.
+ /// whose result returns the unique identifier associated with the token.
///
- public virtual Task GetHashAsync([NotNull] TToken token, CancellationToken cancellationToken)
+ public virtual Task GetIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
- return Store.GetHashAsync(token, cancellationToken);
+ return Store.GetIdAsync(token, cancellationToken);
}
///
- /// Retrieves the unique identifier associated with a token.
+ /// Retrieves the payload associated with a token.
///
/// The token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the unique identifier associated with the token.
+ /// whose result returns the payload associated with the specified token.
///
- public virtual Task GetIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
+ public virtual Task GetPayloadAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
- return Store.GetIdAsync(token, cancellationToken);
+ return Store.GetPayloadAsync(token, cancellationToken);
}
///
@@ -596,6 +602,30 @@ namespace OpenIddict.Core
return Store.ListInvalidAsync(count, offset, cancellationToken);
}
+ ///
+ /// Obfuscates the specified reference identifier so it can be safely stored in a database.
+ /// By default, this method returns a simple hashed representation computed using SHA256.
+ ///
+ /// The client identifier.
+ /// The that can be used to abort the operation.
+ ///
+ /// A that can be used to monitor the asynchronous operation.
+ ///
+ public virtual Task ObfuscateReferenceIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
+ {
+ if (string.IsNullOrEmpty(identifier))
+ {
+ throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
+ }
+
+ using (var algorithm = SHA256.Create())
+ {
+ // Compute the digest of the generated identifier and use it as the hashed identifier of the reference token.
+ // Doing that prevents token identifiers stolen from the database from being used as valid reference tokens.
+ return Task.FromResult(Convert.ToBase64String(algorithm.ComputeHash(Encoding.UTF8.GetBytes(identifier))));
+ }
+ }
+
///
/// Redeems a token.
///
@@ -727,10 +757,10 @@ namespace OpenIddict.Core
{
ApplicationId = await Store.GetApplicationIdAsync(token, cancellationToken),
AuthorizationId = await Store.GetAuthorizationIdAsync(token, cancellationToken),
- Ciphertext = await Store.GetCiphertextAsync(token, cancellationToken),
CreationDate = await Store.GetCreationDateAsync(token, cancellationToken),
ExpirationDate = await Store.GetExpirationDateAsync(token, cancellationToken),
- Hash = await Store.GetHashAsync(token, cancellationToken),
+ Payload = await Store.GetPayloadAsync(token, cancellationToken),
+ ReferenceId = await Store.GetReferenceIdAsync(token, cancellationToken),
Status = await Store.GetStatusAsync(token, cancellationToken),
Subject = await Store.GetSubjectAsync(token, cancellationToken),
Type = await Store.GetTokenTypeAsync(token, cancellationToken)
@@ -765,10 +795,10 @@ namespace OpenIddict.Core
await Store.SetApplicationIdAsync(token, descriptor.ApplicationId, cancellationToken);
await Store.SetAuthorizationIdAsync(token, descriptor.AuthorizationId, cancellationToken);
- await Store.SetCiphertextAsync(token, descriptor.Ciphertext, cancellationToken);
await Store.SetCreationDateAsync(token, descriptor.CreationDate, cancellationToken);
await Store.SetExpirationDateAsync(token, descriptor.ExpirationDate, cancellationToken);
- await Store.SetHashAsync(token, descriptor.Hash, cancellationToken);
+ await Store.SetPayloadAsync(token, descriptor.Payload, cancellationToken);
+ await Store.SetReferenceIdAsync(token, descriptor.ReferenceId, cancellationToken);
await Store.SetStatusAsync(token, descriptor.Status, cancellationToken);
await Store.SetSubjectAsync(token, descriptor.Subject, cancellationToken);
await Store.SetTokenTypeAsync(token, descriptor.Type, cancellationToken);
diff --git a/src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs b/src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs
index dc53ff1d..566b78ad 100644
--- a/src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs
+++ b/src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs
@@ -82,26 +82,27 @@ namespace OpenIddict.Core
Task> FindByAuthorizationIdAsync([NotNull] string identifier, CancellationToken cancellationToken);
///
- /// Retrieves the list of tokens corresponding to the specified hash.
+ /// Retrieves a token using its unique identifier.
///
- /// The hashed crypto-secure random identifier associated with the tokens.
+ /// The unique identifier associated with the token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the tokens corresponding to the specified hash.
+ /// whose result returns the token corresponding to the unique identifier.
///
- Task FindByHashAsync([NotNull] string hash, CancellationToken cancellationToken);
+ Task FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken);
///
- /// Retrieves a token using its unique identifier.
+ /// Retrieves the list of tokens corresponding to the specified reference identifier.
+ /// Note: the reference identifier may be hashed or encrypted for security reasons.
///
- /// The unique identifier associated with the token.
+ /// The reference identifier associated with the tokens.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the token corresponding to the unique identifier.
+ /// whose result returns the tokens corresponding to the specified reference identifier.
///
- Task FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken);
+ Task FindByReferenceIdAsync([NotNull] string identifier, CancellationToken cancellationToken);
///
/// Retrieves the list of tokens corresponding to the specified subject.
@@ -153,59 +154,61 @@ namespace OpenIddict.Core
Task GetAuthorizationIdAsync([NotNull] TToken token, CancellationToken cancellationToken);
///
- /// Retrieves the ciphertext associated with a token.
+ /// Retrieves the creation date associated with a token.
///
/// The token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the ciphertext associated with the specified token.
+ /// whose result returns the creation date associated with the specified token.
///
- Task GetCiphertextAsync([NotNull] TToken token, CancellationToken cancellationToken);
+ Task GetCreationDateAsync([NotNull] TToken token, CancellationToken cancellationToken);
///
- /// Retrieves the creation date associated with a token.
+ /// Retrieves the expiration date associated with a token.
///
/// The token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the creation date associated with the specified token.
+ /// whose result returns the expiration date associated with the specified token.
///
- Task GetCreationDateAsync([NotNull] TToken token, CancellationToken cancellationToken);
+ Task GetExpirationDateAsync([NotNull] TToken token, CancellationToken cancellationToken);
///
- /// Retrieves the expiration date associated with a token.
+ /// Retrieves the unique identifier associated with a token.
///
/// The token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the expiration date associated with the specified token.
+ /// whose result returns the unique identifier associated with the token.
///
- Task GetExpirationDateAsync([NotNull] TToken token, CancellationToken cancellationToken);
+ Task GetIdAsync([NotNull] TToken token, CancellationToken cancellationToken);
///
- /// Retrieves the hashed identifier associated with a token.
+ /// Retrieves the payload associated with a token.
///
/// The token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the hashed identifier associated with the specified token.
+ /// whose result returns the payload associated with the specified token.
///
- Task GetHashAsync([NotNull] TToken token, CancellationToken cancellationToken);
+ Task GetPayloadAsync([NotNull] TToken token, CancellationToken cancellationToken);
///
- /// Retrieves the unique identifier associated with a token.
+ /// Retrieves the reference identifier associated with a token.
+ /// Note: depending on the manager used to create the token,
+ /// the reference identifier may be hashed for security reasons.
///
/// The token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the unique identifier associated with the token.
+ /// whose result returns the reference identifier associated with the specified token.
///
- Task GetIdAsync([NotNull] TToken token, CancellationToken cancellationToken);
+ Task GetReferenceIdAsync([NotNull] TToken token, CancellationToken cancellationToken);
///
/// Retrieves the status associated with a token.
@@ -314,48 +317,50 @@ namespace OpenIddict.Core
Task SetAuthorizationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
///
- /// Sets the ciphertext associated with a token.
+ /// Sets the creation date associated with a token.
///
/// The token.
- /// The ciphertext associated with the token.
+ /// The creation date.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation.
///
- Task SetCiphertextAsync([NotNull] TToken token, [CanBeNull] string ciphertext, CancellationToken cancellationToken);
+ Task SetCreationDateAsync([NotNull] TToken token, [CanBeNull] DateTimeOffset? date, CancellationToken cancellationToken);
///
- /// Sets the creation date associated with a token.
+ /// Sets the expiration date associated with a token.
///
/// The token.
- /// The creation date.
+ /// The expiration date.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation.
///
- Task SetCreationDateAsync([NotNull] TToken token, [CanBeNull] DateTimeOffset? date, CancellationToken cancellationToken);
+ Task SetExpirationDateAsync([NotNull] TToken token, [CanBeNull] DateTimeOffset? date, CancellationToken cancellationToken);
///
- /// Sets the expiration date associated with a token.
+ /// Sets the payload associated with a token.
///
/// The token.
- /// The expiration date.
+ /// The payload associated with the token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation.
///
- Task SetExpirationDateAsync([NotNull] TToken token, [CanBeNull] DateTimeOffset? date, CancellationToken cancellationToken);
+ Task SetPayloadAsync([NotNull] TToken token, [CanBeNull] string payload, CancellationToken cancellationToken);
///
- /// Sets the hash associated with a token.
+ /// Sets the reference identifier associated with a token.
+ /// Note: depending on the manager used to create the token,
+ /// the reference identifier may be hashed for security reasons.
///
/// The token.
- /// The hash associated with the token.
+ /// The reference identifier associated with the token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation.
///
- Task SetHashAsync([NotNull] TToken token, [CanBeNull] string hash, CancellationToken cancellationToken);
+ Task SetReferenceIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
///
/// Sets the status associated with a token.
diff --git a/src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs b/src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs
index 15f60f1d..af1f5e86 100644
--- a/src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs
+++ b/src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs
@@ -124,51 +124,52 @@ namespace OpenIddict.Core
}
///
- /// Retrieves the list of tokens corresponding to the specified hash.
+ /// Retrieves a token using its unique identifier.
///
- /// The hashed crypto-secure random identifier associated with the tokens.
+ /// The unique identifier associated with the token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the tokens corresponding to the specified hash.
+ /// whose result returns the token corresponding to the unique identifier.
///
- public virtual Task FindByHashAsync([NotNull] string hash, CancellationToken cancellationToken)
+ public virtual Task FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
{
- if (string.IsNullOrEmpty(hash))
+ if (string.IsNullOrEmpty(identifier))
{
- throw new ArgumentException("The hash cannot be null or empty.", nameof(hash));
+ throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
- IQueryable Query(IQueryable tokens, string digest)
+ IQueryable Query(IQueryable tokens, TKey key)
=> from token in tokens
- where token.Hash == digest
+ where token.Id.Equals(key)
select token;
- return GetAsync((tokens, digest) => Query(tokens, digest), hash, cancellationToken);
+ return GetAsync((tokens, key) => Query(tokens, key), ConvertIdentifierFromString(identifier), cancellationToken);
}
///
- /// Retrieves a token using its unique identifier.
+ /// Retrieves the list of tokens corresponding to the specified reference identifier.
+ /// Note: the reference identifier may be hashed or encrypted for security reasons.
///
- /// The unique identifier associated with the token.
+ /// The reference identifier associated with the tokens.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the token corresponding to the unique identifier.
+ /// whose result returns the tokens corresponding to the specified reference identifier.
///
- public virtual Task FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
+ public virtual Task FindByReferenceIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(identifier))
{
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
- IQueryable Query(IQueryable tokens, TKey key)
+ IQueryable Query(IQueryable tokens, string id)
=> from token in tokens
- where token.Id.Equals(key)
+ where token.ReferenceId == id
select token;
- return GetAsync((tokens, key) => Query(tokens, key), ConvertIdentifierFromString(identifier), cancellationToken);
+ return GetAsync((tokens, id) => Query(tokens, identifier), identifier, cancellationToken);
}
///
@@ -272,98 +273,100 @@ namespace OpenIddict.Core
}
///
- /// Retrieves the ciphertext associated with a token.
+ /// Retrieves the creation date associated with a token.
///
/// The token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the ciphertext associated with the specified token.
+ /// whose result returns the creation date associated with the specified token.
///
- public virtual Task GetCiphertextAsync([NotNull] TToken token, CancellationToken cancellationToken)
+ public virtual Task GetCreationDateAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
- return Task.FromResult(token.Ciphertext);
+ return Task.FromResult(token.CreationDate);
}
///
- /// Retrieves the creation date associated with a token.
+ /// Retrieves the expiration date associated with a token.
///
/// The token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the creation date associated with the specified token.
+ /// whose result returns the expiration date associated with the specified token.
///
- public virtual Task GetCreationDateAsync([NotNull] TToken token, CancellationToken cancellationToken)
+ public virtual Task GetExpirationDateAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
- return Task.FromResult(token.CreationDate);
+ return Task.FromResult(token.ExpirationDate);
}
///
- /// Retrieves the expiration date associated with a token.
+ /// Retrieves the unique identifier associated with a token.
///
/// The token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the expiration date associated with the specified token.
+ /// whose result returns the unique identifier associated with the token.
///
- public virtual Task GetExpirationDateAsync([NotNull] TToken token, CancellationToken cancellationToken)
+ public virtual Task GetIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
- return Task.FromResult(token.ExpirationDate);
+ return Task.FromResult(ConvertIdentifierToString(token.Id));
}
///
- /// Retrieves the hashed identifier associated with a token.
+ /// Retrieves the payload associated with a token.
///
/// The token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the hashed identifier associated with the specified token.
+ /// whose result returns the payload associated with the specified token.
///
- public virtual Task GetHashAsync([NotNull] TToken token, CancellationToken cancellationToken)
+ public virtual Task GetPayloadAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
- return Task.FromResult(token.Hash);
+ return Task.FromResult(token.Payload);
}
///
- /// Retrieves the unique identifier associated with a token.
+ /// Retrieves the reference identifier associated with a token.
+ /// Note: depending on the manager used to create the token,
+ /// the reference identifier may be hashed for security reasons.
///
/// The token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation,
- /// whose result returns the unique identifier associated with the token.
+ /// whose result returns the reference identifier associated with the specified token.
///
- public virtual Task GetIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
+ public virtual Task GetReferenceIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
- return Task.FromResult(ConvertIdentifierToString(token.Id));
+ return Task.FromResult(token.ReferenceId);
}
///
@@ -545,36 +548,37 @@ namespace OpenIddict.Core
public abstract Task SetApplicationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken);
///
- /// Sets the ciphertext associated with a token.
+ /// Sets the creation date associated with a token.
///
/// The token.
- /// The ciphertext associated with the token.
+ /// The creation date.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation.
///
- public virtual Task SetCiphertextAsync([NotNull] TToken token, [CanBeNull] string ciphertext, CancellationToken cancellationToken)
+ public virtual Task SetCreationDateAsync([NotNull] TToken token,
+ [CanBeNull] DateTimeOffset? date, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
- token.Ciphertext = ciphertext;
+ token.CreationDate = date;
return Task.FromResult(0);
}
///
- /// Sets the creation date associated with a token.
+ /// Sets the expiration date associated with a token.
///
/// The token.
- /// The creation date.
+ /// The expiration date.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation.
///
- public virtual Task SetCreationDateAsync([NotNull] TToken token,
+ public virtual Task SetExpirationDateAsync([NotNull] TToken token,
[CanBeNull] DateTimeOffset? date, CancellationToken cancellationToken)
{
if (token == null)
@@ -582,50 +586,51 @@ namespace OpenIddict.Core
throw new ArgumentNullException(nameof(token));
}
- token.CreationDate = date;
+ token.ExpirationDate = date;
return Task.FromResult(0);
}
///
- /// Sets the expiration date associated with a token.
+ /// Sets the payload associated with a token.
///
/// The token.
- /// The expiration date.
+ /// The payload associated with the token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation.
///
- public virtual Task SetExpirationDateAsync([NotNull] TToken token,
- [CanBeNull] DateTimeOffset? date, CancellationToken cancellationToken)
+ public virtual Task SetPayloadAsync([NotNull] TToken token, [CanBeNull] string payload, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
- token.ExpirationDate = date;
+ token.Payload = payload;
return Task.FromResult(0);
}
///
- /// Sets the hash associated with a token.
+ /// Sets the reference identifier associated with a token.
+ /// Note: depending on the manager used to create the token,
+ /// the reference identifier may be hashed for security reasons.
///
/// The token.
- /// The hash associated with the token.
+ /// The reference identifier associated with the token.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation.
///
- public virtual Task SetHashAsync([NotNull] TToken token, [CanBeNull] string hash, CancellationToken cancellationToken)
+ public virtual Task SetReferenceIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
- token.Hash = hash;
+ token.ReferenceId = identifier;
return Task.FromResult(0);
}
diff --git a/src/OpenIddict.EntityFramework/OpenIddictExtensions.cs b/src/OpenIddict.EntityFramework/OpenIddictExtensions.cs
index f215c10e..f195e345 100644
--- a/src/OpenIddict.EntityFramework/OpenIddictExtensions.cs
+++ b/src/OpenIddict.EntityFramework/OpenIddictExtensions.cs
@@ -265,7 +265,7 @@ namespace Microsoft.Extensions.DependencyInjection
.IsConcurrencyToken();
builder.Entity()
- .Property(token => token.Hash)
+ .Property(token => token.ReferenceId)
.HasMaxLength(450)
.HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute()));
diff --git a/src/OpenIddict.EntityFrameworkCore/OpenIddictExtensions.cs b/src/OpenIddict.EntityFrameworkCore/OpenIddictExtensions.cs
index 7bd1793a..57b75b89 100644
--- a/src/OpenIddict.EntityFrameworkCore/OpenIddictExtensions.cs
+++ b/src/OpenIddict.EntityFrameworkCore/OpenIddictExtensions.cs
@@ -292,7 +292,7 @@ namespace Microsoft.Extensions.DependencyInjection
{
entity.HasKey(token => token.Id);
- entity.HasIndex(token => token.Hash)
+ entity.HasIndex(token => token.ReferenceId)
.IsUnique();
entity.Property(token => token.ConcurrencyToken)
diff --git a/src/OpenIddict.Models/OpenIddictToken.cs b/src/OpenIddict.Models/OpenIddictToken.cs
index 73834fcf..ce10c1fc 100644
--- a/src/OpenIddict.Models/OpenIddictToken.cs
+++ b/src/OpenIddict.Models/OpenIddictToken.cs
@@ -43,13 +43,6 @@ namespace OpenIddict.Models
///
public virtual TAuthorization Authorization { get; set; }
- ///
- /// Gets or sets the encrypted payload
- /// of the current token, if applicable.
- /// This property is only used for reference tokens.
- ///
- public virtual string Ciphertext { get; set; }
-
///
/// Gets or sets the concurrency token.
///
@@ -67,19 +60,27 @@ namespace OpenIddict.Models
///
public virtual DateTimeOffset? ExpirationDate { get; set; }
- ///
- /// Gets or sets the hashed identifier associated
- /// with the current token, if applicable.
- /// This property is only used for reference tokens.
- ///
- public virtual string Hash { get; set; }
-
///
/// Gets or sets the unique identifier
/// associated with the current token.
///
public virtual TKey Id { get; set; }
+ ///
+ /// Gets or sets the payload of the current token, if applicable.
+ /// Note: this property is only used for reference tokens
+ /// and may be encrypted for security reasons.
+ ///
+ public virtual string Payload { get; set; }
+
+ ///
+ /// Gets or sets the reference identifier associated
+ /// with the current token, if applicable.
+ /// Note: this property is only used for reference tokens
+ /// and may be hashed or encrypted for security reasons.
+ ///
+ public virtual string ReferenceId { get; set; }
+
///
/// Gets or sets the status of the current token.
///
diff --git a/src/OpenIddict/OpenIddictProvider.Helpers.cs b/src/OpenIddict/OpenIddictProvider.Helpers.cs
index 808a0695..67cd2484 100644
--- a/src/OpenIddict/OpenIddictProvider.Helpers.cs
+++ b/src/OpenIddict/OpenIddictProvider.Helpers.cs
@@ -161,7 +161,7 @@ namespace OpenIddict
// Note: the data format is automatically replaced at startup time to ensure
// that encrypted tokens stored in the database cannot be considered as
// valid tokens if the developer decides to disable reference tokens support.
- descriptor.Ciphertext = format.Protect(ticket);
+ descriptor.Payload = format.Protect(ticket);
// Generate a new crypto-secure random identifier that will be
// substituted to the ciphertext returned by the data format.
@@ -169,14 +169,8 @@ namespace OpenIddict
options.RandomNumberGenerator.GetBytes(bytes);
result = Base64UrlEncoder.Encode(bytes);
- // Compute the digest of the generated identifier and use
- // it as the hashed identifier of the reference token.
- // Doing that prevents token identifiers stolen from
- // the database from being used as valid reference tokens.
- using (var algorithm = SHA256.Create())
- {
- descriptor.Hash = Convert.ToBase64String(algorithm.ComputeHash(bytes));
- }
+ // Obfuscate the reference identifier so it can be safely stored in the databse.
+ descriptor.ReferenceId = await tokens.ObfuscateReferenceIdAsync(result, context.RequestAborted);
}
// Otherwise, only create a token metadata entry for authorization codes and refresh tokens.
@@ -253,15 +247,11 @@ namespace OpenIddict
if (options.UseReferenceTokens)
{
- string hash;
+ // Retrieve the token entry from the database.
+ // If it cannot be found, assume the token is not valid.
try
{
- // Compute the digest of the received token and use it
- // to retrieve the reference token from the database.
- using (var algorithm = SHA256.Create())
- {
- hash = Convert.ToBase64String(algorithm.ComputeHash(Base64UrlEncoder.DecodeBytes(value)));
- }
+ token = await tokens.FindByReferenceIdAsync(value, context.RequestAborted);
}
// Swallow format-related exceptions to ensure badly formed
@@ -271,13 +261,10 @@ namespace OpenIddict
return null;
}
- // Retrieve the token entry from the database. If it
- // cannot be found, assume the token is not valid.
- token = await tokens.FindByHashAsync(hash, context.RequestAborted);
if (token == null)
{
- logger.LogInformation("The reference token corresponding to the '{Hash}' hashed " +
- "identifier cannot be found in the database.", hash);
+ logger.LogInformation("The reference token corresponding to the '{Identifier}' " +
+ "reference identifier cannot be found in the database.", value);
return null;
}
@@ -294,8 +281,8 @@ namespace OpenIddict
// 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 ciphertext = await tokens.GetCiphertextAsync(token, context.RequestAborted);
- if (string.IsNullOrEmpty(ciphertext))
+ var payload = await tokens.GetPayloadAsync(token, context.RequestAborted);
+ if (string.IsNullOrEmpty(payload))
{
logger.LogWarning("The ciphertext associated with the token '{Identifier}' cannot be retrieved. " +
"This may indicate that the token is not a reference token.", identifier);
@@ -303,7 +290,7 @@ namespace OpenIddict
return null;
}
- ticket = format.Unprotect(ciphertext);
+ ticket = format.Unprotect(payload);
if (ticket == null)
{
logger.LogWarning("The ciphertext associated with the token '{Identifier}' cannot be decrypted. " +
diff --git a/test/OpenIddict.Tests/OpenIddictProviderTests.Introspection.cs b/test/OpenIddict.Tests/OpenIddictProviderTests.Introspection.cs
index 14aa5a64..40fb77e9 100644
--- a/test/OpenIddict.Tests/OpenIddictProviderTests.Introspection.cs
+++ b/test/OpenIddict.Tests/OpenIddictProviderTests.Introspection.cs
@@ -357,7 +357,7 @@ namespace OpenIddict.Tests
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.FindByHashAsync("coYFMTIt6jDp2O41qaUfV+XGhPsils3Z3YfmUvudrVw=", It.IsAny()))
+ instance.Setup(mock => mock.FindByReferenceIdAsync("QaTk2f6UPe9trKismGBJr0OIs0KqpvNrqRsJqGuJAAI", It.IsAny()))
.ReturnsAsync(value: null);
});
@@ -397,7 +397,7 @@ namespace OpenIddict.Tests
Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]);
- Mock.Get(manager).Verify(mock => mock.FindByHashAsync("coYFMTIt6jDp2O41qaUfV+XGhPsils3Z3YfmUvudrVw=", It.IsAny()), Times.Exactly(3));
+ Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync("QaTk2f6UPe9trKismGBJr0OIs0KqpvNrqRsJqGuJAAI", It.IsAny()), Times.Exactly(3));
}
[Fact]
@@ -424,13 +424,13 @@ namespace OpenIddict.Tests
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.FindByHashAsync("coYFMTIt6jDp2O41qaUfV+XGhPsils3Z3YfmUvudrVw=", It.IsAny()))
+ instance.Setup(mock => mock.FindByReferenceIdAsync("QaTk2f6UPe9trKismGBJr0OIs0KqpvNrqRsJqGuJAAI", It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
.ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56");
- instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny()))
+ instance.Setup(mock => mock.GetPayloadAsync(token, It.IsAny()))
.ReturnsAsync("2YotnFZFEjr1zCsicMWpAA");
instance.Setup(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny()))
@@ -477,7 +477,7 @@ namespace OpenIddict.Tests
Assert.Single(response.GetParameters());
Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]);
- Mock.Get(manager).Verify(mock => mock.FindByHashAsync("coYFMTIt6jDp2O41qaUfV+XGhPsils3Z3YfmUvudrVw=", It.IsAny()), Times.Once());
+ Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync("QaTk2f6UPe9trKismGBJr0OIs0KqpvNrqRsJqGuJAAI", It.IsAny()), Times.Once());
Mock.Get(manager).Verify(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny()), Times.Once());
Mock.Get(manager).Verify(mock => mock.IsValidAsync(token, It.IsAny()), Times.Once());
}
diff --git a/test/OpenIddict.Tests/OpenIddictProviderTests.Serialization.cs b/test/OpenIddict.Tests/OpenIddictProviderTests.Serialization.cs
index 7f78f116..1cd4bcf1 100644
--- a/test/OpenIddict.Tests/OpenIddictProviderTests.Serialization.cs
+++ b/test/OpenIddict.Tests/OpenIddictProviderTests.Serialization.cs
@@ -142,7 +142,7 @@ namespace OpenIddict.Tests
Assert.True((bool) response[OpenIdConnectConstants.Claims.Active]);
format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Once());
- Mock.Get(manager).Verify(mock => mock.FindByHashAsync(It.IsAny(), It.IsAny()), Times.Never());
+ Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync(It.IsAny(), It.IsAny()), Times.Never());
}
[Fact]
@@ -153,7 +153,7 @@ namespace OpenIddict.Tests
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()))
+ instance.Setup(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
@@ -196,7 +196,7 @@ namespace OpenIddict.Tests
Assert.Single(response.GetParameters());
Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]);
- Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.AtLeastOnce());
+ Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()), Times.AtLeastOnce());
Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.AtLeastOnce());
}
@@ -208,13 +208,13 @@ namespace OpenIddict.Tests
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()))
+ instance.Setup(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
.ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56");
- instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny()))
+ instance.Setup(mock => mock.GetPayloadAsync(token, It.IsAny()))
.ReturnsAsync(value: null);
});
@@ -254,7 +254,7 @@ namespace OpenIddict.Tests
Assert.Single(response.GetParameters());
Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]);
- Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.AtLeastOnce());
+ Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()), Times.AtLeastOnce());
Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.AtLeastOnce());
}
@@ -271,13 +271,13 @@ namespace OpenIddict.Tests
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()))
+ instance.Setup(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
.ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56");
- instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny()))
+ instance.Setup(mock => mock.GetPayloadAsync(token, It.IsAny()))
.ReturnsAsync("2YotnFZFEjr1zCsicMWpAA");
});
@@ -319,7 +319,7 @@ namespace OpenIddict.Tests
Assert.Single(response.GetParameters());
Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]);
- Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.AtLeastOnce());
+ Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()), Times.AtLeastOnce());
Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.AtLeastOnce());
format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Once());
}
@@ -347,13 +347,13 @@ namespace OpenIddict.Tests
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()))
+ instance.Setup(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
.ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56");
- instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny()))
+ instance.Setup(mock => mock.GetPayloadAsync(token, It.IsAny()))
.ReturnsAsync("2YotnFZFEjr1zCsicMWpAA");
instance.Setup(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny()))
@@ -415,7 +415,7 @@ namespace OpenIddict.Tests
Assert.Equal(1483228800, (long) response[OpenIdConnectConstants.Claims.IssuedAt]);
Assert.Equal(1484006400, (long) response[OpenIdConnectConstants.Claims.ExpiresAt]);
- Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.Once());
+ Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()), Times.Once());
Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.Once());
format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Once());
}
@@ -538,7 +538,7 @@ namespace OpenIddict.Tests
Assert.True((bool) response[OpenIdConnectConstants.Claims.Active]);
format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Once());
- Mock.Get(manager).Verify(mock => mock.FindByHashAsync(It.IsAny(), It.IsAny()), Times.Never());
+ Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync(It.IsAny(), It.IsAny()), Times.Never());
}
[Fact]
@@ -549,7 +549,7 @@ namespace OpenIddict.Tests
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()))
+ instance.Setup(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
@@ -592,7 +592,7 @@ namespace OpenIddict.Tests
Assert.Single(response.GetParameters());
Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]);
- Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.AtLeastOnce());
+ Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()), Times.AtLeastOnce());
Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.AtLeastOnce());
}
@@ -604,13 +604,13 @@ namespace OpenIddict.Tests
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()))
+ instance.Setup(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
.ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56");
- instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny()))
+ instance.Setup(mock => mock.GetPayloadAsync(token, It.IsAny()))
.ReturnsAsync(value: null);
});
@@ -650,7 +650,7 @@ namespace OpenIddict.Tests
Assert.Single(response.GetParameters());
Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]);
- Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.AtLeastOnce());
+ Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()), Times.AtLeastOnce());
Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.AtLeastOnce());
}
@@ -667,13 +667,13 @@ namespace OpenIddict.Tests
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()))
+ instance.Setup(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
.ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56");
- instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny()))
+ instance.Setup(mock => mock.GetPayloadAsync(token, It.IsAny()))
.ReturnsAsync("2YotnFZFEjr1zCsicMWpAA");
});
@@ -715,7 +715,7 @@ namespace OpenIddict.Tests
Assert.Single(response.GetParameters());
Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]);
- Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.AtLeastOnce());
+ Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()), Times.AtLeastOnce());
Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.AtLeastOnce());
format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Once());
}
@@ -741,13 +741,13 @@ namespace OpenIddict.Tests
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()))
+ instance.Setup(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
.ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56");
- instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny()))
+ instance.Setup(mock => mock.GetPayloadAsync(token, It.IsAny()))
.ReturnsAsync("2YotnFZFEjr1zCsicMWpAA");
instance.Setup(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny()))
@@ -809,7 +809,7 @@ namespace OpenIddict.Tests
Assert.Equal(1483228800, (long) response[OpenIdConnectConstants.Claims.IssuedAt]);
Assert.Equal(1484006400, (long) response[OpenIdConnectConstants.Claims.ExpiresAt]);
- Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.Once());
+ Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()), Times.Once());
Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.Once());
format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Once());
}
@@ -1118,7 +1118,7 @@ namespace OpenIddict.Tests
Assert.True((bool) response[OpenIdConnectConstants.Claims.Active]);
format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Once());
- Mock.Get(manager).Verify(mock => mock.FindByHashAsync(It.IsAny(), It.IsAny()), Times.Never());
+ Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync(It.IsAny(), It.IsAny()), Times.Never());
}
[Fact]
@@ -1129,7 +1129,7 @@ namespace OpenIddict.Tests
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()))
+ instance.Setup(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
@@ -1172,7 +1172,7 @@ namespace OpenIddict.Tests
Assert.Single(response.GetParameters());
Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]);
- Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.AtLeastOnce());
+ Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()), Times.AtLeastOnce());
Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.AtLeastOnce());
}
@@ -1184,13 +1184,13 @@ namespace OpenIddict.Tests
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()))
+ instance.Setup(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
.ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56");
- instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny()))
+ instance.Setup(mock => mock.GetPayloadAsync(token, It.IsAny()))
.ReturnsAsync(value: null);
});
@@ -1230,7 +1230,7 @@ namespace OpenIddict.Tests
Assert.Single(response.GetParameters());
Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]);
- Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.AtLeastOnce());
+ Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()), Times.AtLeastOnce());
Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.AtLeastOnce());
}
@@ -1247,13 +1247,13 @@ namespace OpenIddict.Tests
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()))
+ instance.Setup(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
.ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56");
- instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny()))
+ instance.Setup(mock => mock.GetPayloadAsync(token, It.IsAny()))
.ReturnsAsync("2YotnFZFEjr1zCsicMWpAA");
});
@@ -1295,7 +1295,7 @@ namespace OpenIddict.Tests
Assert.Single(response.GetParameters());
Assert.False((bool) response[OpenIdConnectConstants.Claims.Active]);
- Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.AtLeastOnce());
+ Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()), Times.AtLeastOnce());
Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.AtLeastOnce());
format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Once());
}
@@ -1321,13 +1321,13 @@ namespace OpenIddict.Tests
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()))
+ instance.Setup(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
.ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56");
- instance.Setup(mock => mock.GetCiphertextAsync(token, It.IsAny()))
+ instance.Setup(mock => mock.GetPayloadAsync(token, It.IsAny()))
.ReturnsAsync("2YotnFZFEjr1zCsicMWpAA");
instance.Setup(mock => mock.FindByIdAsync("3E228451-1555-46F7-A471-951EFBA23A56", It.IsAny()))
@@ -1389,7 +1389,7 @@ namespace OpenIddict.Tests
Assert.Equal(1483228800, (long) response[OpenIdConnectConstants.Claims.IssuedAt]);
Assert.Equal(1484006400, (long) response[OpenIdConnectConstants.Claims.ExpiresAt]);
- Mock.Get(manager).Verify(mock => mock.FindByHashAsync("jTwUlKz7IT5tRnmMnxYW26OdS28cPG2rM04zQr0ez70=", It.IsAny()), Times.Once());
+ Mock.Get(manager).Verify(mock => mock.FindByReferenceIdAsync("HQnldPTjH_9m85GcS-5PPYaCxmJTt1umxOa2y9ggVUQ", It.IsAny()), Times.Once());
Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.Once());
format.Verify(mock => mock.Unprotect("2YotnFZFEjr1zCsicMWpAA"), Times.Once());
}
@@ -1629,6 +1629,9 @@ namespace OpenIddict.Tests
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
.ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56");
+
+ instance.Setup(mock => mock.ObfuscateReferenceIdAsync(It.IsAny(), It.IsAny()))
+ .ReturnsAsync("B1F0D503-55A4-4B03-B05B-EF07713C18E1");
});
var server = CreateAuthorizationServer(builder =>
@@ -1658,12 +1661,15 @@ namespace OpenIddict.Tests
// Assert
Assert.NotNull(response.AccessToken);
+ Mock.Get(manager).Verify(mock => mock.ObfuscateReferenceIdAsync(
+ It.IsAny(), It.IsAny()), Times.Exactly(2));
+
Mock.Get(manager).Verify(mock => mock.CreateAsync(
It.Is(descriptor =>
- descriptor.Ciphertext != null &&
- descriptor.Hash != null &&
descriptor.ExpirationDate == token.ExpirationDate &&
descriptor.CreationDate == token.CreationDate &&
+ descriptor.Payload != null &&
+ descriptor.ReferenceId != null &&
descriptor.Subject == "Bob le Magnifique" &&
descriptor.Type == OpenIdConnectConstants.TokenTypeHints.AccessToken),
It.IsAny()), Times.Once());
@@ -1889,10 +1895,10 @@ namespace OpenIddict.Tests
Mock.Get(manager).Verify(mock => mock.CreateAsync(
It.Is(descriptor =>
- descriptor.Ciphertext == null &&
- descriptor.Hash == null &&
descriptor.ExpirationDate == token.ExpirationDate &&
descriptor.CreationDate == token.CreationDate &&
+ descriptor.Payload == null &&
+ descriptor.ReferenceId == null &&
descriptor.Subject == "Bob le Magnifique" &&
descriptor.Type == OpenIdConnectConstants.TokenTypeHints.AuthorizationCode),
It.IsAny()), Times.Once());
@@ -1915,6 +1921,9 @@ namespace OpenIddict.Tests
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
.ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56");
+
+ instance.Setup(mock => mock.ObfuscateReferenceIdAsync(It.IsAny(), It.IsAny()))
+ .ReturnsAsync("B1F0D503-55A4-4B03-B05B-EF07713C18E1");
});
var server = CreateAuthorizationServer(builder =>
@@ -1960,12 +1969,15 @@ namespace OpenIddict.Tests
// Assert
Assert.NotNull(response.Code);
+ Mock.Get(manager).Verify(mock => mock.ObfuscateReferenceIdAsync(
+ It.IsAny(), It.IsAny()), Times.Once());
+
Mock.Get(manager).Verify(mock => mock.CreateAsync(
It.Is(descriptor =>
- descriptor.Ciphertext != null &&
- descriptor.Hash != null &&
descriptor.ExpirationDate == token.ExpirationDate &&
descriptor.CreationDate == token.CreationDate &&
+ descriptor.Payload != null &&
+ descriptor.ReferenceId != null &&
descriptor.Subject == "Bob le Magnifique" &&
descriptor.Type == OpenIdConnectConstants.TokenTypeHints.AuthorizationCode),
It.IsAny()), Times.Once());
@@ -2246,10 +2258,10 @@ namespace OpenIddict.Tests
Mock.Get(manager).Verify(mock => mock.CreateAsync(
It.Is(descriptor =>
- descriptor.Ciphertext == null &&
- descriptor.Hash == null &&
descriptor.ExpirationDate == token.ExpirationDate &&
descriptor.CreationDate == token.CreationDate &&
+ descriptor.Payload == null &&
+ descriptor.ReferenceId == null &&
descriptor.Subject == "Bob le Magnifique" &&
descriptor.Type == OpenIdConnectConstants.TokenTypeHints.RefreshToken),
It.IsAny()), Times.Once());
@@ -2272,6 +2284,9 @@ namespace OpenIddict.Tests
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
.ReturnsAsync("3E228451-1555-46F7-A471-951EFBA23A56");
+
+ instance.Setup(mock => mock.ObfuscateReferenceIdAsync(It.IsAny(), It.IsAny()))
+ .ReturnsAsync("B1F0D503-55A4-4B03-B05B-EF07713C18E1");
});
var server = CreateAuthorizationServer(builder =>
@@ -2301,12 +2316,15 @@ namespace OpenIddict.Tests
// Assert
Assert.NotNull(response.RefreshToken);
+ Mock.Get(manager).Verify(mock => mock.ObfuscateReferenceIdAsync(
+ It.IsAny(), It.IsAny()), Times.Exactly(2));
+
Mock.Get(manager).Verify(mock => mock.CreateAsync(
It.Is(descriptor =>
- descriptor.Ciphertext != null &&
- descriptor.Hash != null &&
descriptor.ExpirationDate == token.ExpirationDate &&
descriptor.CreationDate == token.CreationDate &&
+ descriptor.Payload != null &&
+ descriptor.ReferenceId == "B1F0D503-55A4-4B03-B05B-EF07713C18E1" &&
descriptor.Subject == "Bob le Magnifique" &&
descriptor.Type == OpenIdConnectConstants.TokenTypeHints.RefreshToken),
It.IsAny()), Times.Once());