mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2026-04-25 17:25:57 +03:00
[GH-ISSUE #6311] SSO: Authentik Refresh token not valid #2398
Labels
No labels
SSO
Third party
better for forum
bug
bug
documentation
duplicate
enhancement
future Vault
future Vault
future Vault
good first issue
help wanted
low priority
notes
pull-request
question
troubleshooting
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/vaultwarden#2398
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @samclark2015 on GitHub (Sep 22, 2025).
Original GitHub issue: https://github.com/dani-garcia/vaultwarden/issues/6311
Prerequisites
Vaultwarden Support String
Your environment (Generated via diagnostics page)
Config & Details (Generated via diagnostics page)
Show Config & Details
Environment settings which are overridden: DOMAIN, SIGNUPS_ALLOWED
Config:
Vaultwarden Build Version
1.34.3-a2ad1dc7
Deployment method
Official Container Image
Custom deployment method
No response
Reverse Proxy
traefik v3.1.2
Host/Server Operating System
Linux
Operating System Version
Ubuntu 25.04
Clients
Desktop, Browser Extension, Android
Client Version
Desktop - 2025.7.0, Firefox - 2025.8.2, Android - 2025.8.1
Steps To Reproduce
minutes=1minutes=15days=90Expected Result
Vaultwarden utilizes the refresh token provided by Authentik to keep session alive, exchanging after Access Token validity period for a new access token. User prompted for login after Refresh Token validity period.
Actual Result
User is prompted for SSO login anywhere from hours to a week after initial login.
Logs
Screenshots or Videos
No response
Additional Context
Using Authentik v2025.8.1, though appeared on earlier releases.
@Timshel commented on GitHub (Oct 21, 2025):
Hey,
Sorry missed your issue.
This usually happened when two
refresh_tokencalls are made at the same time.If you can still reproduce can you check if it's the case ?
@samclark2015 commented on GitHub (Oct 22, 2025):
Thanks! I enabled
SSO_AUTH_ONLY_NOT_SESSIONwhich resolved things. I'd behappy to disable and give some info, though.
What would be useful here? Authentik logs?
On Tue, Oct 21, 2025, 11:50 AM Timshel @.***> wrote:
@Timshel commented on GitHub (Oct 22, 2025):
More Vaultwarden server log before the issue is triggered might help :)
@samclark2015 commented on GitHub (Oct 22, 2025):
Just toggled that setting & will report back with logs when it happens.
@samclark2015 commented on GitHub (Oct 23, 2025):
Here is a longer log. Multiple clients authenticated in this span, so not sure how helpful this is to trace duplicate calls... Happy to provide any other info that would be useful!
@Timshel commented on GitHub (Oct 27, 2025):
Hey,
So it does not look like the use case I was speaking of, since it used to manifest with two almost simultaneous
POST /identity/connect/tokenwith only one of the two working.With a 90days refresh token validity I'm not sure what could be the source of the error :(.
Would you have a way to track in Authentik when the token was revoked ?
@controlaltnerd commented on GitHub (Nov 12, 2025):
I seem to be having a similar issue. In my case, I'm getting the error
[ERROR] Unable to refresh login credentials: Access token is close to expiration but we have no refresh token. I have access token expiration set to 10 minutes, and after I've logged in to Vaultwarden on either the web or through the Chrome extension, about 10 minutes later both will sign me out and the error will be logged.Refresh token lifespan is set to 30 days, and I am able to verify that the refresh token is actually being passed from Authentik to the web frontend so my best guess at the moment is that somehow the access token is being used in place of the refresh token, which would suggest Vaultwarden is attempting to authenticate again rather than refresh. I could eliminate session handling and restrict it to authentication only, but I'm unsure of what the result would be. Would the session just persist for the duration of the Authentik login session?
@0xmillennium commented on GitHub (Jan 21, 2026):
@Timshel You mentioned earlier that this
invalid_grantloop might be caused by two refresh_token calls happening at the same time. I am experiencing a specific issue with OIDC (Authelia) where the session is killed exactly at the 1-hour mark (access token expiration) due to a race condition in the refresh flow.Environment:
Server: Vaultwarden (Docker)
OIDC Provider: Authelia
Client: Bitwarden Browser Extension (Desktop/Mobile apps work fine)
Auth Method:
client_secret_basic(since Vaultwarden does not seem to supportclient_secret_postyet)The Issue:
I am encountering a session termination issue with the Bitwarden Browser Extension when using OIDC (Authelia). The logs confirm that the client is firing two identical refresh requests at the exact same millisecond.
\rightarrowToken B).invalid_grant).Logs:
Notice the timestamp 04:25:20.652. Two POST requests are initiated simultaneously.
Consistency & Impact: This issue happens every single time the token expiration is reached (100% reproducible). It is not an intermittent glitch.
Important Note: I do not want to use the workaround of setting extremely long Access Token lifespans (e.g. 30 days) to simply bypass the refresh loop. I aim to maintain secure, short-lived tokens with proper SSO management. Therefore, fixing this race condition/debounce issue is critical for my use case.
Is there a workaround to lock the refresh process or debounce these calls within Vaultwarden?
@Timshel commented on GitHub (Jan 28, 2026):
@0xmillennium Hey not sure why it's happening only with the browser extension. It should share the same code as the desktop/web app :(.
I contributed a fix (https://github.com/bitwarden/clients/pull/10799) last year which should prevent the issue :(.
I'll try to have a look to see if I can find something.
@faustlod commented on GitHub (Feb 9, 2026):
@faustlod commented on GitHub (Feb 9, 2026):
Could you show me your Docker Compose configuration settings for SSO, your Authentik configuration, and your Traefik middleware configuration? Unfortunately, SSO is not working for me at all:
Failed to discover OpenID provider: Request failed","validationErrors":{"":["Failed to discover OpenID provider: Request failed"]}," errorModel":{"message":"Failed to discover OpenID provider: Request failed","object":"error"},"error":"","error_description":"","exceptionMessage":null,"exceptionStackTrace":null,"innerExceptionMessage":null,"object":"error"}
Thank you!
@gelbphoenix commented on GitHub (Feb 10, 2026):
Have you set the
SSO_AUTHORITYto your specific authority URL? If the.well-known/openid-configurationpage is underhttps://application.company/oidc/.well-known/openid-configurationthen mustSSO_AUTHORITYbe set tohttps://application.company/oidc.@faustlod commented on GitHub (Feb 16, 2026):
Thank you for your comment!
Unfortunately, it still doesn't work. SSO_AUTHORITY was set, I use Authentik, so I set it up as follows:
OpenID Configuration in authentik: https://auth.mydomain.tld/application/o/vaultwarden/.well-known/openid-configuration
SSO_AUTHORITY: https://auth.mydomain.tld/application/o/vaultwarden/ (tried with and without the / at the end)
Unfortunately, the error still persists.
@ChristianKilmer commented on GitHub (Feb 18, 2026):
I just wanted to chime in to mention that I am also experiencing this exact same issue, but with Authelia. At least this confirms that the issue is in Vaultwarden and not related to an OIDC provider.
Here's a log dump, please let me know if you'd like to see this with debug-level logs or something and I'd be happy to provide.
@rharish101 commented on GitHub (Feb 18, 2026):
I'm facing the same issue as @0xmillennium, also with Authelia. My logs also show two identical calls for the refresh token made at the same time, which happen both with the desktop browser extension in Firefox and the Bitwarden app on Android.
@rharish101 commented on GitHub (Feb 19, 2026):
I added
SSO_AUTH_ONLY_NOT_SESSION=true, and it seems to work so far (just been 1 day since the addition of this env var) on my Android device with Bitwarden from Google Play. However, the Bitwarden extension on Firefox desktop (Linux) ALWAYS stops working after I close and reopen the browser.EDIT: Here's my Vaultwarden config:
And here's my Authelia config for Vaultwarden (in Nix format):
@Timshel commented on GitHub (Feb 20, 2026):
@rharish101 yes the
SSO_AUTH_ONLY_NOT_SESSIONbypass your provider and use the default Vaultwarden session which does not care if you reuse an old refresh token.Tried to trigger the issue again but even with a 2min access token (Bitwarden consider <5min expired), the application spam call to the token endpoint but had no parallel calls.
Not sure what you mean by that ? do you have to login again ?
@ChristianKilmer do you have any information on authelia side why the call was denied ? because
Is vague.
@faustlod not sure if it might help to troubleshoot, but I just updated the Authentik docker compose debug/demo stack I use. It uses OIDCWarden (the client allow connection over
http) but the configuration should be the same.@rharish101 commented on GitHub (Feb 20, 2026):
Yes indeed. I have to relogin with Authelia. I also waited for the 5 minute timeout that I set in the extension's settings. When it's just supposed to lock the vault, it actually ends up logging me out altogether.
@ChristianKilmer commented on GitHub (Feb 20, 2026):
@Timshel I noticed something interesting today. If you'd like to see a recording of this, I can show you, but hopefully this makes sense.
I have since set
SSO_AUTH_ONLY_NOT_SESSION=trueas the obvious workaround, but noticed the weirdest phenomenon in the logs despite that. While watching the logs, I noticed that every single time the Bitwarden desktop application is minimized (not even closed!) I get this error sequence...That's not even the weirdest thing. What's really crazy to me is that every single time I change browser tabs, the exact same thing happens! I don't even have a Vaultwarden tab open, so that tells me that its just the simple act of the browser extension being refreshed.
In all of the above situations, I have been logged in and my session has been functional. I have confirmed this by making edits to items in the desktop and browser extensions, seeing successful POST operations in the logs, and verifying that the change took place. Despite that, I still see this message every single time. I have also confirmed that it is no related to the state of
SSO_AUTH_ONLY_NOT_SESSIONby trying it both ways.Now to your question, I have set
SSO_AUTH_ONLY_NOT_SESSION=falseagain, but have not been able to replicate the issue yet. Once it starts happening, I will reply with my logs.@ChristianKilmer commented on GitHub (Feb 21, 2026):
Alright, so this is my uninformed opinion on a potential fix after looking at some of the codebase. I am not a professional, so please take this with a grain of salt.
It looks like maybe you're treating the SSO refresh tokens as stateless? They're being pushed to clients using JWTs rather than remembering them on the server. When the OIDC provider rotates the token, concurrent client requests all carry the same token, and after the first one succeeds, the provider revokes that token, causing all subsequent concurrent requests to fail. I suspect that when multiple Bitwarden clients (web, desktop, mobile, etc.) see that a token is nearing expiry, they all request at the exact same time. You mentioning in an earlier comment that multiple calls to refresh_token can cause this issue combined with what I saw today so far is what put me down this rabbit hole, and I think that accurately reflects what is happening.
My proposal would be adding something like an sso_refresh_token to the devices table of your db schema as a nullable (non-SSO users) text field. This way, the server always knows the current valid token. The existing refresh_token column is actually Vaultwarden's own device lookup token rather than the OIDC provider's token, which confused me initially (I could be wrong about this).
This SSO refresh token could then be saved after a successful login. Perhaps in src/api/identity.rs, you could have an action where upon a successful token exchange, before the device is saved, something like
device.sso_refresh_token = sso_refresh_token.map(|t| t.to_string());could be run to save the token server-side in the database.Now, the actual bug fix... This is where I think I somewhat fall apart, but I'll let you decide. Also in the src/api/identity.rs file, under the _refresh_login function... instead of unpacking the OIDC token from the client's JWT, read it from the new device.sso_refresh_token. After a successful exchange, save the new one back. I simply do not have know-how to write this out for myself in Rust, and don't want to throw vibe-code at you that I myself don't even understand.
Because the server now stores the token in the db, even if multiple requests arrive simultaneously, the second one can detect that the first already updated the stored token. The server can either retry with the new token or return the cached result. The OIDC provider only should ever see one request with each token. And by storing the token server-side, you'd no longer depend on the client's JWT wrapper correctly preserving it. Even in the freak scenario that the JWT wrapping logic causes the OIDC token to get lost, the server's database copy can still be used. Just some gravy, but maybe some type of mutex lock could be applied as well to prevent that brief window where two requests can read the same DB value before writing back.
Hopefully this puts you onto something, but I really don't know enough to make a proper PR myself.
@controlaltnerd commented on GitHub (Feb 21, 2026):
That explanation helps make sense of some behavior I've been seeing lately that I couldn't explain, namely that the Bitwarden extension (Chrome/Brave) on my laptop consistently fails to stay logged in, while on my desktop it tends to stay logged in for a few days at a time. I thought for a while that the iOS app wasn't having any issues, but recently discovered it hadn't connected to the server in over a month. The logouts on my laptop always happen at the expiration of the refresh token, but I didn't make the connection to the successful refreshes happening on the desktop, and the iOS "logged in but not really" behavior helped to obfuscate that.
@Timshel commented on GitHub (Feb 21, 2026):
@ChristianKilmer
I believe this is unlikely to be the cause of error. I have not tested it with Authentik, but multiple sessions should have different tokens each with a separate lifecycle which are unlikely to expire at the same time. And even if they were to expire at the same time they should be different, in Authentik admin you probably should be able to see the different user sessions somewhere (at least it's visible in Keycloak and each are separate and can be revoked independently).
As for your fix suggestion, storing the tokens in the server db was something I wanted to avoid since keeping them is a security risk.
Fixing the issue in the client should be simpler since they are the root of the issue (current fix I contributed is quite trivial).
Looking at the latest web-vault code I can't identify how the issue could arise. But unless running a really outdated web-vault the fix should be present :(.
A simpler fix server side would be to debounce the refresh_token call with a simple query cache, but I'm reluctant to do it since it would add state to the server which bring limitations (such as running multiple nodes, but unsure if it's done).
@Timshel commented on GitHub (Feb 21, 2026):
@ChristianKilmer For your previous issue,
SSO is now required, Login againshould mean you have a non SSO session somewhere which refresh is rejected sinceSSO_ONLYis activated.@ChristianKilmer commented on GitHub (Feb 21, 2026):
@Timshel Ok I was finally able to reproduce the issue this morning. Here's the logs...
Vaultwarden:
Authelia:
@Timshel commented on GitHub (Feb 21, 2026):
@ChristianKilmer Authelia logs mention the refresh token is expired since
2026-02-21 00:38:39you probably need to extend their validity.You can have a short access token lifetime to force a refresh each time there is some activity but if your refresh token has a short lifetime too then the application won't be able to refresh if you are idle too long.
@rharish101 commented on GitHub (Feb 22, 2026):
I uninstalled my browser extension on Firefox (Linux) desktop and reinstalled it, and this issue is now gone! So using Authelia only for auth (using
SSO_AUTH_ONLY_NOT_SESSION=true) works for me (so far).@controlaltnerd commented on GitHub (Feb 23, 2026):
Saw this issue again today, this time on my desktop when I tried to update a credential and found that the Bitwarden extension wasn't actually logged in anymore but hadn't ended its own local "session":
And from Authentik:
Refresh tokens are valid for 90 days, and the extension was most recently logged in within the past 30 days.