Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: check for expired token in any header value #79

Merged
merged 4 commits into from
Jul 16, 2024

Conversation

Dovchik
Copy link
Contributor

@Dovchik Dovchik commented Jul 9, 2024

No description provided.

@@ -128,7 +128,7 @@ internal class Http : IHttp
// will not retry when no "expired" header for a token.
const string wwwAuthenticateHeader = "www-authenticate";
if (_auth.Scheme == AuthSchemes.Bearer && result.Headers.Contains(wwwAuthenticateHeader) &&
!result.Headers.GetValues(wwwAuthenticateHeader).Contains("expired"))
!result.Headers.GetValues(wwwAuthenticateHeader).Any(x => x.Contains("expired")))

Choose a reason for hiding this comment

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

Looking at the fix, it highlights that our expiration detection mechanism is not robust enough: any change on the backend side for the property error_description will break our SDKs.
For instance, if the message changes for Jwt expiry reached at ..., this won't work anymore

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can we merge that while we settle on the robust way of doing that?

Choose a reason for hiding this comment

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

This commit fixes the reported bug indeed

[Fact]
public async Task NewTokenOnlyOnceAfterSuccessfulRefresh()
{
_tokenManagerMock.GetAuthToken(Arg.Any<bool>())

Choose a reason for hiding this comment

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

A three steps approach would be simpler and more realistic towards a real-life scenario. There is no need to use 3 tokens in the test.

  • token1 valid
  • token1 expired
  • token2 valid

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have the scenario about. And I want to have that one as well

Choose a reason for hiding this comment

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

I can't find the scenario I describe and you say you already have. Can you point it to me please?
Please bear with me while I'm trying to understand the necessity to make 2 requests in this scenario: when sending the request (op2) on line 111, the auth manager is in the same state as at the beginning of the scenario. Can you explain why you want to keep the scenario like this? What does it cover more than with a single request?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The scenario checks how the state is cached across two different request to make sure the state is preserved and works as expected.
The 3 token approach you describe is also valid, but it's covered by this case, which is:

  1. Server was running for some time without request to Sinch API so token expired, got Unauthorized
  2. First request refreshed token and successful
  3. Idle, token expired again and second request refreshed it successfully

Choose a reason for hiding this comment

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

Thanks for your explanations. I have some comments though:

  • In my first comment I don't describe a 3 tokens approach, but only 2, making sure the first one is valid before it expires
  • "Server was running for some time without request to Sinch API" => the token doesn't expire because of inactivity. It expires at a fixed time, which can during a surge of requests.
  • "Idle, token expired again" => same remark as above

Then the name of the test NewTokenOnlyOnceAfterSuccessfulRefresh is confusing: it says that the framework will fetch a token only once after a successful refresh, which is not describing what you explain about having a shared state between 2 requests which share the same Http object instance. I would have expected to see a concurrency test instead when several objects share the same resource.
On a side note, the terminology "refresh token" is not correct as the framework doesn't refresh the token but fetches a brand new one by sending again the credentials.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Commenting test out with the intention to revisit
https://tickets.sinch.com/browse/DEVEXP-491

@Dovchik Dovchik requested a review from asein-sinch July 11, 2024 14:59
Copy link

@asein-sinch asein-sinch left a comment

Choose a reason for hiding this comment

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

You may completely remove the test and add it in the new ticket to keep the codebase clean and free from unnecessary clutter

@@ -76,6 +76,48 @@ public async Task ForceNewTokenOnlyOnce()
_httpMessageHandlerMock.VerifyNoOutstandingExpectation();
}

// [Fact]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

To update in next PR:

  • description to clarify test intentions
  • name
  • use expired header here as well

@Dovchik Dovchik merged commit 953f501 into main Jul 16, 2024
3 checks passed
@Dovchik Dovchik deleted the fix/auth-fail-after-refresh branch July 16, 2024 09:49
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.

2 participants