From e16a24233c05d932efd57c83d1e0b1ab64859f7d Mon Sep 17 00:00:00 2001 From: Alex Smith <67177275+Ajsmith1435@users.noreply.github.com> Date: Tue, 14 Oct 2025 15:09:26 -0600 Subject: [PATCH 1/2] sso(authentik): always surface current provider refresh token from exchange --- src/sso_client.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/sso_client.rs b/src/sso_client.rs index 3d2a3c48..1336af64 100644 --- a/src/sso_client.rs +++ b/src/sso_client.rs @@ -240,11 +240,19 @@ impl Client { Ok(token_response) => token_response, }; - Ok(( - token_response.refresh_token().map(|token| token.secret().clone()), - token_response.access_token().secret().clone(), - token_response.expires_in(), - )) + // Always surface a refresh token: + // - If the IdP (e.g., Authentik) returned a rotated one, use it. + // - Otherwise, keep using the one we just used for this request. + let access = token_response.access_token().secret().clone(); + let expires_in = token_response.expires_in(); + + let new_refresh = token_response + .refresh_token() + .map(|t| t.secret().clone()) + .unwrap_or_else(|| rt.secret().clone()); + + Ok((Some(new_refresh), access, expires_in)) + } } From efa54a419bb6fc6b3d6cea557a4a208101202e62 Mon Sep 17 00:00:00 2001 From: Alex Smith <67177275+Ajsmith1435@users.noreply.github.com> Date: Tue, 14 Oct 2025 15:16:09 -0600 Subject: [PATCH 2/2] Update sso.rs - sso(authentik): always adopt rotated provider refresh token to prevent invalid_grant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensures Vaultwarden immediately switches to the IdP’s latest provider refresh token after each refresh, preventing reuse of a revoked token and eliminating `invalid_grant` errors that prematurely log users out. --- src/sso.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sso.rs b/src/sso.rs index 71793dbd..5fe6e684 100644 --- a/src/sso.rs +++ b/src/sso.rs @@ -424,13 +424,13 @@ pub async fn exchange_refresh_token( Some(TokenWrapper::Refresh(refresh_token)) => { // Use new refresh_token if returned let (new_refresh_token, access_token, expires_in) = - Client::exchange_refresh_token(refresh_token.clone()).await?; + Client::exchange_refresh_token(refresh_token).await?; create_auth_tokens( device, user, client_id, - new_refresh_token.or(Some(refresh_token)), + new_refresh_token, access_token, expires_in, )