Skip to content

fix: Refresh hook race - #224

Merged
piitaya merged 13 commits into
cdnninja:masterfrom
pantsman0:refresh_hook_race
Sep 9, 2026
Merged

piitaya merged 13 commits into
cdnninja:masterfrom
pantsman0:refresh_hook_race

Conversation

@pantsman0

@pantsman0 pantsman0 commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

If two requests, R1 and R2, call into YotoClient's check_and_refresh_token, there is the potential to race to token updating and writing an invalidated token to the cache.

Timeline:

  1. R1 and R2 get the token and initiate a refresh.
  2. R1 requests a new token and writes to the cache.
  3. R2 requests a new token with the invalidated refresh token, causing the Yoto IdP to invalidate the refresh token issued in step 2.

To combat this, there token has been locked in the three locations it is accessed:

  1. set_refresh_token locks the refresh token so it's not changed during the middle of another change.
  2. check_and_refresh_token will hold the lock from the first time it check the token until the return of the function, including a potential change of token.
  3. device_code_flow_complete polls for a new token, then locks while updating the internal token and calling the refresh token hook.

pantsman0 and others added 7 commits August 26, 2026 13:49
…n. The access token should be kept for the client, but sending both returns structured data and exposing that access key shouldn't impede the operation of the client.
…tiple concurrent requests can't race to update the access/refresh tokens.
… so a slow IdP authorization doesn't block requests, when used for re-authorization instead of initial auth.

@piitaya piitaya left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch on the race.
Could you call the hook after releasing the lock? A hook that calls back into the client would otherwise wait forever on it.
Can we also keep set_refresh_token sync, since making it async silently breaks existing callers. A test with two concurrent refreshes would be nice too.

@pantsman0

Copy link
Copy Markdown
Contributor Author

I have updated the actual code, but I will have to wait until I have some more time to do the new test case.

Comment thread scripts/oauth_login.py Fixed
I can't confidently commit this script as it was AI generate and I haven't checked it is properly safe.

Github actions has also identified a potential source of HTML injection in the authentication error message.
@pantsman0
pantsman0 requested a review from piitaya September 2, 2026 06:09
@pantsman0

Copy link
Copy Markdown
Contributor Author

@piitaya Is there a chance you could re-review this PR? I would love to integrate this change into my changes to Music Assistant.

@piitaya piitaya left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems good ! Thank you !

@piitaya
piitaya merged commit 524628a into cdnninja:master Sep 9, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants