I am self-hosting Taiga in a Docker environment and am trying to troubleshoot an issue that at least one user is experiencing.
This user’s usage behaviour is a bit unusual in that he has many, many Taiga tabs open in his browser, for very extended periods of time. He very rarely closes his browser and he almost never reboots his computer.
I understand that the browser obtains an access token from the Taiga API which lasts for 24 hours by default. a Refresh token is also obtained which lasts for 8 days by default.
Both of these tokens I understand to reside in ‘Local Storage’ in the user’s browser.
The problem is described as follows by the user:
“I go to an open tab in my Browser. I see the story I am expecting to see but cannot update it. I see on the top bar of Tracker on the page it says Login (it thinks I am not logged in. I then click Login but I can see I have an active session on another tab already in the same Browser, sometimes right next to the one that is logged out. Why does it not know I have active session and use that?”
The user has also explained that when they relaunch Chrome, e.g as part of Chrome having performed a self-update, it loads all the many tabs automatically.
In analysing the nginx traffic logs, I can see some interesting behaviour:
1.2.3.4 - - [27/Apr/2025:23:59:23 +0000] "POST /api/v1/auth/refresh HTTP/1.1" 200 356 "https://taiga.example.com/project/project-1/kanban" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
1.2.3.4 - - [27/Apr/2025:23:59:23 +0000] "POST /api/v1/auth/refresh HTTP/1.1" 401 79 "https://taiga.example.com/project/project-5/us/187469869" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
1.2.3.4 - - [27/Apr/2025:23:59:23 +0000] "POST /api/v1/auth/refresh HTTP/1.1" 401 79 "https://taiga.example.com/project/project-1/epic/5250958" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
1.2.3.4 - - [27/Apr/2025:23:59:23 +0000] "POST /api/v1/auth/refresh HTTP/1.1" 200 354 "https://taiga.example.com/project/project-6/epic/5137777" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
1.2.3.4 - - [27/Apr/2025:23:59:23 +0000] "POST /api/v1/auth/refresh HTTP/1.1" 200 357 "https://taiga.example.com/project/project-3/kanban" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
1.2.3.4 - - [27/Apr/2025:23:59:23 +0000] "POST /api/v1/auth/refresh HTTP/1.1" 401 79 "https://taiga.example.com/project/project-1/us/188783388" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
1.2.3.4 - - [27/Apr/2025:23:59:23 +0000] "POST /api/v1/auth/refresh HTTP/1.1" 401 79 "https://taiga.example.com/project/project-4/epic/188814559" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
1.2.3.4 - - [27/Apr/2025:23:59:23 +0000] "POST /api/v1/auth/refresh HTTP/1.1" 401 79 "https://taiga.example.com/project/project-4/us/188814600" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
1.2.3.4 - - [27/Apr/2025:23:59:23 +0000] "POST /api/v1/auth/refresh HTTP/1.1" 401 79 "https://taiga.example.com/project/project-4/us/188814507" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
1.2.3.4 - - [27/Apr/2025:23:59:23 +0000] "POST /api/v1/auth/refresh HTTP/1.1" 200 354 "https://taiga.example.com/project/project-1/epic/5250970" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
1.2.3.4 - - [27/Apr/2025:23:59:23 +0000] "POST /api/v1/auth/refresh HTTP/1.1" 200 353 "https://taiga.example.com/project/project-1/epic/5272954" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
1.2.3.4 - - [27/Apr/2025:23:59:23 +0000] "POST /api/v1/auth/refresh HTTP/1.1" 401 79 "https://taiga.example.com/project/project-2/task/188781713" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
1.2.3.4 - - [27/Apr/2025:23:59:23 +0000] "POST /api/v1/auth/refresh HTTP/1.1" 401 79 "https://taiga.example.com/project/project-4/epic/188814610" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
1.2.3.4 - - [27/Apr/2025:23:59:23 +0000] "POST /api/v1/auth/refresh HTTP/1.1" 200 356 "https://taiga.example.com/project/project-3/us/187904759?kanban-status=548&kanban-swimlane=52" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"
We see here a big flurry of requests from the same browser all in the space of a single second, to the refresh page. I am not 100% sure but presume that this ‘flood’ is due to the browser having re-launched, and perhaps if the access token in Local Storage had expired, it is causing the browser to use the refresh token to obtain a new access token.
You will note that a number of the requests above returned a 401, but some succeed. Can I get clarity on what would cause this? My working theory is that it is a race condition whereby once a new access token is obtained from the refresh token, the refresh token is now obsolete/cannot be reused - and the requests that returned a 401 are because that refresh token is now itself revoked. Can I get confirmation that refresh tokens are one-time use only?
Secondly, can anyone explain the other behaviour the user describes, whereby the content of the page e.g the story actually renders, yet they also see a ‘Login’ button. In our context, all projects and content are ‘private’ - there are no public projects, so I would not expect any content to be shown if the ‘Login’ button is also to be shown. To see the ‘Login’ button implies ‘not authenticated’, so why/how is any content shown at all in this scenario? I have not reproduced it myself but am interested to hear if anyone else has seen this. It may just be a by-product of the first issue.
Finally, any ideas, assuming I am right, on how to avoid the ‘refresh token collision’ race condition when many tabs request it at once?
Thanks in advance!