Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
35e5414
feat: implement server side session store to be used when storing aut…
jhbritton-RSK Jul 20, 2026
c13e871
feat: implement mapping auth ticket to a serialisable form
jhbritton-RSK Jul 21, 2026
7fe083c
feat: implementing ITicketStore implementation
jhbritton-RSK Jul 22, 2026
9e8c19d
feat: adding cofiguration of server side sessions using extention
jhbritton-RSK Jul 27, 2026
3a1778a
feat: added telemetry calls to server side session stores
jhbritton-RSK Jul 28, 2026
a9f72f4
fix: create on renew when no existing session
jhbritton-RSK Jul 28, 2026
b671b2c
fix: added handling of protection envolope
jhbritton-RSK Jul 28, 2026
00f7b4c
fix: added name and role claim type when deserializing claim principl…
jhbritton-RSK Jul 29, 2026
a34fe35
fix: missing XML docs
jhbritton-RSK Jul 29, 2026
a8700ab
feat: added in memory session store to allow for integration tests an…
jhbritton-RSK Jul 29, 2026
c13b357
feat: server side session integration tests [WIP]
jhbritton-RSK Jul 29, 2026
2426413
test: added integration tests to check for session creation and removal
jhbritton-RSK Jul 30, 2026
48b1c9e
fix: correcting warnings
jhbritton-RSK Jul 30, 2026
e3344e5
pr: action comments from PR review, missing tests, superfluous tags o…
jhbritton-RSK Aug 4, 2026
dbe19f7
Merge pull request #52 from RockSolidKnowledge/feat/35-session-store
jhbritton-RSK Aug 20, 2026
f20173d
pr: action comments from PR review, missing tests, superfluous tags o…
jhbritton-RSK Aug 4, 2026
d5858da
feat: added settings for backchannel logout/user session coordination
jhbritton-RSK Aug 10, 2026
64f6633
feat: added support for multiple client ids and types for persistent …
jhbritton-RSK Aug 10, 2026
74e6799
feat: implemented user session event service for handling logout and …
jhbritton-RSK Aug 11, 2026
344208b
feat: added telemetry and logging with input validation
jhbritton-RSK Aug 11, 2026
d847b5c
feat: link up lohout event and handler created in user session events…
jhbritton-RSK Aug 11, 2026
a7da644
fix: broken tests due to missing dependency when server side sessions…
jhbritton-RSK Aug 25, 2026
fb9fb7a
pr: correcting issues spotted in review
jhbritton-RSK Aug 28, 2026
94e9f4a
Merge pull request #58 from RockSolidKnowledge/feat/38-backchannel-lo…
jhbritton-RSK Sep 1, 2026
2352197
pr: correcting issues spotted in review
jhbritton-RSK Aug 28, 2026
da28f56
feat: added filter methods for session stores
jhbritton-RSK Aug 24, 2026
898a9da
feat: added method for handling token validation for server-side sess…
jhbritton-RSK Aug 24, 2026
82d10d4
feat: add event handler for checking for ForceCookieRefresh flag
jhbritton-RSK Aug 27, 2026
00a8d9c
feat: working on triggering session validation from token validators
jhbritton-RSK Aug 27, 2026
aa5ff78
fix: missing comments, and comment corrections
jhbritton-RSK Aug 28, 2026
5dff924
feat: registered token validators for server side sessions
jhbritton-RSK Aug 28, 2026
32463c8
fix: correct ticket store registration in DI to use extended interface
jhbritton-RSK Sep 2, 2026
7063d51
pr: acting on review comments
jhbritton-RSK Sep 3, 2026
ec3e630
Merge pull request #66 from RockSolidKnowledge/feat/37-update-on-toke…
jhbritton-RSK Sep 7, 2026
61116a6
feat: added settings for session cleanup functionality
jhbritton-RSK Sep 4, 2026
da9d265
feat: added method on session store to get and delete expired sessions
jhbritton-RSK Sep 4, 2026
49335c6
feat: implement helper service for running the process of removing ex…
jhbritton-RSK Sep 4, 2026
f61d47e
feat: implement server-side session cleanup hosted service
jhbritton-RSK Sep 7, 2026
e06331e
pr: working on pr review comments
jhbritton-RSK Sep 14, 2026
c4855b9
test: created shared utilities project for testing
jhbritton-RSK Sep 18, 2026
963ee0a
pr: correcting issues commented on in PR
jhbritton-RSK Sep 18, 2026
251c5ec
Merge pull request #77 from RockSolidKnowledge/feat/39-cleanup-expire…
patchandthat Sep 21, 2026
0fd2edf
fix: broken utilities project build
jhbritton-RSK Sep 21, 2026
82a3d3c
version: bumped version number to 3.0
jhbritton-RSK Sep 22, 2026
8656345
Merge pull request #82 from RockSolidKnowledge/fix/broken-build-with-…
patchandthat Sep 22, 2026
f436ff2
feat: setup management interfaces, and stub implementation with place…
jhbritton-RSK Sep 11, 2026
d65ba19
feat: implementing paginated query on stores
jhbritton-RSK Sep 17, 2026
26e6a12
feat: setup scaffold for default session management implementation an…
jhbritton-RSK Sep 18, 2026
eebaaef
fix: modified stores to add functionality needed for the session mana…
jhbritton-RSK Sep 22, 2026
bf9f3e1
feat: implementing session management default implementation
jhbritton-RSK Sep 22, 2026
44dee40
feat: wired up sessions management in DI container
jhbritton-RSK Sep 24, 2026
930ea3f
feat: added display name claim options to server-side session options
jhbritton-RSK Sep 24, 2026
2764629
pr: correcting issue identitifed in pull request
jhbritton-RSK Sep 25, 2026
4c0f3a4
docs: adding docs for implemented so far features of server side sess…
jhbritton-RSK Sep 9, 2026
d575444
pr: updated after review
jhbritton-RSK Sep 14, 2026
41c5478
test: integration test for serverside sessions
JoStevensRSK Sep 1, 2026
ca40069
test: split sever side session test
JoStevensRSK Sep 24, 2026
160b556
pr: remove uneeded client and comment
JoStevensRSK Sep 28, 2026
e0bf57f
feat: added issuer property to user session
jhbritton-RSK Sep 28, 2026
4774453
docs: added docs sestion for session management interface
jhbritton-RSK Sep 28, 2026
2f25f65
Merge pull request #83 from RockSolidKnowledge/feat/40-management-int…
patchandthat Sep 29, 2026
2c1b666
Merge pull request #79 from RockSolidKnowledge/docs/43-server-sessions
patchandthat Sep 29, 2026
1e73d74
Merge pull request #86 from RockSolidKnowledge/feat/62-ServerSideInte…
patchandthat Sep 29, 2026
fb8417e
fix: make session login tests use feature enable flag on pipeline
jhbritton-RSK Sep 29, 2026
a7a5c55
fix: fixed failing integration tests
jhbritton-RSK Sep 30, 2026
1f6a288
refactor: server session integration tests to clean them up
jhbritton-RSK Sep 30, 2026
e5b03a1
Merge pull request #90 from RockSolidKnowledge/bug/failing-integratio…
patchandthat Sep 30, 2026
816e3b7
Merge branch 'release/3.0.0' into server-side-sessions
patchandthat Sep 30, 2026
81f8ecf
fix: added issuer to auth ticket when storing new ticket
jhbritton-RSK Oct 1, 2026
8b1f723
Merge pull request #93 from RockSolidKnowledge/bug/92-issuer-not-set
patchandthat Oct 1, 2026
3b1a67c
Merge branch 'release/3.0.0' into server-side-sessions
patchandthat Oct 1, 2026
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
4 changes: 2 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<VersionPrefix>2.0.0</VersionPrefix>
<MinVerMinimumMajorMinor>2.0</MinVerMinimumMajorMinor>
<VersionPrefix>3.0.0</VersionPrefix>
<MinVerMinimumMajorMinor>3.0</MinVerMinimumMajorMinor>
<Company>RockSolidKnowledge</Company>
<WarningsAsErrors>CS1591;CS1570;CS1571;CS1572;CS1573;CS1574;CS1580;CS1581;CS1584;CS1587;CS1591;CS1658;CS1712;CS1734</WarningsAsErrors>
</PropertyGroup>
Expand Down
9 changes: 9 additions & 0 deletions Open.IdentityServer.sln
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{7A351D3D
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Open.IdentityServer.Storage.UnitTests", "src\Storage\tests\Open.IdentityServer.Storage.UnitTests\Open.IdentityServer.Storage.UnitTests.csproj", "{FF1944C8-2516-4197-9B63-8BB3581882B3}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{36985CF3-7E79-4BF4-91FD-3E9195A0FCEA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Open.IdentityServer.Test.Utilities", "src\Open.IdentityServer.Test.Utilities\Open.IdentityServer.Test.Utilities.csproj", "{F0AD47D4-F27B-4265-B1B9-B2346824CBE4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -109,6 +113,7 @@ Global
{C459AC33-FD11-402E-8058-F76DD940190D} = {78510D3C-6BE1-4017-8AD4-CC905D58D788}
{7A351D3D-4AC7-4662-8BF3-8F42D6097F87} = {7C740022-8283-4021-8E72-3F2847949309}
{FF1944C8-2516-4197-9B63-8BB3581882B3} = {7A351D3D-4AC7-4662-8BF3-8F42D6097F87}
{F0AD47D4-F27B-4265-B1B9-B2346824CBE4} = {36985CF3-7E79-4BF4-91FD-3E9195A0FCEA}
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A2D626B8-1532-4E35-B9F2-4246C838D192}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -183,5 +188,9 @@ Global
{FF1944C8-2516-4197-9B63-8BB3581882B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FF1944C8-2516-4197-9B63-8BB3581882B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FF1944C8-2516-4197-9B63-8BB3581882B3}.Release|Any CPU.Build.0 = Release|Any CPU
{F0AD47D4-F27B-4265-B1B9-B2346824CBE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F0AD47D4-F27B-4265-B1B9-B2346824CBE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F0AD47D4-F27B-4265-B1B9-B2346824CBE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F0AD47D4-F27B-4265-B1B9-B2346824CBE4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
4 changes: 4 additions & 0 deletions build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ New-Item -ItemType Directory -Force -Path ./nuget

dotnet tool restore

pushd ./src/Open.IdentityServer.Test.Utilities
Invoke-Expression "dotnet build"
popd

pushd ./src/Storage
Invoke-Expression "./build.ps1 $args"
popd
Expand Down
4 changes: 4 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ mkdir nuget

dotnet tool restore

pushd ./src/Open.IdentityServer.Test.Utilities
dotnet build
popd

pushd ./src/Storage
./build.sh "$@"
popd
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ Open.IdentityServer enables the following features in your applications:
topics/compatibility
topics/resources
topics/clients
topics/server_side_sessions
topics/signin
topics/signin_external_providers
topics/windows
Expand Down
2 changes: 0 additions & 2 deletions docs/migrating/from_duende.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ Migration Steps
- Remove all references. Not yet supported in Open.IdentityServer.
* - Automatic Key Management
- Remove all references. You will need to configure signing keys manually, or :ref:`configure read-only key store <refCompatibility>`.
* - Server Side Sessions
- Remove all references. Not yet supported in Open.IdentityServer.
* - Pushed Authorisation Requests (PAR)
- Remove all references. Not yet supported in Open.IdentityServer.
* - CIBA (Client Initiated Backchannel Authentication)
Expand Down
21 changes: 21 additions & 0 deletions docs/reference/options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,24 @@ Mutual TLS
Specifies whether a cnf claim gets emitted for access tokens if a client certificate was present.
Normally the cnf claims only gets emitted if the client used the client certificate for authentication,
setting this to true, will set the claim regardless of the authentication method. (defaults to false).

Server-Side Sessions
^^^^^^^^^^^^^^^^^^^^

* ``ExpiredSessionsTriggerBackchannelLogout``
Specifies if session expiry should trigger back channel logout, this will override any other settings that may
cause back channel logout such as AuthenticationOptions.CoordinateClientLifetimesWithUserSession or
Client.CoordinateLifetimeWithUserSession.

* ``RemoveExpiredSessions``
Specifies if expired sessions should be cleaned up automatically by Open.IdentityServer. The default value is true.

* ``RemoveExpiredSessionsFrequency``
Specifies the frequency with which expired sessions are looked for and removed. The default value is a TimeSpan of 10 minutes.

* ``FuzzExpiredSessionsFrequency``
Specifies if the start time of the hosted service should be randomised. This avoids the scenario where multiple running instances
of identityserver run cleanup jobs simultaneously. The default value is true.

* ``RemoveExpiredSessionsBatchSize``
Specifies how many expired sessions should be removed in a single pass. The default value is 100.
225 changes: 225 additions & 0 deletions docs/topics/server_side_sessions.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
.. _refServerSideSessions:

Server-Side Sessions
====================

Overview
--------
When users authenticate with Open.IdentityServer, a session is created to track the logged in user. By default this will be done by storing this state in cookies in the user browser. This approach of storing session state in a cookie can work well for many scenarios but does have some drawbacks.

* **No Tracking Active Sessions** - There is no way to track active sessions, and how many users are currently logged in.
* **No Immediate Revocation** - There will be no process of Immediate session revocation on the server side-session cookie will be valid till it expires, or they log out.
* **No Sign-Out Coordination** - Coordinating sign-outs from Open.IdentityServer with connected clients is less relable without server tracking of active sessions.

Open.IdentityServer Server-Side Sessions solves these issues by storing the contents of this cookie in a server side data store. This gives Open.IdentityServer the ability to:

* Provide APIs for managing and querying active user sessions
* Support for explicit session revocation regardless of the cookie state in the browser
* Storing session data server side, so browser cookie only contains an ID for the session nothing more

Getting Started
^^^^^^^^^^^^^^^

1. **Database schema**

Ensure your database is in the correct state. If you are coming from Duende IdentityServer, there is nothing further to do - the schema is already compatible. If you are migrating from IdentityServer4 and have not yet updated your schema to match the Open.IdentityServer schema, you will need to do this first. See :ref:`migration from IdentityServer4 <refMigrateFromIdS4>` for details.

2. **Enable server-side sessions**

Call ``.AddServerSideSessions()`` when configuring Open.IdentityServer:

.. code-block:: csharp

builder.Services.AddIdentityServer()
.AddServerSideSessions();

3. **Configure a session store**

``AddServerSideSessions`` requires an implementation of ``IServerSideSessionStore`` to persist session data. If you are using Entity Framework Core, this is provided automatically when you configure the operational store:

.. code-block:: csharp

builder.Services.AddIdentityServer()
.AddServerSideSessions()
.AddOperationalStore(options =>
{
options.ConfigureDbContext = b =>
b.UseSqlServer("ConnectionString");
});

If you are not using the built-in EF Core store, you will need to provide your own ``IServerSideSessionStore`` implementation.

5. **(Optional) Configure additional session options**

You can customize behavior via ``ServerSideSessionOptions``, such as how often sessions are checked for expiration in the background, or coordinating this with your sign-in cookie expiration:

.. code-block:: csharp

builder.Services.AddIdentityServer(options =>
{
// Other options...
options.ServerSideSessions.ExpiredSessionsTriggerBackchannelLogout = true;
options.ServerSideSessions.RemoveExpiredSessions = true;
options.ServerSideSessions.RemoveExpiredSessionsFrequency = TimeSpan.FromSeconds(10);
options.ServerSideSessions.FuzzExpiredSessionsFrequency = true;
options.ServerSideSessions.RemoveExpiredSessionsBatchSize = 100;
});

Management Interface
^^^^^^^^^^^^^^^^^^^^

Open.IdentityServer has a built-in session management interface, ``ISessionManagementService``, that allows you to query existing sessions and remove sessions. When you configure Open.IdentityServer to use server-side sessions, a default implementation is registered for this interface.

The interface provides two methods:

- ``Task<QueryResult<UserSession>> ISessionManagementService.QuerySessionsAsync(SessionQuery? filter, CancellationToken ct = default)``

Filters sessions using the ``SessionQuery`` object. The filter is optional; default values are used when it is not provided.

- ``Task ISessionManagementService.RemoveSessionsAsync(RemoveSessionsContext context, CancellationToken ct = default)``

Removes sessions using the ``RemoveSessionsContext`` object. The context allows you to control which sessions are removed and what actions are taken as part of the removal.

Data Types
^^^^^^^^^^

The following types are used by ``ISessionManagementService`` to query and manage sessions.

SessionQuery
""""""""""""

``SessionQuery`` is used to filter results when calling ``QuerySessionsAsync``.

.. list-table::
:header-rows: 1
:widths: 30 20 50

* - Property
- Type
- Description
* - ``ResultsToken``
- ``string?``
- Optional selector for current page location, contains identifier for the first element and last element in page of results. e.g. '0,24'
* - ``RequestPriorResults``
- ``bool``
- Specifies if instead of getting next page should get the previous page that ResultsToken identifies. Only valid if ResultsToken is specified.
* - ``CountRequested``
- ``int``
- Specifies the count requested per page, defaults to 25
* - ``SubjectId``
- ``string?``
- Filters sessions with a specific subject id
* - ``SessionId``
- ``string?``
- Filters sessions with a specific session id
* - ``DisplayName``
- ``string?``
- Filters sessions with a specific display name

QueryResult<T>
""""""""""""""

``QueryResult<T>`` wraps paged results returned from ``QuerySessionsAsync``.

.. list-table::
:header-rows: 1
:widths: 30 20 50

* - Property
- Type
- Description
* - ``ResultsToken``
- ``string?``
- Token identifying the current page of results. Contains the first element and last element in page of results. e.g. '0,24'
* - ``HasPrevResults``
- ``bool``
- Specifies if there is a page of results before this page
* - ``HasNextResults``
- ``bool``
- Specifies if there is a page of results after this page
* - ``TotalCount``
- ``int?``
- Total sessions accross all pages of results
* - ``TotalPages``
- ``int?``
- Total number of pages for query result
* - ``CurrentPage``
- ``int?``
- Page numer of the current result collection
* - ``Results``
- ``IReadOnlyCollection<T>``
- The collection of results for the current page

UserSession
"""""""""""

``UserSession`` represents a single server-side session record.

.. list-table::
:header-rows: 1
:widths: 30 20 50

* - Property
- Type
- Description
* - ``SubjectId``
- ``string``
- The subject (user) identifier associated with the session.
* - ``SessionId``
- ``string``
- The unique identifier for the session
* - ``DisplayName``
- ``string?``
- An optional display name for the user
* - ``Created``
- ``DateTime``
- The date and time the session was created.
* - ``Renewed``
- ``DateTime``
- The date and time the session was last renewed
* - ``Expires``
- ``DateTime?``
- The date and time the session expires, if applicable
* - ``Issuer``
- ``string?``
- The issuer of the authentication ticket
* - ``Clients``
- ``IEnumerable<string>``
- The clients associated with the session
* - ``AuthenticationTicket``
- ``AuthenticationTicket?``
- The user sessions suthentication ticket object

RemoveSessionsContext
""""""""""""""""""""""

``RemoveSessionsContext`` controls which sessions are removed and what side effects occur when calling ``RemoveSessionsAsync``.

.. list-table::
:header-rows: 1
:widths: 30 20 50

* - Property
- Type
- Description
* - ``SubjectId``
- ``string?``
- Optional if SessionId has value, limits removal to a specific subject id
* - ``SessionId``
- ``string?``
- Optional if SubjectId has value, limits removal to a specific session id
* - ``ClientIds``
- ``IEnumerable<string>?``
- Optionally limits removal to sessions for specific clients
* - ``RemoveServerSideSession``
- ``bool``
- Whether to trigger session entity removal from the database
* - ``SendBackchannelLogoutNotification``
- ``bool``
- Whether to trigger backchannel logout notifications for removed sessions
* - ``RevokeTokens``
- ``bool``
- Whether to trigger session token removal
* - ``RevokeConsents``
- ``bool``
- Whether to trigger session consent removal
2 changes: 1 addition & 1 deletion src/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<ExtensionsVersion>10.0.12</ExtensionsVersion>
<EntityFrameworkVersion>10.0.12</EntityFrameworkVersion>

<IdentityServerVersion>2.0.1-*</IdentityServerVersion>
<IdentityServerVersion>3.0.0-*</IdentityServerVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/EntityFramework.Storage/src/Entities/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ public class Client
public string UserCodeType { get; set; }
public int DeviceCodeLifetime { get; set; } = 300;
public bool NonEditable { get; set; }
public bool? CoordinateLifetimeWithUserSession { get; set; }

//Unused Compatibility Properties
public int? CibaLifetime { get; set; }
public int? PollingInterval { get; set; }
public bool? CoordinateLifetimeWithUserSession { get; set; }
public string InitiateLoginUri { get; set; }
public TimeSpan DPoPClockSkew { get; set; }
public int DPoPValidationMode { get; set; }
Expand Down
Loading
Loading