Multiple SAML sessions stored per user instead of being updated (peertube-plugin-auth-saml2)

Hi everyone,

I’m investigating how sessions are handled in the peertube-plugin-auth-saml2 plugin and noticed something that could become a scalability issue.

Environment:

  • PeerTube version: 6.3.3
  • Plugin: peertube-plugin-auth-saml2
  • IdP: Keycloak

What I observed:

  • Each time a user logs in via SAML, a new entry is created in the plugin table (storage column).

  • These entries look like saml_session_<random_id> and store name_id and session_index.

  • Even for the same user, multiple sessions are stored instead of updating/reusing an existing one.

Example:

  • Same user (u0011@yourdomain.com) has multiple session entries with different session_index values.

Concern:

  • Over time, this leads to accumulation of many session records per user.

  • With a large number of users and frequent logins, this could cause unnecessary growth in the database and impact performance.

My question:

  • Is this behavior intentional (e.g., to support multiple concurrent SAML sessions or SLO requirements)?

  • Or should the plugin be updating/replacing existing sessions for the same name_id instead of creating new ones?

  • Is there any recommended cleanup mechanism or configuration to prevent unbounded growth?

Would appreciate any clarification on the design decision or best practices for handling this.

Thanks!

Example:
{
  "saml_session_147272034def8efefe73": {
    "name_id": "u0015@yourdomain.com",
    "session_index": "iXNcxuM1TWr2dbxRJUnr4i4b::eeb4d31f-991d-44c5-967d-76da73ad7449"
  },
  "saml_session_1a14ca232e58a45080ea": {
    "name_id": "u0011@yourdomain.com",
    "session_index": "Hxfi_LtPIgUKClxuZsVTBAj2::eeb4d31f-991d-44c5-967d-76da73ad7449"
  },
  "saml_session_2e24022a9ec486d0c3bc": {
    "name_id": "u0011@yourdomain.com",
    "session_index": "gm9hcuhYKj3AQuFQrLDVrdUp::eeb4d31f-991d-44c5-967d-76da73ad7449"
  },
  "saml_session_312fc66bced2bbcc6555": {
    "name_id": "u0013@yourdomain.com",
    "session_index": "Y1uEabNrde3bi-rgjLYtCi6n::eeb4d31f-991d-44c5-967d-76da73ad7449"
  },
  "saml_session_53095c156434f4e297e7": {
    "name_id": "u0014@yourdomain.com",
    "session_index": "fcWQ2wSQf-Gb14nylbtenN3o::eeb4d31f-991d-44c5-967d-76da73ad7449"
  },
  "saml_session_58ac7b051d85cf1a6c8d": {
    "name_id": "u0015@yourdomain.com",
    "session_index": "enUlGM3-uASxnpsiegUwUxel::eeb4d31f-991d-44c5-967d-76da73ad7449"
  },
  "saml_session_76110c94da31ae8f9ab8": {
    "name_id": "u0011@yourdomain.com",
    "session_index": "nYcib7aV37rzpKTStQbrF7Tw::eeb4d31f-991d-44c5-967d-76da73ad7449"
  },
  "saml_session_80479274012748ddda49": {
    "name_id": "u0015@yourdomain.com",
    "session_index": "qUVLSq-t_r8PEy6YAUj9u1a5::eeb4d31f-991d-44c5-967d-76da73ad7449"
  },
  "saml_session_9013a3245c28a4e1a546": {
    "name_id": "u0015@yourdomain.com",
    "session_index": "iXNcxuM1TWr2dbxRJUnr4i4b::eeb4d31f-991d-44c5-967d-76da73ad7449"
  },
  "saml_session_a80f09997053bbc366ae": {
    "name_id": "u0015@yourdomain.com",
    "session_index": "qebG7tQl9enC5MwFFeRGQNk6::eeb4d31f-991d-44c5-967d-76da73ad7449"
  },
  "saml_session_c23cfeaeb80129b37364": {
    "name_id": "u0011@yourdomain.com",
    "session_index": "KX46iuVaVGd_itWyFPI6a-bO::eeb4d31f-991d-44c5-967d-76da73ad7449"
  },
  "saml_session_d6273916583745e0f9ce": {
    "name_id": "u0011@yourdomain.com",
    "session_index": "mtLAkYQoV3XcuP93QOeHfpgm::eeb4d31f-991d-44c5-967d-76da73ad7449"
  },
  "saml_session_ed86e90b895593016d93": {
    "name_id": "u0013@yourdomain.com",
    "session_index": "gVd1GxgpKkj387iQ4vNIHIfW::eeb4d31f-991d-44c5-967d-76da73ad7449"
  },
  "saml_session_ffc38bf368a3b9da3af9": {
    "name_id": "u0013@yourdomain.com",
    "session_index": "gVd1GxgpKkj387iQ4vNIHIfW::eeb4d31f-991d-44c5-967d-76da73ad7449"
  }
}

Hi,

Thank you. Can you test v0.1.0? I added a cleanup job and we now only store 1 session per name id.

How will it handle for multiple device login simultaneously for same user ?

The logout saml logout endpoint will be called when the latest (by date) session will have the PeerTube logout endpoint called.

Hi, thanks for the fix and the cleanup job—that definitely helps with the DB growth issue.

I had a follow-up question regarding the change to “1 session per name_id”.

In our use case, users may log in from multiple devices simultaneously (e.g., mobile + laptop), and each login generates a different session_index from the IdP (Keycloak). With the current approach of storing only one session per name_id, it seems that previous sessions get overwritten.

This raises a concern around SAML Single Logout (SLO), since we would lose the ability to track and properly invalidate multiple active sessions for the same user.

Would it make sense to support one of the following approaches instead?

  • Allow multiple sessions per name_id, but with a limit (e.g., last N sessions per user)
  • Introduce a TTL/expiration mechanism for old sessions
  • Key sessions by session_index rather than overwriting by name_id

I’m trying to understand whether the current design intentionally drops multi-session support, or if there’s room to support both cleanup and multiple active sessions safely.

Curious to hear your thoughts on this.

Thanks!

I’m currently testing SAML session cleanup and noticed that expired sessions are not being fully removed from the JSONB storage column. Instead, they are being stored as null values like this:

"saml_session_9686ddd9ce9f41143ad6": null,
"saml_session_c9f83c1003d6987aad76": null,
"saml_session_edb3753c631d25342483": null,
"saml_session_ee9f902220a23b9fc5ff": null

This seems to be caused by the following code:

await storageManager.storeData(`saml_session_${id}`, null);

From what I understand, this does not remove the key, but simply sets its value to null, which still keeps it in the JSONB object. Over time, this leads to unnecessary growth of the storage column.

Is there a recommended way to completely delete these expired session keys instead of setting them to null?

Sorry, I didn’t know keycloak was able to track multiple sessions. I updated the plugin in Handle multiple sessions per name id (2882c88f) · Validations · Framasoft / PeerTube / official-plugins · GitLab

Fixed by Correctly delete data from storage (0207e657) · Validations · Framasoft / PeerTube / official-plugins · GitLab when PeerTube 8.2 will be released.

These changes are released in version 0.2.0 of the SAMLv2 plugin.

Thank for the response. It work for my case.