Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,16 @@ public async Task<ActionResult> Authorize()
{
var sessions = await _sessionManager.FindAsync(
query: (
Subject : user.Id,
LoginId : result.Identity.GetClaim("login_id"),
ApplicationId: await _applicationManager.GetIdAsync(application),
Status : Statuses.Valid)).ToListAsync();
Subject : user.Id,
LoginId : result.Identity.GetClaim("login_id"),
ApplicationId : await _applicationManager.GetIdAsync(application),
AuthorizationId: await _authorizationManager.GetIdAsync(authorization),
Status : Statuses.Valid)).ToListAsync();

var session = sessions.LastOrDefault() ?? await _sessionManager.CreateAsync(new()
{
ApplicationId = await _applicationManager.GetIdAsync(application),
AuthorizationId = await _authorizationManager.GetIdAsync(authorization),
LoginId = result.Identity.GetClaim("login_id"),
Subject = user.Id
});
Expand Down Expand Up @@ -354,14 +356,16 @@ public async Task<ActionResult> Accept()
{
var sessions = await _sessionManager.FindAsync(
query: (
Subject : user.Id,
LoginId : result.Identity.GetClaim("login_id"),
ApplicationId: await _applicationManager.GetIdAsync(application),
Status : Statuses.Valid)).ToListAsync();
Subject : user.Id,
LoginId : result.Identity.GetClaim("login_id"),
ApplicationId : await _applicationManager.GetIdAsync(application),
AuthorizationId: await _authorizationManager.GetIdAsync(authorization),
Status : Statuses.Valid)).ToListAsync();

var session = sessions.LastOrDefault() ?? await _sessionManager.CreateAsync(new()
{
ApplicationId = await _applicationManager.GetIdAsync(application),
AuthorizationId = await _authorizationManager.GetIdAsync(authorization),
LoginId = result.Identity.GetClaim("login_id"),
Subject = user.Id
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,14 +233,16 @@ public async Task<IActionResult> Authorize()
{
var sessions = await _sessionManager.FindAsync(
query: (
Subject : await _userManager.GetUserIdAsync(user),
LoginId : result.Principal.GetClaim("login_id"),
ApplicationId: await _applicationManager.GetIdAsync(application),
Status : Statuses.Valid)).ToListAsync();
Subject : await _userManager.GetUserIdAsync(user),
LoginId : result.Principal.GetClaim("login_id"),
ApplicationId : await _applicationManager.GetIdAsync(application),
AuthorizationId: await _authorizationManager.GetIdAsync(authorization),
Status : Statuses.Valid)).ToListAsync();

var session = sessions.LastOrDefault() ?? await _sessionManager.CreateAsync(new()
{
ApplicationId = await _applicationManager.GetIdAsync(application),
AuthorizationId = await _authorizationManager.GetIdAsync(authorization),
LoginId = result.Principal.GetClaim("login_id"),
Subject = await _userManager.GetUserIdAsync(user)
});
Expand Down Expand Up @@ -365,14 +367,16 @@ public async Task<IActionResult> Accept()
{
var sessions = await _sessionManager.FindAsync(
query: (
Subject : await _userManager.GetUserIdAsync(user),
LoginId : User.GetClaim("login_id"),
ApplicationId: await _applicationManager.GetIdAsync(application),
Status : Statuses.Valid)).ToListAsync();
Subject : await _userManager.GetUserIdAsync(user),
LoginId : User.GetClaim("login_id"),
ApplicationId : await _applicationManager.GetIdAsync(application),
AuthorizationId: await _authorizationManager.GetIdAsync(authorization),
Status : Statuses.Valid)).ToListAsync();

