Skip to content

Proposal on how to fix issue #692#1002

Closed
johanblumenberg wants to merge 1 commit intogoogleapis:mainfrom
truid-app:fix-issue-692
Closed

Proposal on how to fix issue #692#1002
johanblumenberg wants to merge 1 commit intogoogleapis:mainfrom
truid-app:fix-issue-692

Conversation

@johanblumenberg
Copy link
Copy Markdown
Contributor

Questionnaire

Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly:

  • Make sure to open an issue as a bug/issue before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea
  • Ensure the tests and linter pass
  • Code coverage does not decrease (if any source code was changed)
  • Appropriate docs were updated (if necessary)

Fixes #692

Problem

There is a race condition here

When task is completed, two things happen:

When more than one thread is involved, there is a race condition in which of these that get to execute first. Most of the time the listener executes first, and everything works. But now and then the listener is delayed, and that means that whoever is waiting for refresh() to complete will read the old token.

Logs

Adding a sleep in the listener shows that the race condition exists: https://github.com/veritru/google-auth-library-java/commit/551513b233339b952ec40366e12d448e8c7f7661

This produces the following logs:

2022-09-21 15:07:35.288 INFO --- [pool-6-thread-1] OAuth2Credentials : Starting refresh task
2022-09-21 15:07:35.289 INFO --- [pool-6-thread-2] OAuth2Credentials : refresh()
2022-09-21 15:07:35.308 INFO --- [pool-6-thread-1] OAuth2Credentials : Refresh task done
2022-09-21 15:07:35.308 INFO --- [pool-6-thread-2] OAuth2Credentials : refresh() done
2022-09-21 15:07:40.309 INFO --- [pool-6-thread-1] OAuth2Credentials : Update token info

The "refresh() done" log is the point where the caller would get and use the access token. It does not wait for the listener to actually update the current access token.

Solution Proposal

The proposed solution is to move the update of value to be done before the task is completed.

@johanblumenberg johanblumenberg requested a review from a team September 21, 2022 16:41
@product-auto-label product-auto-label Bot added the size: s Pull request size is small. label Sep 21, 2022
@conventional-commit-lint-gcf
Copy link
Copy Markdown

conventional-commit-lint-gcf Bot commented Sep 21, 2022

🤖 I detect that the PR title and the commit message differ and there's only one commit. To use the PR title for the commit history, you can use Github's automerge feature with squashing, or use automerge label. Good luck human!

-- conventional-commit-lint bot
https://conventionalcommits.org/

@google-cla
Copy link
Copy Markdown

google-cla Bot commented Sep 21, 2022

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

public OAuthValue call() throws Exception {
return OAuthValue.create(refreshAccessToken(), getAdditionalHeaders());
OAuthValue result = OAuthValue.create(refreshAccessToken(), getAdditionalHeaders());

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Would it be better to move finishRefreshAsync up onto this line?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, that might be better.

I don't know if there is any listener that relies on the task being completed, so I didn't want to change it.

@clundin25
Copy link
Copy Markdown
Contributor

LGTM, do you mind signing the CLA and updating to a conventional commit?

return OAuthValue.create(refreshAccessToken(), getAdditionalHeaders());
OAuthValue result = OAuthValue.create(refreshAccessToken(), getAdditionalHeaders());

synchronized (lock) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this lock necessary? Only one thread should be doing work on this future right?

Copy link
Copy Markdown
Contributor Author

@johanblumenberg johanblumenberg Sep 29, 2022

Choose a reason for hiding this comment

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

The lock was taken in the finishRefreshAsync() method when modifying the value variable. I wasn't sure why, if it was needed to protect the value variable or something else. But you are probably right, the lock is not necessary here.

But don't take my word for it ... :)

@clundin25
Copy link
Copy Markdown
Contributor

clundin25 commented Sep 28, 2022

There are a few test regressions introduced by this.

Hopefully @igorbernstein2 can chime in on those

@clundin25
Copy link
Copy Markdown
Contributor

Thanks @johanblumenberg for the fix. We are eager to get this merged so I have forked your PR here #1031 in order to resolve the test failures.

I will make sure you are credited if that is the PR that lands.

@johanblumenberg
Copy link
Copy Markdown
Contributor Author

Thanks @johanblumenberg for the fix. We are eager to get this merged so I have forked your PR here #1031 in order to resolve the test failures.

@clundin25 Perfect, thanks a lot

@TimurSadykov
Copy link
Copy Markdown

Thanks for suggestion, closing as we are about to fix with another PR: #1031

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size: s Pull request size is small.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Possible race condition in credential refresh

4 participants