Table of Contents

Class DapperServerSideSessionStore

Namespace
Fdyay.IdentityServer.Dapper.Stores
Assembly
Fdyay.IdentityServer.Dapper.dll

Dapper-backed server-side session store.

public sealed class DapperServerSideSessionStore : IServerSideSessionStore
Inheritance
DapperServerSideSessionStore
Implements
Inherited Members

Remarks

The in-memory store is development-only, and the two ways it falls short are both invisible in development: sessions do not survive a restart, so every deploy signs everyone out, and they are not shared between instances, so the ticket key in the cookie resolves on the instance that wrote it and nowhere else. The second presents as users being signed out intermittently, whenever the load balancer moves them, which is the worst way for it to present. This is the store that makes server-side sessions usable in production.

Constructors

DapperServerSideSessionStore(IDbConnectionFactory)

Creates a session store over the ServerSideSessions table, on the system clock.

public DapperServerSideSessionStore(IDbConnectionFactory connectionFactory)

Parameters

connectionFactory IDbConnectionFactory

Opens a connection for each operation and supplies the dialect's upsert and paging clause.

DapperServerSideSessionStore(IDbConnectionFactory, TimeProvider)

Creates a session store over the ServerSideSessions table, on the server's clock.

public DapperServerSideSessionStore(IDbConnectionFactory connectionFactory, TimeProvider time)

Parameters

connectionFactory IDbConnectionFactory

Opens a connection for each operation and supplies the dialect's upsert and paging clause.

time TimeProvider

The clock the expiry sweep judges Expires against — the server's, as every other store here reads.

Remarks

Since 0.175.0, and the one the container builds; until then the sweep read UtcNow.

Methods

CreateSessionAsync(ServerSideSession, CancellationToken)

Stores a session under its Key, replacing any already held under that key.

public Task CreateSessionAsync(ServerSideSession session, CancellationToken cancellationToken = default)

Parameters

session ServerSideSession

The session.

cancellationToken CancellationToken

Cancels the write.

Returns

Task

Remarks

An upsert rather than an insert, because that is what the in-memory store does. Two implementations of one interface that disagree about a re-used key disagree only in production, where the store is not the in-memory one.

DeleteSessionAsync(string, CancellationToken)

Removes the session stored under a key. A key with nothing stored under it is not an error.

public Task DeleteSessionAsync(string key, CancellationToken cancellationToken = default)

Parameters

key string

The session's Key.

cancellationToken CancellationToken

Cancels the removal.

Returns

Task

Remarks

Deletes the ServerSideSessions row whose SessionKey matches. A miss deletes nothing and is not an error.

Exceptions

ArgumentException

key is null or empty.

DeleteSessionsAsync(SessionFilter, CancellationToken)

Ends every session matching the filter.

public Task DeleteSessionsAsync(SessionFilter filter, CancellationToken cancellationToken = default)

Parameters

filter SessionFilter
cancellationToken CancellationToken

Returns

Task

Remarks

Deletes the ServerSideSessions rows matching the filter's subject id and session id, whichever it sets. No match deletes nothing and is not an error.

Exceptions

ArgumentNullException

filter is null.

ArgumentException

filter names neither a subject nor a session, which would otherwise end every session.

GetAndRemoveExpiredSessionsAsync(int, CancellationToken)

Removes sessions past their expiry and returns them, so a caller can act on what it removed.

public Task<IReadOnlyCollection<ServerSideSession>> GetAndRemoveExpiredSessionsAsync(int count, CancellationToken cancellationToken = default)

Parameters

count int
cancellationToken CancellationToken

Returns

Task<IReadOnlyCollection<ServerSideSession>>

Remarks

Returns rather than merely deletes because an expired session still has clients that were signed in to it, and they are owed a back-channel logout. A sweep that deleted silently would leave every relying party believing a session that ended hours ago is still live.

GetSessionAsync(string, CancellationToken)

The session stored under a key, or null.

public Task<ServerSideSession?> GetSessionAsync(string key, CancellationToken cancellationToken = default)

Parameters

key string

The session's Key.

cancellationToken CancellationToken

Cancels the read.

Returns

Task<ServerSideSession>

The session, or null when none is stored under that key.

Remarks

Reads the ServerSideSessions row whose SessionKey matches. A miss returns null; an expired row is returned as stored, for the caller to judge.

Exceptions

ArgumentException

key is null or empty.

GetSessionsAsync(SessionFilter, CancellationToken)

Every session matching the filter.

public Task<IReadOnlyCollection<ServerSideSession>> GetSessionsAsync(SessionFilter filter, CancellationToken cancellationToken = default)

Parameters

filter SessionFilter
cancellationToken CancellationToken

Returns

Task<IReadOnlyCollection<ServerSideSession>>

Remarks

Reads the ServerSideSessions rows matching the filter's subject id and session id, whichever it sets, expired ones included. No match is an empty collection.

Exceptions

ArgumentNullException

filter is null.

ArgumentException

filter names neither a subject nor a session.

QuerySessionsAsync(SessionQuery, CancellationToken)

A page of sessions, for an administrative list.

public Task<QueryResult<ServerSideSession>> QuerySessionsAsync(SessionQuery query, CancellationToken cancellationToken = default)

Parameters

query SessionQuery
cancellationToken CancellationToken

Returns

Task<QueryResult<ServerSideSession>>

Remarks

Counts and then pages the ServerSideSessions rows, filtered when Filter is set and ordered by Created then SessionKey. A page or page size below one is treated as one. A page past the end returns no results alongside the true total.

Exceptions

ArgumentNullException

query is null.

UpdateSessionAsync(ServerSideSession, CancellationToken)

Replaces the session stored under its Key, or stores it when none is.

public Task UpdateSessionAsync(ServerSideSession session, CancellationToken cancellationToken = default)

Parameters

session ServerSideSession

The session as it now stands.

cancellationToken CancellationToken

Cancels the write.

Returns

Task

Remarks

Also an upsert, and deliberately not an UPDATE that no-ops on a missing row. The guard against resurrecting a revoked session lives in ServerSideTicketStore.RenewAsync, which reads before it writes; putting a second, differently-shaped guard here would make the two stores disagree about what updating an absent key means.