var session = sessions.LastOrDefault() ?? await _sessionManager.CreateAsync(new()
{
ApplicationId = await _applicationManager.GetIdAsync(application),
AuthorizationId = await _authorizationManager.GetIdAsync(authorization),
LoginId = User.GetClaim("login_id"),
Subject = await _userManager.GetUserIdAsync(user)
});
Expand Down
7 changes: 4 additions & 3 deletions sandbox/OpenIddict.Sandbox.AspNetCore.Server/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -320,10 +320,11 @@
// For applications that need immediate access token or authorization
// revocation, the database entry of the received tokens and their
// associated authorizations can be validated for each API call.
// Enabling these options may have a negative impact on performance.
//
// options.EnableAuthorizationEntryValidation();
// options.EnableTokenEntryValidation();
// Note: enabling these options may have a negative impact on performance.
options.EnableAuthorizationEntryValidation()
.EnableSessionEntryValidation()
.EnableTokenEntryValidation();
});

builder.Services.AddTransient<IEmailSender, AuthMessageSender>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public interface IOpenIddictSessionCache<TSession> where TSession : class
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The sessions corresponding to the criteria.</returns>
IAsyncEnumerable<TSession> FindAsync(
(string? Subject, string? LoginId, string? ApplicationId, string? Status) query, CancellationToken cancellationToken);
(string? Subject, string? LoginId, string? ApplicationId, string? AuthorizationId, string? Status) query, CancellationToken cancellationToken);

/// <summary>
/// Retrieves the list of sessions corresponding to the specified application identifier.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ public class OpenIddictTokenDescriptor
/// </remarks>
public string? ReferenceId { get; set; }

/// <summary>
/// Gets or sets the identifier of the session associated with the token.
/// </summary>
public string? SessionId { get; set; }

/// <summary>
/// Gets or sets the status of the token.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ ValueTask<long> CountAsync<TState, TResult>(
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The sessions corresponding to the criteria.</returns>
IAsyncEnumerable<object> FindAsync(
(string? Subject, string? LoginId, string? ApplicationId, string? Status) query,
(string? Subject, string? LoginId, string? ApplicationId, string? AuthorizationId, string? Status) query,
CancellationToken cancellationToken = default);

