diff --git a/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs b/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
index cd8db35b..c1480e63 100644
--- a/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
+++ b/src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
@@ -61,11 +61,16 @@ namespace OpenIddict.Core
///
/// The token type.
/// The subject associated with the token.
+ /// The date on which the token will start to be considered valid.
+ /// The date on which the token will no longer be considered valid.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation, whose result returns the token.
///
- public virtual Task CreateAsync([NotNull] string type, [NotNull] string subject, CancellationToken cancellationToken)
+ public virtual Task CreateAsync(
+ [NotNull] string type, [NotNull] string subject,
+ [CanBeNull] DateTimeOffset? start,
+ [CanBeNull] DateTimeOffset? end, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(type))
{
@@ -77,7 +82,7 @@ namespace OpenIddict.Core
throw new ArgumentException("The subject cannot be null or empty.");
}
- return Store.CreateAsync(type, subject, cancellationToken);
+ return Store.CreateAsync(type, subject, start, end, cancellationToken);
}
///
@@ -87,13 +92,15 @@ namespace OpenIddict.Core
/// The subject associated with the token.
/// The hash of the crypto-secure random identifier associated with the token.
/// The ciphertext associated with the token.
+ /// The date on which the token will start to be considered valid.
+ /// The date on which the token will no longer be considered valid.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation, whose result returns the token.
///
public virtual Task CreateAsync(
- [NotNull] string type, [NotNull] string subject, [NotNull] string hash,
- [NotNull] string ciphertext, CancellationToken cancellationToken)
+ [NotNull] string type, [NotNull] string subject, [NotNull] string hash, [NotNull] string ciphertext,
+ [CanBeNull] DateTimeOffset? start, [CanBeNull] DateTimeOffset? end, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(type))
{
@@ -110,7 +117,7 @@ namespace OpenIddict.Core
throw new ArgumentException("The ciphertext cannot be null or empty.", nameof(ciphertext));
}
- return Store.CreateAsync(type, subject, hash, ciphertext, cancellationToken);
+ return Store.CreateAsync(type, subject, hash, ciphertext, start, end, cancellationToken);
}
///
diff --git a/src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs b/src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs
index 9840206c..ca9dc883 100644
--- a/src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs
+++ b/src/OpenIddict.Core/Stores/IOpenIddictTokenStore.cs
@@ -4,6 +4,7 @@
* the license and the contributors participating to this project.
*/
+using System;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
@@ -31,11 +32,16 @@ namespace OpenIddict.Core
///
/// The token type.
/// The subject associated with the token.
+ /// The date on which the token will start to be considered valid.
+ /// The date on which the token will no longer be considered valid.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation, whose result returns the token.
///
- Task CreateAsync([NotNull] string type, [NotNull] string subject, CancellationToken cancellationToken);
+ Task CreateAsync(
+ [NotNull] string type, [NotNull] string subject,
+ [CanBeNull] DateTimeOffset? start,
+ [CanBeNull] DateTimeOffset? end, CancellationToken cancellationToken);
///
/// Creates a new reference token, which is associated with a particular subject.
@@ -44,13 +50,15 @@ namespace OpenIddict.Core
/// The subject associated with the token.
/// The hash of the crypto-secure random identifier associated with the token.
/// The ciphertext associated with the token.
+ /// The date on which the token will start to be considered valid.
+ /// The date on which the token will no longer be considered valid.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation, whose result returns the token.
///
Task CreateAsync(
- [NotNull] string type, [NotNull] string subject, [NotNull] string hash,
- [NotNull] string ciphertext, CancellationToken cancellationToken);
+ [NotNull] string type, [NotNull] string subject, [NotNull] string hash, [NotNull] string ciphertext,
+ [CanBeNull] DateTimeOffset? start, [CanBeNull] DateTimeOffset? end, CancellationToken cancellationToken);
///
/// Removes a token.
diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs
index d9a922a8..399a8189 100644
--- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs
+++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs
@@ -114,11 +114,16 @@ namespace OpenIddict.EntityFrameworkCore
///
/// The token type.
/// The subject associated with the token.
+ /// The date on which the token will start to be considered valid.
+ /// The date on which the token will no longer be considered valid.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation, whose result returns the token.
///
- public virtual Task CreateAsync([NotNull] string type, [NotNull] string subject, CancellationToken cancellationToken)
+ public virtual Task CreateAsync(
+ [NotNull] string type, [NotNull] string subject,
+ [CanBeNull] DateTimeOffset? start,
+ [CanBeNull] DateTimeOffset? end, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(type))
{
@@ -132,6 +137,8 @@ namespace OpenIddict.EntityFrameworkCore
var token = new TToken
{
+ End = end,
+ Start = start,
Subject = subject,
Type = type
};
@@ -146,13 +153,15 @@ namespace OpenIddict.EntityFrameworkCore
/// The subject associated with the token.
/// The hash of the crypto-secure random identifier associated with the token.
/// The ciphertext associated with the token.
+ /// The date on which the token will start to be considered valid.
+ /// The date on which the token will no longer be considered valid.
/// The that can be used to abort the operation.
///
/// A that can be used to monitor the asynchronous operation, whose result returns the token.
///
public virtual Task CreateAsync(
- [NotNull] string type, [NotNull] string subject, [NotNull] string hash,
- [NotNull] string ciphertext, CancellationToken cancellationToken)
+ [NotNull] string type, [NotNull] string subject, [NotNull] string hash, [NotNull] string ciphertext,
+ [CanBeNull] DateTimeOffset? start, [CanBeNull] DateTimeOffset? end, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(type))
{
@@ -167,7 +176,9 @@ namespace OpenIddict.EntityFrameworkCore
var token = new TToken
{
Ciphertext = ciphertext,
+ End = end,
Hash = hash,
+ Start = start,
Subject = subject,
Type = type
};
diff --git a/src/OpenIddict.Models/OpenIddictToken.cs b/src/OpenIddict.Models/OpenIddictToken.cs
index ba6113c0..f9926574 100644
--- a/src/OpenIddict.Models/OpenIddictToken.cs
+++ b/src/OpenIddict.Models/OpenIddictToken.cs
@@ -50,6 +50,12 @@ namespace OpenIddict.Models
///
public virtual string Ciphertext { get; set; }
+ ///
+ /// Gets or sets the date on which the token
+ /// will no longer be considered valid.
+ ///
+ public virtual DateTimeOffset? End { get; set; }
+
///
/// Gets or sets the hashed identifier associated
/// with the current token, if applicable.
@@ -63,6 +69,12 @@ namespace OpenIddict.Models
///
public virtual TKey Id { get; set; }
+ ///
+ /// Gets or sets the date on which the token
+ /// will start to be considered valid.
+ ///
+ public virtual DateTimeOffset? Start { get; set; }
+
///
/// Gets or sets the status of the current token.
///
diff --git a/src/OpenIddict/OpenIddictProvider.Serialization.cs b/src/OpenIddict/OpenIddictProvider.Serialization.cs
index 4ae3abbc..6133e488 100644
--- a/src/OpenIddict/OpenIddictProvider.Serialization.cs
+++ b/src/OpenIddict/OpenIddictProvider.Serialization.cs
@@ -14,6 +14,7 @@ using AspNet.Security.OpenIdConnect.Primitives;
using AspNet.Security.OpenIdConnect.Server;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using OpenIddict.Core;
@@ -31,8 +32,9 @@ namespace OpenIddict
return;
}
- var ticket = await ReceiveTokenAsync(context.AccessToken, options, context.Request,
- context.DataFormat, context.HttpContext.RequestAborted);
+ var ticket = await ReceiveTokenAsync(
+ context.AccessToken, options, context.HttpContext,
+ context.Request, context.DataFormat);
// If a valid ticket was returned by ReceiveTokenAsync(),
// force the OpenID Connect server middleware to use it.
@@ -54,8 +56,9 @@ namespace OpenIddict
return;
}
- var ticket = await ReceiveTokenAsync(context.AuthorizationCode, options, context.Request,
- context.DataFormat, context.HttpContext.RequestAborted);
+ var ticket = await ReceiveTokenAsync(
+ context.AuthorizationCode, options, context.HttpContext,
+ context.Request, context.DataFormat);
// If a valid ticket was returned by ReceiveTokenAsync(),
// force the OpenID Connect server middleware to use it.
@@ -77,8 +80,9 @@ namespace OpenIddict
return;
}
- var ticket = await ReceiveTokenAsync(context.RefreshToken, options, context.Request,
- context.DataFormat, context.HttpContext.RequestAborted);
+ var ticket = await ReceiveTokenAsync(
+ context.RefreshToken, options, context.HttpContext,
+ context.Request, context.DataFormat);
// If a valid ticket was returned by ReceiveTokenAsync(),
// force the OpenID Connect server middleware to use it.
@@ -94,9 +98,10 @@ namespace OpenIddict
public override async Task SerializeAccessToken([NotNull] SerializeAccessTokenContext context)
{
- var token = await CreateTokenAsync(OpenIdConnectConstants.TokenUsages.AccessToken,
- (OpenIddictOptions) context.Options, context.Request, context.DataFormat,
- context.Ticket, context.HttpContext.RequestAborted);
+ var token = await CreateTokenAsync(
+ OpenIdConnectConstants.TokenUsages.AccessToken,
+ context.Ticket, (OpenIddictOptions) context.Options,
+ context.HttpContext, context.Request, context.DataFormat);
// If a reference token was returned by CreateTokenAsync(),
// force the OpenID Connect server middleware to use it.
@@ -112,9 +117,10 @@ namespace OpenIddict
public override async Task SerializeAuthorizationCode([NotNull] SerializeAuthorizationCodeContext context)
{
- var token = await CreateTokenAsync(OpenIdConnectConstants.TokenUsages.AuthorizationCode,
- (OpenIddictOptions) context.Options, context.Request, context.DataFormat,
- context.Ticket, context.HttpContext.RequestAborted);
+ var token = await CreateTokenAsync(
+ OpenIdConnectConstants.TokenUsages.AuthorizationCode,
+ context.Ticket, (OpenIddictOptions) context.Options,
+ context.HttpContext, context.Request, context.DataFormat);
// If a reference token was returned by CreateTokenAsync(),
// force the OpenID Connect server middleware to use it.
@@ -130,9 +136,10 @@ namespace OpenIddict
public override async Task SerializeRefreshToken([NotNull] SerializeRefreshTokenContext context)
{
- var token = await CreateTokenAsync(OpenIdConnectConstants.TokenUsages.RefreshToken,
- (OpenIddictOptions) context.Options, context.Request, context.DataFormat,
- context.Ticket, context.HttpContext.RequestAborted);
+ var token = await CreateTokenAsync(
+ OpenIdConnectConstants.TokenUsages.RefreshToken,
+ context.Ticket, (OpenIddictOptions) context.Options,
+ context.HttpContext, context.Request, context.DataFormat);
// If a reference token was returned by CreateTokenAsync(),
// force the OpenID Connect server middleware to use it.
@@ -147,10 +154,10 @@ namespace OpenIddict
}
private async Task CreateTokenAsync(
- [NotNull] string type, [NotNull] OpenIddictOptions options,
+ [NotNull] string type, [NotNull] AuthenticationTicket ticket,
+ [NotNull] OpenIddictOptions options, [NotNull] HttpContext context,
[NotNull] OpenIdConnectRequest request,
- [NotNull] ISecureDataFormat format,
- [NotNull] AuthenticationTicket ticket, CancellationToken cancellationToken)
+ [NotNull] ISecureDataFormat format)
{
Debug.Assert(!(options.DisableTokenRevocation && options.UseReferenceTokens),
"Token revocation cannot be disabled when using reference tokens.");
@@ -202,14 +209,18 @@ namespace OpenIddict
hash = Convert.ToBase64String(algorithm.ComputeHash(bytes));
}
- token = await Tokens.CreateAsync(type, subject, hash, ciphertext, cancellationToken);
+ token = await Tokens.CreateAsync(type, subject, hash, ciphertext,
+ ticket.Properties.IssuedUtc,
+ ticket.Properties.ExpiresUtc, context.RequestAborted);
}
// Otherwise, only create a token metadata entry for authorization codes and refresh tokens.
else if (string.Equals(type, OpenIdConnectConstants.TokenUsages.AuthorizationCode, StringComparison.OrdinalIgnoreCase) ||
string.Equals(type, OpenIdConnectConstants.TokenUsages.RefreshToken, StringComparison.OrdinalIgnoreCase))
{
- token = await Tokens.CreateAsync(type, subject, cancellationToken);
+ token = await Tokens.CreateAsync(type, subject,
+ ticket.Properties.IssuedUtc,
+ ticket.Properties.ExpiresUtc, context.RequestAborted);
}
else
@@ -224,7 +235,7 @@ namespace OpenIddict
}
// Throw an exception if the token identifier can't be resolved.
- var identifier = await Tokens.GetIdAsync(token, cancellationToken);
+ var identifier = await Tokens.GetIdAsync(token, context.RequestAborted);
if (string.IsNullOrEmpty(identifier))
{
throw new InvalidOperationException("The unique key associated with a refresh token cannot be null or empty.");
@@ -238,22 +249,22 @@ namespace OpenIddict
// If the client application is known, associate it with the token.
if (!string.IsNullOrEmpty(request.ClientId))
{
- var application = await Applications.FindByClientIdAsync(request.ClientId, cancellationToken);
+ var application = await Applications.FindByClientIdAsync(request.ClientId, context.RequestAborted);
if (application == null)
{
throw new InvalidOperationException("The client application cannot be retrieved from the database.");
}
- var key = await Applications.GetIdAsync(application, cancellationToken);
+ var key = await Applications.GetIdAsync(application, context.RequestAborted);
- await Tokens.SetClientAsync(token, key, cancellationToken);
+ await Tokens.SetClientAsync(token, key, context.RequestAborted);
}
// If an authorization identifier was specified, bind it to the token.
if (ticket.HasProperty(OpenIddictConstants.Properties.AuthorizationId))
{
await Tokens.SetAuthorizationAsync(token,
- ticket.GetProperty(OpenIddictConstants.Properties.AuthorizationId), cancellationToken);
+ ticket.GetProperty(OpenIddictConstants.Properties.AuthorizationId), context.RequestAborted);
}
// Otherwise, create an ad-hoc authorization if the token is an authorization code.
@@ -261,21 +272,21 @@ namespace OpenIddict
{
Debug.Assert(!string.IsNullOrEmpty(request.ClientId), "The client identifier shouldn't be null.");
- var application = await Applications.FindByClientIdAsync(request.ClientId, cancellationToken);
+ var application = await Applications.FindByClientIdAsync(request.ClientId, context.RequestAborted);
if (application == null)
{
throw new InvalidOperationException("The client application cannot be retrieved from the database.");
}
var authorization = await Authorizations.CreateAsync(subject,
- await Applications.GetIdAsync(application, cancellationToken), request.GetScopes(), cancellationToken);
+ await Applications.GetIdAsync(application, context.RequestAborted), request.GetScopes(), context.RequestAborted);
if (authorization != null)
{
- var key = await Authorizations.GetIdAsync(authorization, cancellationToken);
+ var key = await Authorizations.GetIdAsync(authorization, context.RequestAborted);
ticket.SetProperty(OpenIddictConstants.Properties.AuthorizationId, key);
- await Tokens.SetAuthorizationAsync(token, key, cancellationToken);
+ await Tokens.SetAuthorizationAsync(token, key, context.RequestAborted);
}
}
@@ -291,8 +302,8 @@ namespace OpenIddict
private async Task ReceiveTokenAsync(
[NotNull] string value, [NotNull] OpenIddictOptions options,
- [NotNull] OpenIdConnectRequest request,
- [NotNull] ISecureDataFormat format, CancellationToken cancellationToken)
+ [NotNull] HttpContext context, [NotNull] OpenIdConnectRequest request,
+ [NotNull] ISecureDataFormat format)
{
if (!options.UseReferenceTokens)
{
@@ -319,7 +330,7 @@ namespace OpenIddict
// Retrieve the token entry from the database. If it
// cannot be found, assume the token is not valid.
- var token = await Tokens.FindByHashAsync(hash, cancellationToken);
+ var token = await Tokens.FindByHashAsync(hash, context.RequestAborted);
if (token == null)
{
Logger.LogInformation("The reference token corresponding to the '{Hash}' hashed " +
@@ -328,7 +339,7 @@ namespace OpenIddict
return null;
}
- var identifier = await Tokens.GetIdAsync(token, cancellationToken);
+ var identifier = await Tokens.GetIdAsync(token, context.RequestAborted);
if (string.IsNullOrEmpty(identifier))
{
Logger.LogWarning("The identifier associated with the received token cannot be retrieved. " +
@@ -339,7 +350,7 @@ 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, cancellationToken);
+ var ciphertext = await Tokens.GetCiphertextAsync(token, context.RequestAborted);
if (string.IsNullOrEmpty(ciphertext))
{
Logger.LogWarning("The ciphertext associated with the token '{Identifier}' cannot be retrieved. " +
@@ -353,7 +364,7 @@ namespace OpenIddict
{
Logger.LogWarning("The ciphertext associated with the token '{Identifier}' cannot be decrypted. " +
"This may indicate that the token entry is corrupted or tampered.",
- await Tokens.GetIdAsync(token, cancellationToken));
+ await Tokens.GetIdAsync(token, context.RequestAborted));
return null;
}
@@ -367,7 +378,7 @@ namespace OpenIddict
if (!ticket.HasProperty(OpenIddictConstants.Properties.AuthorizationId))
{
ticket.SetProperty(OpenIddictConstants.Properties.AuthorizationId,
- await Tokens.GetAuthorizationIdAsync(token, cancellationToken));
+ await Tokens.GetAuthorizationIdAsync(token, context.RequestAborted));
}
Logger.LogTrace("The reference token '{Identifier}' was successfully retrieved " +
diff --git a/test/OpenIddict.Tests/OpenIddictProviderTests.Authentication.cs b/test/OpenIddict.Tests/OpenIddictProviderTests.Authentication.cs
index 30e8e548..26a8a9f6 100644
--- a/test/OpenIddict.Tests/OpenIddictProviderTests.Authentication.cs
+++ b/test/OpenIddict.Tests/OpenIddictProviderTests.Authentication.cs
@@ -1,4 +1,5 @@
-using System.IO;
+using System;
+using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -559,7 +560,10 @@ namespace OpenIddict.Tests
{
var token = new OpenIddictToken();
- instance.Setup(mock => mock.CreateAsync(OpenIdConnectConstants.TokenTypeHints.AuthorizationCode, "Bob le Magnifique", It.IsAny()))
+ instance.Setup(mock => mock.CreateAsync(
+ OpenIdConnectConstants.TokenTypeHints.AuthorizationCode, "Bob le Magnifique",
+ It.IsAny(), It.IsAny(),
+ It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
diff --git a/test/OpenIddict.Tests/OpenIddictProviderTests.Serialization.cs b/test/OpenIddict.Tests/OpenIddictProviderTests.Serialization.cs
index 1f0d427a..6599cfa1 100644
--- a/test/OpenIddict.Tests/OpenIddictProviderTests.Serialization.cs
+++ b/test/OpenIddict.Tests/OpenIddictProviderTests.Serialization.cs
@@ -1,9 +1,11 @@
-using System.Collections;
+using System;
+using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using AspNet.Security.OpenIdConnect.Client;
using AspNet.Security.OpenIdConnect.Primitives;
+using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
@@ -43,20 +45,28 @@ namespace OpenIddict.Tests
// Assert
Assert.NotNull(response.AccessToken);
- Mock.Get(manager).Verify(mock => mock.CreateAsync(OpenIdConnectConstants.TokenTypeHints.AccessToken, "Bob le Magnifique", It.IsAny()), Times.Never());
+ Mock.Get(manager).Verify(mock => mock.CreateAsync(
+ OpenIdConnectConstants.TokenTypeHints.AccessToken, "Bob le Magnifique",
+ It.IsAny(), It.IsAny(),
+ It.IsAny()), Times.Never());
}
[Fact]
public async Task SerializeAccessToken_ReferenceAccessTokenIsCorrectlyPersisted()
{
// Arrange
- var token = new OpenIddictToken();
+ var token = new OpenIddictToken
+ {
+ End = new DateTimeOffset(2017, 01, 01, 00, 00, 00, TimeSpan.Zero),
+ Start = new DateTimeOffset(2017, 01, 02, 00, 00, 00, TimeSpan.Zero),
+ };
var manager = CreateTokenManager(instance =>
{
instance.Setup(mock => mock.CreateAsync(
OpenIdConnectConstants.TokenTypeHints.AccessToken, "Bob le Magnifique",
- It.IsNotNull(), It.IsNotNull(), It.IsAny()))
+ It.IsNotNull(), It.IsNotNull(),
+ token.Start, token.End, It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
@@ -68,6 +78,12 @@ namespace OpenIddict.Tests
builder.Services.AddSingleton(manager);
builder.UseReferenceTokens();
+
+ builder.Configure(options =>
+ {
+ options.SystemClock = Mock.Of(mock => mock.UtcNow == token.Start.Value);
+ options.AccessTokenLifetime = token.End.Value - token.Start.Value;
+ });
});
var client = new OpenIdConnectClient(server.CreateClient());
@@ -86,7 +102,8 @@ namespace OpenIddict.Tests
Mock.Get(manager).Verify(mock => mock.CreateAsync(
OpenIdConnectConstants.TokenTypeHints.AccessToken, "Bob le Magnifique",
- It.IsNotNull(), It.IsNotNull(), It.IsAny()), Times.Once());
+ It.IsNotNull(), It.IsNotNull(),
+ token.Start, token.End, It.IsAny()), Times.Once());
Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.Once());
}
@@ -100,7 +117,9 @@ namespace OpenIddict.Tests
{
instance.Setup(mock => mock.CreateAsync(
OpenIdConnectConstants.TokenTypeHints.AccessToken, "Bob le Magnifique",
- It.IsNotNull(), It.IsNotNull(), It.IsAny()))
+ It.IsNotNull(), It.IsNotNull(),
+ It.IsAny(), It.IsAny(),
+ It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
@@ -159,7 +178,9 @@ namespace OpenIddict.Tests
{
instance.Setup(mock => mock.CreateAsync(
OpenIdConnectConstants.TokenTypeHints.AccessToken, "Bob le Magnifique",
- It.IsNotNull(), It.IsNotNull(), It.IsAny()))
+ It.IsNotNull(), It.IsNotNull(),
+ It.IsAny(), It.IsAny(),
+ It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
@@ -245,18 +266,27 @@ namespace OpenIddict.Tests
// Assert
Assert.NotNull(response.Code);
- Mock.Get(manager).Verify(mock => mock.CreateAsync(OpenIdConnectConstants.TokenTypeHints.AuthorizationCode, "Bob le Magnifique", It.IsAny()), Times.Never());
+ Mock.Get(manager).Verify(mock => mock.CreateAsync(
+ OpenIdConnectConstants.TokenTypeHints.AuthorizationCode, "Bob le Magnifique",
+ It.IsAny(), It.IsAny(),
+ It.IsAny()), Times.Never());
}
[Fact]
public async Task SerializeAuthorizationCode_AuthorizationCodeIsCorrectlyPersisted()
{
// Arrange
- var token = new OpenIddictToken();
+ var token = new OpenIddictToken
+ {
+ End = new DateTimeOffset(2017, 01, 02, 00, 00, 00, TimeSpan.Zero),
+ Start = new DateTimeOffset(2017, 01, 01, 00, 00, 00, TimeSpan.Zero),
+ };
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.CreateAsync(OpenIdConnectConstants.TokenTypeHints.AuthorizationCode, "Bob le Magnifique", It.IsAny()))
+ instance.Setup(mock => mock.CreateAsync(
+ OpenIdConnectConstants.TokenTypeHints.AuthorizationCode, "Bob le Magnifique",
+ token.Start, token.End, It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
@@ -283,6 +313,12 @@ namespace OpenIddict.Tests
}));
builder.Services.AddSingleton(manager);
+
+ builder.Configure(options =>
+ {
+ options.SystemClock = Mock.Of(mock => mock.UtcNow == token.Start.Value);
+ options.AuthorizationCodeLifetime = token.End.Value - token.Start.Value;
+ });
});
var client = new OpenIdConnectClient(server.CreateClient());
@@ -298,7 +334,9 @@ namespace OpenIddict.Tests
// Assert
Assert.NotNull(response.Code);
- Mock.Get(manager).Verify(mock => mock.CreateAsync(OpenIdConnectConstants.TokenTypeHints.AuthorizationCode, "Bob le Magnifique", It.IsAny()), Times.Once());
+ Mock.Get(manager).Verify(mock => mock.CreateAsync(
+ OpenIdConnectConstants.TokenTypeHints.AuthorizationCode, "Bob le Magnifique",
+ token.Start, token.End, It.IsAny()), Times.Once());
Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.Once());
}
@@ -306,13 +344,18 @@ namespace OpenIddict.Tests
public async Task SerializeAuthorizationCode_ReferenceAuthorizationCodeIsCorrectlyPersisted()
{
// Arrange
- var token = new OpenIddictToken();
+ var token = new OpenIddictToken
+ {
+ End = new DateTimeOffset(2017, 01, 02, 00, 00, 00, TimeSpan.Zero),
+ Start = new DateTimeOffset(2017, 01, 01, 00, 00, 00, TimeSpan.Zero),
+ };
var manager = CreateTokenManager(instance =>
{
instance.Setup(mock => mock.CreateAsync(
OpenIdConnectConstants.TokenTypeHints.AuthorizationCode, "Bob le Magnifique",
- It.IsNotNull(), It.IsNotNull(), It.IsAny()))
+ It.IsNotNull(), It.IsNotNull(),
+ token.Start, token.End, It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
@@ -341,6 +384,12 @@ namespace OpenIddict.Tests
builder.Services.AddSingleton(manager);
builder.UseReferenceTokens();
+
+ builder.Configure(options =>
+ {
+ options.SystemClock = Mock.Of(mock => mock.UtcNow == token.Start.Value);
+ options.AuthorizationCodeLifetime = token.End.Value - token.Start.Value;
+ });
});
var client = new OpenIdConnectClient(server.CreateClient());
@@ -356,8 +405,10 @@ namespace OpenIddict.Tests
// Assert
Assert.NotNull(response.Code);
- Mock.Get(manager).Verify(mock => mock.CreateAsync(OpenIdConnectConstants.TokenTypeHints.AuthorizationCode,
- "Bob le Magnifique", It.IsNotNull(), It.IsNotNull(), It.IsAny()), Times.Once());
+ Mock.Get(manager).Verify(mock => mock.CreateAsync(
+ OpenIdConnectConstants.TokenTypeHints.AuthorizationCode, "Bob le Magnifique",
+ It.IsNotNull(), It.IsNotNull(),
+ token.Start, token.End, It.IsAny()), Times.Once());
Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.Once());
}
@@ -369,7 +420,10 @@ namespace OpenIddict.Tests
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.CreateAsync(OpenIdConnectConstants.TokenTypeHints.AuthorizationCode, "Bob le Magnifique", It.IsAny()))
+ instance.Setup(mock => mock.CreateAsync(
+ OpenIdConnectConstants.TokenTypeHints.AuthorizationCode, "Bob le Magnifique",
+ It.IsAny(), It.IsAny(),
+ It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
@@ -428,7 +482,10 @@ namespace OpenIddict.Tests
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.CreateAsync(OpenIdConnectConstants.TokenTypeHints.AuthorizationCode, "Bob le Magnifique", It.IsAny()))
+ instance.Setup(mock => mock.CreateAsync(
+ OpenIdConnectConstants.TokenTypeHints.AuthorizationCode, "Bob le Magnifique",
+ It.IsAny(), It.IsAny(),
+ It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
@@ -525,7 +582,10 @@ namespace OpenIddict.Tests
builder.Services.AddSingleton(CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.CreateAsync(OpenIdConnectConstants.TokenTypeHints.AuthorizationCode, "Bob le Magnifique", It.IsAny()))
+ instance.Setup(mock => mock.CreateAsync(
+ OpenIdConnectConstants.TokenTypeHints.AuthorizationCode, "Bob le Magnifique",
+ It.IsAny(), It.IsAny(),
+ It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
@@ -581,18 +641,27 @@ namespace OpenIddict.Tests
// Assert
Assert.NotNull(response.RefreshToken);
- Mock.Get(manager).Verify(mock => mock.CreateAsync(OpenIdConnectConstants.TokenTypeHints.RefreshToken, "Bob le Magnifique", It.IsAny()), Times.Never());
+ Mock.Get(manager).Verify(mock => mock.CreateAsync(
+ OpenIdConnectConstants.TokenTypeHints.RefreshToken, "Bob le Magnifique",
+ It.IsAny(), It.IsAny(),
+ It.IsAny()), Times.Never());
}
[Fact]
public async Task SerializeRefreshToken_RefreshTokenIsCorrectlyPersisted()
{
// Arrange
- var token = new OpenIddictToken();
+ var token = new OpenIddictToken
+ {
+ End = new DateTimeOffset(2017, 01, 02, 00, 00, 00, TimeSpan.Zero),
+ Start = new DateTimeOffset(2017, 01, 01, 00, 00, 00, TimeSpan.Zero)
+ };
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.CreateAsync(OpenIdConnectConstants.TokenTypeHints.RefreshToken, "Bob le Magnifique", It.IsAny()))
+ instance.Setup(mock => mock.CreateAsync(
+ OpenIdConnectConstants.TokenTypeHints.RefreshToken, "Bob le Magnifique",
+ token.Start, token.End, It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
@@ -602,6 +671,12 @@ namespace OpenIddict.Tests
var server = CreateAuthorizationServer(builder =>
{
builder.Services.AddSingleton(manager);
+
+ builder.Configure(options =>
+ {
+ options.SystemClock = Mock.Of(mock => mock.UtcNow == token.Start.Value);
+ options.RefreshTokenLifetime = token.End.Value - token.Start.Value;
+ });
});
var client = new OpenIdConnectClient(server.CreateClient());
@@ -618,7 +693,9 @@ namespace OpenIddict.Tests
// Assert
Assert.NotNull(response.RefreshToken);
- Mock.Get(manager).Verify(mock => mock.CreateAsync(OpenIdConnectConstants.TokenTypeHints.RefreshToken, "Bob le Magnifique", It.IsAny()), Times.Once());
+ Mock.Get(manager).Verify(mock => mock.CreateAsync(
+ OpenIdConnectConstants.TokenTypeHints.RefreshToken, "Bob le Magnifique",
+ token.Start, token.End, It.IsAny()), Times.Once());
Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.Once());
}
@@ -626,13 +703,18 @@ namespace OpenIddict.Tests
public async Task SerializeRefreshToken_ReferenceRefreshTokenIsCorrectlyPersisted()
{
// Arrange
- var token = new OpenIddictToken();
+ var token = new OpenIddictToken
+ {
+ End = new DateTimeOffset(2017, 01, 02, 00, 00, 00, TimeSpan.Zero),
+ Start = new DateTimeOffset(2017, 01, 01, 00, 00, 00, TimeSpan.Zero),
+ };
var manager = CreateTokenManager(instance =>
{
instance.Setup(mock => mock.CreateAsync(
OpenIdConnectConstants.TokenTypeHints.RefreshToken, "Bob le Magnifique",
- It.IsNotNull(), It.IsNotNull(), It.IsAny()))
+ It.IsNotNull(), It.IsNotNull(),
+ token.Start, token.End, It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
@@ -644,6 +726,12 @@ namespace OpenIddict.Tests
builder.Services.AddSingleton(manager);
builder.UseReferenceTokens();
+
+ builder.Configure(options =>
+ {
+ options.SystemClock = Mock.Of(mock => mock.UtcNow == token.Start.Value);
+ options.RefreshTokenLifetime = token.End.Value - token.Start.Value;
+ });
});
var client = new OpenIdConnectClient(server.CreateClient());
@@ -662,7 +750,8 @@ namespace OpenIddict.Tests
Mock.Get(manager).Verify(mock => mock.CreateAsync(
OpenIdConnectConstants.TokenTypeHints.RefreshToken, "Bob le Magnifique",
- It.IsNotNull(), It.IsNotNull(), It.IsAny()), Times.Once());
+ It.IsNotNull(), It.IsNotNull(),
+ token.Start, token.End, It.IsAny()), Times.Once());
Mock.Get(manager).Verify(mock => mock.GetIdAsync(token, It.IsAny()), Times.Once());
}
@@ -674,7 +763,10 @@ namespace OpenIddict.Tests
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.CreateAsync(OpenIdConnectConstants.TokenTypeHints.RefreshToken, "Bob le Magnifique", It.IsAny()))
+ instance.Setup(mock => mock.CreateAsync(
+ OpenIdConnectConstants.TokenTypeHints.RefreshToken, "Bob le Magnifique",
+ It.IsAny(), It.IsAny(),
+ It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))
@@ -729,7 +821,10 @@ namespace OpenIddict.Tests
var manager = CreateTokenManager(instance =>
{
- instance.Setup(mock => mock.CreateAsync(OpenIdConnectConstants.TokenTypeHints.RefreshToken, "Bob le Magnifique", It.IsAny()))
+ instance.Setup(mock => mock.CreateAsync(
+ OpenIdConnectConstants.TokenTypeHints.RefreshToken, "Bob le Magnifique",
+ It.IsAny(), It.IsAny(),
+ It.IsAny()))
.ReturnsAsync(token);
instance.Setup(mock => mock.GetIdAsync(token, It.IsAny()))