public void ContainerRegistryChallengeAuthenticationPolicy_OneHundredConcurrentCallsFailed() { MockAuthenticationClient mockAuthClient = new MockAuthenticationClient( service => { Thread.Sleep(100); throw new InvalidOperationException("Error"); }, (service, scope) => { return(new AcrAccessToken("TestAcrAccessToken")); }); var policy = new ContainerRegistryChallengeAuthenticationPolicy(new MockCredential(), "scope", mockAuthClient); MockTransport transport = CreateMockTransport(r => GetChallengeResponse()); var requestTasks = new Task <Response> [100]; for (int i = 0; i < requestTasks.Length; i++) { requestTasks[i] = SendGetRequest(transport, policy, uri: new Uri("https://example.com")); } Assert.CatchAsync(async() => await Task.WhenAll(requestTasks)); foreach (Task <Response> task in requestTasks) { Assert.IsTrue(task.IsFaulted); } }
public async Task ContainerRegistryChallengeAuthenticationPolicy_OneHundredConcurrentCalls() { MockAuthenticationClient mockAuthClient = new MockAuthenticationClient( service => new AcrRefreshToken("TestAcrRefreshToken"), (service, scope) => { Thread.Sleep(100); return(new AcrAccessToken("TestAcrAccessToken")); }); var policy = new ContainerRegistryChallengeAuthenticationPolicy(new MockCredential(), "scope", mockAuthClient); MockTransport transport = CreateMockTransport(r => GetChallengeResponse()); var requestTasks = new Task <Response> [100]; for (int i = 0; i < requestTasks.Length; i++) { requestTasks[i] = SendGetRequest(transport, policy, uri: new Uri("https://example.com")); } await Task.WhenAll(requestTasks); Assert.True(transport.Requests[0].Headers.TryGetValue("Authorization", out string auth1Value)); for (int i = 1; i < requestTasks.Length; i++) { Assert.True(transport.Requests[i].Headers.TryGetValue("Authorization", out string authValue)); Assert.AreEqual(auth1Value, authValue); } }
public void ContainerRegistryChallengeAuthenticationPolicy_ThrowsForNonTlsEndpoint() { MockAuthenticationClient mockAuthClient = GetMockAuthClient(); var policy = new ContainerRegistryChallengeAuthenticationPolicy(new MockCredential(), "scope", mockAuthClient); MockTransport transport = CreateMockTransport(); Assert.ThrowsAsync <InvalidOperationException>(async() => await SendGetRequest(transport, policy, uri: new Uri("http://example.com"))); }
public async Task ContainerRegistryChallengeAuthenticationPolicy_CachesRefreshToken() { // Arrange int refreshTokenRequests = 0; int accessTokenRequests = 0; string mockJwt = GetMockJwt(TimeSpan.FromHours(3)); // We expect the refresh token request method to be called only the first time. MockAuthenticationClient mockClient = new MockAuthenticationClient( service => { refreshTokenRequests++; return(new AcrRefreshToken(mockJwt)); }, (service, scope) => { accessTokenRequests++; return(new AcrAccessToken($"TestAcrAccessToken{accessTokenRequests}")); }); MockCredential mockCredential = new MockCredential(); var policy = new ContainerRegistryChallengeAuthenticationPolicy(mockCredential, "TestScope", mockClient); // We'll send two GET requests - each will receive a challenge response MockTransport transport = CreateMockTransport( GetChallengeResponse(), new MockResponse(200), GetChallengeResponse(), new MockResponse(200)); // Act await SendGetRequest(transport, policy, uri : new Uri("https://example.azurecr.io/acr/v1/hello-world/_tags/latest"), cancellationToken : default); MockRequest firstRequest = transport.Requests[0]; // Assert string authHeaderValue; Assert.IsTrue(firstRequest.Headers.TryGetValue(HttpHeader.Names.Authorization, out authHeaderValue)); Assert.AreEqual("Bearer TestAcrAccessToken1", authHeaderValue); Assert.AreEqual(1, refreshTokenRequests); Assert.AreEqual(1, accessTokenRequests); // Act await SendGetRequest(transport, policy, uri : new Uri("https://example.azurecr.io/acr/v1/hello-world/_tags/latest"), cancellationToken : default); MockRequest secondRequest = transport.Requests[2]; // Assert Assert.IsTrue(secondRequest.Headers.TryGetValue(HttpHeader.Names.Authorization, out authHeaderValue)); Assert.AreEqual("Bearer TestAcrAccessToken2", authHeaderValue); Assert.AreEqual(1, refreshTokenRequests); Assert.AreEqual(2, accessTokenRequests); }
public async Task ContainerRegistryChallengeAuthenticationPolicy_RequestsTokenOnForceRefresh() { // Arrange int refreshTokenRequests = 0; int accessTokenRequests = 0; MockAuthenticationClient mockClient = new MockAuthenticationClient( service => { refreshTokenRequests++; return(new AcrRefreshToken(GetMockJwt(TimeSpan.FromHours(3)))); }, (service, scope) => { accessTokenRequests++; return(new AcrAccessToken($"TestAcrAccessToken{accessTokenRequests}")); }); MockCredential mockCredential = new MockCredential(); var policy = new ContainerRegistryChallengeAuthenticationPolicy(mockCredential, "TestScope", mockClient); // Getting a different service name will invalidate the token and force a refresh. MockTransport transport = CreateMockTransport( GetChallengeResponse("example1"), new MockResponse(200), GetChallengeResponse("example2"), new MockResponse(200)); // Act await SendGetRequest(transport, policy, uri : new Uri("https://example.azurecr.io/acr/v1/hello-world/_tags/latest"), cancellationToken : default); MockRequest firstRequest = transport.Requests[0]; // Assert string authHeaderValue; Assert.IsTrue(firstRequest.Headers.TryGetValue(HttpHeader.Names.Authorization, out authHeaderValue)); Assert.AreEqual("Bearer TestAcrAccessToken1", authHeaderValue); Assert.AreEqual(1, refreshTokenRequests); Assert.AreEqual(1, accessTokenRequests); // Act await SendGetRequest(transport, policy, uri : new Uri("https://example.azurecr.io/acr/v1/hello-world/_tags/latest"), cancellationToken : default); MockRequest secondRequest = transport.Requests[2]; // Assert Assert.IsTrue(secondRequest.Headers.TryGetValue(HttpHeader.Names.Authorization, out authHeaderValue)); Assert.AreEqual("Bearer TestAcrAccessToken2", authHeaderValue); Assert.AreEqual(2, refreshTokenRequests); Assert.AreEqual(2, accessTokenRequests); }
public async Task ContainerRegistryChallengeAuthenticationPolicy_UsesTokenProvidedByAuthClient() { MockAuthenticationClient mockClient = GetMockAuthClient(); MockCredential mockCredential = new MockCredential(); var policy = new ContainerRegistryChallengeAuthenticationPolicy(mockCredential, "TestScope", mockClient); MockTransport transport = CreateMockTransport(GetChallengeResponse(), new MockResponse(200)); await SendGetRequest(transport, policy, uri : new Uri("https://example.azurecr.io/acr/v1/hello-world/_tags/latest"), cancellationToken : default); MockRequest request = transport.Requests[0]; Assert.IsTrue(request.Headers.TryGetValue(HttpHeader.Names.Authorization, out string authHeaderValue)); Assert.AreEqual("Bearer TestAcrAccessToken", authHeaderValue); }
public async Task ChallengePolicySetsToken() { MockAuthenticationClient mockClient = new MockAuthenticationClient(); MockCredential mockCredential = new MockCredential(); var policy = new ContainerRegistryChallengeAuthenticationPolicy(mockCredential, "TestScope", mockClient); var challengeResponse = new MockResponse(401); string challenge = "Bearer realm=\"https://example.azurecr.io/oauth2/token\",service=\"example.azurecr.io\",scope=\"repository:library/hello-world:metadata_read\",error=\"invalid_token\""; challengeResponse.AddHeader(new HttpHeader(HttpHeader.Names.WwwAuthenticate, challenge)); MockTransport transport = CreateMockTransport(challengeResponse, new MockResponse(200)); await SendGetRequest(transport, policy, uri : new Uri("https://example.azurecr.io/acr/v1/hello-world/_tags/latest"), cancellationToken : default); MockRequest request = transport.Requests[0]; Assert.IsTrue(request.Headers.TryGetValue(HttpHeader.Names.Authorization, out string authHeaderValue)); Assert.AreEqual("Bearer TestAcrAccessToken", authHeaderValue); }
public async Task ContainerRegistryChallengeAuthenticationPolicy_RefreshesRefreshToken() { // Arrange int refreshTokenRequests = 0; int accessTokenRequests = 0; TimeSpan refreshOffset = TimeSpan.FromSeconds(30); TimeSpan expiryTime = TimeSpan.FromSeconds(35); string mockJwt = GetMockJwt(expiryTime); // We expect the refresh token request method to be called the first and third times. MockAuthenticationClient mockClient = new MockAuthenticationClient( service => { refreshTokenRequests++; return(new AcrRefreshToken(mockJwt)); }, (service, scope) => { accessTokenRequests++; return(new AcrAccessToken($"TestAcrAccessToken{accessTokenRequests}")); }); MockCredential mockCredential = new MockCredential(); // Set expiration 5 seconds longer than refresh time. Result should be that it tries to refresh in 5 seconds. var policy = new ContainerRegistryChallengeAuthenticationPolicy(mockCredential, "TestScope", mockClient, tokenRefreshOffset: refreshOffset); // We'll send three GET requests - each will receive a challenge response // In the last one, the token will need to be refreshed so a new request for it will be sent MockTransport transport = CreateMockTransport( GetChallengeResponse(), new MockResponse(200), GetChallengeResponse(), new MockResponse(200), GetChallengeResponse(), new MockResponse(200)); // Act await SendGetRequest(transport, policy, uri : new Uri("https://example.azurecr.io/acr/v1/hello-world/_tags/latest"), cancellationToken : default); MockRequest firstRequest = transport.Requests[0]; // Assert string authHeaderValue; Assert.IsTrue(firstRequest.Headers.TryGetValue(HttpHeader.Names.Authorization, out authHeaderValue)); Assert.AreEqual("Bearer TestAcrAccessToken1", authHeaderValue); Assert.AreEqual(1, refreshTokenRequests); Assert.AreEqual(1, accessTokenRequests); // Act await SendGetRequest(transport, policy, uri : new Uri("https://example.azurecr.io/acr/v1/hello-world/_tags/latest"), cancellationToken : default); MockRequest secondRequest = transport.Requests[2]; // Assert Assert.IsTrue(secondRequest.Headers.TryGetValue(HttpHeader.Names.Authorization, out authHeaderValue)); Assert.AreEqual("Bearer TestAcrAccessToken2", authHeaderValue); Assert.AreEqual(1, refreshTokenRequests); Assert.AreEqual(2, accessTokenRequests); // Act await Task.Delay(expiryTime - refreshOffset); await SendGetRequest(transport, policy, uri : new Uri("https://example.azurecr.io/acr/v1/hello-world/_tags/latest"), cancellationToken : default); MockRequest thirdRequest = transport.Requests[4]; // Wait for bg thread to complete its refresh request. await Task.Delay(TimeSpan.FromSeconds(1)); // Assert Assert.IsTrue(thirdRequest.Headers.TryGetValue(HttpHeader.Names.Authorization, out authHeaderValue)); Assert.AreEqual("Bearer TestAcrAccessToken3", authHeaderValue); Assert.AreEqual(2, refreshTokenRequests); Assert.AreEqual(3, accessTokenRequests); }