/// <summary>
Expand Down Expand Up @@ -258,6 +258,15 @@ IAsyncEnumerable<object> FindAsync(
/// </returns>
ValueTask<string?> GetSubjectAsync(object session, CancellationToken cancellationToken = default);

/// <summary>
/// Determines whether a given session has the specified status.
/// </summary>
/// <param name="session">The session.</param>
/// <param name="status">The expected status.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns><see langword="true"/> if the session has the specified status, <see langword="false"/> otherwise.</returns>
ValueTask<bool> HasStatusAsync(object session, string status, CancellationToken cancellationToken = default);

/// <summary>
/// Executes the specified query and returns all the corresponding elements.
/// </summary>
Expand Down Expand Up @@ -313,6 +322,18 @@ IAsyncEnumerable<TResult> ListAsync<TState, TResult>(
/// </returns>
ValueTask PopulateAsync(object session, OpenIddictSessionDescriptor descriptor, CancellationToken cancellationToken = default);

/// <summary>
/// Removes the sessions that are marked as invalid and don't have any token attached.
/// Only sessions created before the specified <paramref name="threshold"/> are removed.
/// </summary>
/// <remarks>
/// Since sessions with tokens still attached are not deleted, tokens should always be pruned first.
/// </remarks>
/// <param name="threshold">The date before which sessions are not pruned.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The number of sessions that were removed.</returns>
ValueTask<long> PruneAsync(DateTimeOffset threshold, CancellationToken cancellationToken);

/// <summary>
/// Updates an existing session.
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions src/OpenIddict.Abstractions/Managers/IOpenIddictTokenManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,17 @@ IAsyncEnumerable<object> FindAsync(
/// </returns>
ValueTask<string?> GetReferenceIdAsync(object token, CancellationToken cancellationToken = default);

/// <summary>
/// Retrieves the optional session identifier associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the session identifier associated with the token.
/// </returns>
ValueTask<string?> GetSessionIdAsync(object token, CancellationToken cancellationToken = default);

/// <summary>
/// Retrieves the status associated with a token.
/// </summary>
Expand Down
31 changes: 12 additions & 19 deletions src/OpenIddict.Abstractions/OpenIddictResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -537,10 +537,7 @@ Reference the 'OpenIddict.Validation.SystemNetHttp' package and call 'services.A
<value>The client secret cannot be null or empty when using introspection. Alternatively, one or multiple signing credentials can be registered and used as TLS client certificates or to produce client assertions if the authorization server supports it.</value>
</data>
<data name="ID0133" xml:space="preserve">
<value>Authorization entry validation cannot be enabled when using introspection.</value>
</data>
<data name="ID0134" xml:space="preserve">
<value>Token entry validation cannot be enabled when using introspection.</value>
<value>Authorization entry, session entry and token entry validation cannot be enabled when using introspection.</value>
</data>
<data name="ID0135" xml:space="preserve">
<value>A discovery client must be registered when using server discovery.
Expand All @@ -557,7 +554,7 @@ Reference the 'OpenIddict.Validation.SystemNetHttp' package and call 'services.A
This may indicate that it was not properly registered in the dependency injection container. To register an event handler, use 'services.AddOpenIddict().AddValidation().AddEventHandler()'.</value>
</data>
<data name="ID0139" xml:space="preserve">
<value>The core services must be registered when enabling token entry validation.
<value>The core services must be registered when enabling authorization entry, session entry or token entry validation.
To register the OpenIddict core services, reference the 'OpenIddict.Core' package and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.</value>
</data>
<data name="ID0140" xml:space="preserve">
Expand All @@ -566,10 +563,6 @@ To register the OpenIddict core services, reference the 'OpenIddict.Core' packag
<data name="ID0141" xml:space="preserve">
<value>An unknown error occurred while introspecting the access token.</value>
</data>
<data name="ID0142" xml:space="preserve">
<value>The core services must be registered when enabling authorization entry validation.
To register the OpenIddict core services, reference the 'OpenIddict.Core' package and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.</value>
</data>
<data name="ID0143" xml:space="preserve">
<value>The URI cannot be null or empty.</value>
</data>
Expand Down Expand Up @@ -855,17 +848,8 @@ Reload the entity from the database and retry the operation.</value>
<value>An error occurred while trying to create a new entity instance.
Make sure that the entity is not abstract and has a public parameterless constructor or create a custom store that overrides 'InstantiateAsync()' to use a custom factory.</value>
</data>
<data name="ID0243" xml:space="preserve">
<value>An error occurred while pruning authorizations.</value>
</data>
<data name="ID0244" xml:space="preserve">
<value>The application matching the specified identifier cannot be found in the change tracker or in the database.</value>
</data>
<data name="ID0249" xml:space="preserve">
<value>An error occurred while pruning tokens.</value>
</data>
<data name="ID0251" xml:space="preserve">
<value>The authorization matching the specified identifier cannot be found in the change tracker or in the database.</value>
<value>The entity matching the specified identifier cannot be found in the change tracker or in the database.</value>
</data>
<data name="ID0253" xml:space="preserve">
<value>No Entity Framework Core context was configured to be used with OpenIddict.
Expand Down Expand Up @@ -2436,6 +2420,9 @@ To use a custom policy relying on the system store, set 'OpenIddictServerOptions
<data name="ID2209" xml:space="preserve">
<value>The login identifier cannot be null or empty and must match the value used to represent the user session.</value>
</data>
<data name="ID2210" xml:space="preserve">
<value>The session associated with the token is no longer valid.</value>
</data>
<data name="ID4000" xml:space="preserve">
<value>The '{0}' parameter shouldn't be null or empty at this point.</value>
</data>
Expand Down Expand Up @@ -2502,6 +2489,9 @@ To use a custom policy relying on the system store, set 'OpenIddictServerOptions
<data name="ID4021" xml:space="preserve">
<value>The length of the memory span ({0}) doesn't match the expected value ({1}).</value>
</data>
<data name="ID4022" xml:space="preserve">
<value>The session identifier shouldn't be null or empty at this point.</value>
</data>
<data name="ID6000" xml:space="preserve">
<value>An error occurred while validating the token '{Token}'.</value>
</data>
Expand Down Expand Up @@ -3294,6 +3284,9 @@ This may indicate that the hashed entry is corrupted or malformed.</value>
<data name="ID6296" xml:space="preserve">
<value>A signing key of type '{Type}' was ignored because its ML-DSA public key couldn't be extracted.</value>
</data>
<data name="ID6297" xml:space="preserve">
<value>The session '{Identifier}' was no longer valid.</value>
</data>
<data name="ID8000" xml:space="preserve">
<value>https://documentation.openiddict.com/errors/{0}</value>
</data>
Expand Down
14 changes: 13 additions & 1 deletion src/OpenIddict.Abstractions/Stores/IOpenIddictSessionStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ ValueTask<long> CountAsync<TState, TResult>(
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The sessions corresponding to the criteria.</returns>
IAsyncEnumerable<TSession> FindAsync(
(string? Subject, string? LoginId, string? ApplicationId, string? Status) query, CancellationToken cancellationToken);
(string? Subject, string? LoginId, string? ApplicationId, string? AuthorizationId, string? Status) query, CancellationToken cancellationToken);

/// <summary>
/// Retrieves the list of sessions corresponding to the specified application identifier.
Expand Down Expand Up @@ -245,6 +245,18 @@ IAsyncEnumerable<TResult> ListAsync<TState, TResult>(
Func<IQueryable<TSession>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken);

/// <summary>
/// Removes the sessions that are marked as invalid and don't have any token attached.
/// Only sessions created before the specified <paramref name="threshold"/> are removed.
/// </summary>
/// <remarks>
/// Since sessions with tokens still attached are not deleted, tokens should always be pruned first.
/// </remarks>
/// <param name="threshold">The date before which sessions are not pruned.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The number of sessions that were removed.</returns>
ValueTask<long> PruneAsync(DateTimeOffset threshold, CancellationToken cancellationToken);

/// <summary>
/// Sets the application identifier associated with a session.
/// </summary>
Expand Down
20 changes: 20 additions & 0 deletions src/OpenIddict.Abstractions/Stores/IOpenIddictTokenStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,17 @@ IAsyncEnumerable<TToken> FindAsync(
/// </returns>
ValueTask<string?> GetReferenceIdAsync(TToken token, CancellationToken cancellationToken);

/// <summary>
/// Retrieves the optional session identifier associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the session identifier associated with the token.
/// </returns>
ValueTask<string?> GetSessionIdAsync(TToken token, CancellationToken cancellationToken);

/// <summary>
/// Retrieves the status associated with a token.
/// </summary>
Expand Down Expand Up @@ -359,6 +370,15 @@ IAsyncEnumerable<TResult> ListAsync<TState, TResult>(
/// <returns>A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
ValueTask SetAuthorizationIdAsync(TToken token, string? identifier, CancellationToken cancellationToken);

/// <summary>
/// Sets the session identifier associated with a token.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="identifier">The unique identifier associated with the token.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.</returns>
ValueTask SetSessionIdAsync(TToken token, string? identifier, CancellationToken cancellationToken);

/// <summary>
/// Sets the creation date associated with a token.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/OpenIddict.Core/Caches/OpenIddictSessionCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public void Dispose()

/// <inheritdoc/>
public async IAsyncEnumerable<TSession> FindAsync(
(string? Subject, string? LoginId, string? ApplicationId, string? Status) query,
(string? Subject, string? LoginId, string? ApplicationId, string? AuthorizationId, string? Status) query,
[EnumeratorCancellation] CancellationToken cancellationToken)
{
// Note: this method is only partially cached.
Expand Down
Loading
Loading