feat(oidc): impl back channel logout

This commit is contained in:
Edouard Vanbelle
2026-08-03 08:00:13 +02:00
parent 166b8c4891
commit acd4420fe3
11 changed files with 673 additions and 9 deletions
+22
View File
@@ -18,6 +18,11 @@ pub struct Session {
/// RP-initiated logout URL so the IdP can terminate its own SSO session.
/// `None` for password / magic-link sessions.
oidc_id_token: Option<String>,
/// OIDC session identifier (sid claim). Populated only when the IdP
/// emits it. Enables per-device Back-Channel Logout — without it, a
/// BCL notification would revoke all of the user's sessions rather
/// than just the one that logged out on the far end.
oidc_sid: Option<String>,
}
impl Session {
@@ -45,6 +50,7 @@ impl Session {
revoked: false,
family_id,
oidc_id_token: None,
oidc_sid: None,
}
}
@@ -56,6 +62,16 @@ impl Session {
self
}
/// Attach the OIDC session identifier from the id_token's `sid` claim.
/// Optional even for OIDC sessions — only present when the IdP emits
/// sid (Keycloak requires "Backchannel Logout Session Required" on the
/// client). Without it, Back-Channel Logout falls back to sub-based
/// revocation which is coarser (all of the user's OxiCloud sessions).
pub fn with_oidc_sid(mut self, sid: String) -> Self {
self.oidc_sid = Some(sid);
self
}
#[allow(clippy::too_many_arguments)]
pub fn from_raw(
id: Uuid,
@@ -68,6 +84,7 @@ impl Session {
revoked: bool,
family_id: Uuid,
oidc_id_token: Option<String>,
oidc_sid: Option<String>,
) -> Self {
Self {
id,
@@ -80,6 +97,7 @@ impl Session {
revoked,
family_id,
oidc_id_token,
oidc_sid,
}
}
@@ -131,4 +149,8 @@ impl Session {
pub fn oidc_id_token(&self) -> Option<&str> {
self.oidc_id_token.as_deref()
}
pub fn oidc_sid(&self) -> Option<&str> {
self.oidc_sid.as_deref()
}
}