public async Task Refresh_token_should_be_retained_if_token_response_contains_only_access_token() { var document = File.ReadAllText(FileName.Create("success_access_token_response.json")); var handler = new NetworkHandler(document, HttpStatusCode.OK); var tokenClient = new TokenClient( "http://server/token", "client", handler); var indirectOutputOfHttpResponses = new StubHttpResponsesHandler(); var refreshHandler = new RefreshTokenDelegatingHandler( tokenClient, "refresh_token", "access_token", indirectOutputOfHttpResponses); var apiClient = new HttpClient(refreshHandler); await apiClient.GetStringAsync("http://someapi/somecall"); refreshHandler.RefreshToken .Should() .Be("refresh_token", "Refresh token should be retained if token response contains only access token"); }
public async Task The_401_response_that_causes_token_refresh_and_retry_should_be_disposed_to_unblock_socket() { var document = File.ReadAllText(FileName.Create("success_token_response.json")); var handler = new NetworkHandler(document, HttpStatusCode.OK); var tokenClient = new TokenClient( "http://server/token", "client", handler); var tokenResponse = await tokenClient.RequestClientCredentialsAsync(); var indirectOutputOfHttpResponses = new StubHttpResponsesHandler(); var refreshHandler = new RefreshTokenDelegatingHandler( tokenClient, tokenResponse.RefreshToken, tokenResponse.AccessToken, indirectOutputOfHttpResponses); var apiClient = new HttpClient(refreshHandler); await apiClient.GetStringAsync("http://someapi/somecall"); indirectOutputOfHttpResponses.FirstAttempt401Response .Disposed .Should() .BeTrue("Unauthorized response should be disposed to avoid socket blocking"); }
public TestClient(RefreshTokenDelegatingHandler refreshTokenHandler) { _client = new HttpClient(refreshTokenHandler) { BaseAddress = new Uri("http://testing") }; }
public async Task Can_refresh_access_tokens_in_parallel() { var logicalThreadCount = 10; var callsPerThread = 10; var maxCallsPerAccessToken = 20; var tokens = new TestTokens(maxCallsPerAccessToken); var handlerUnderTest = new RefreshTokenDelegatingHandler( new TestableOidcTokenRefreshClient(tokens, 2.Milliseconds()), tokens.InitialAccessToken, tokens.InitialRefreshToken, new TestServer(tokens, 0.Milliseconds())); using (var client = new TestClient(handlerUnderTest)) { async Task PerformPingRequests() { for (var i = 0; i < callsPerThread; i++) { await client.SecuredPing(); } } var tasks = Enumerable.Range(0, logicalThreadCount).Select(i => PerformPingRequests()); await Task.WhenAll(tasks); } tokens.Count.Should().BeGreaterOrEqualTo(logicalThreadCount * callsPerThread / maxCallsPerAccessToken); }
public async Task Can_refresh_access_tokens_with_sliding_refresh_tokens() { const int maxCallsPerAccessToken = 2; var tokens = new TestTokens(maxCallsPerAccessToken, _writeLine); var handlerUnderTest = new RefreshTokenDelegatingHandler( new TestableOidcTokenRefreshClient(tokens, TimeSpan.Zero), tokens.InitialAccessToken, tokens.InitialRefreshToken, new TestServer(tokens, TimeSpan.Zero)); using (var client = new TestClient(handlerUnderTest)) { tokens.Count.Should().Be(1); await client.SecuredPing(); tokens.Count.Should().Be(1); await client.SecuredPing(); tokens.Count.Should().Be(1); await client.SecuredPing(); tokens.Count.Should().Be(2); } }
protected override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (!(InnerHandler is RefreshTokenDelegatingHandler)) { var tokenResponse = await _tokenClient.RequestResourceOwnerPasswordAsync(_options.Username, _options.Password, _options.ClientScope, cancellationToken : cancellationToken); InnerHandler = new RefreshTokenDelegatingHandler(_tokenClient, tokenResponse.RefreshToken, tokenResponse.AccessToken, InnerHandler ?? new HttpClientHandler()); } return(await base.SendAsync(request, cancellationToken)); }