You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2021/09/24 20:13:14 UTC

[httpcomponents-client] branch master updated (0870824 -> a9092e8)

This is an automated email from the ASF dual-hosted git repository.

olegk pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-client.git.


    from 0870824  HTTPCLIENT-2120: force HTTP/1.1 protocol policy when creating a tunnel via HTTP/1.1 proxy
     new 3aeba1b  Added immutable CredentialsProvider implementations and a CredentialsProvider builder; changed test cases and examples to use immutable CredentialsProvider where possible
     new a9092e8  Cleanup of authentication test cases

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../AbstractHttpAsyncClientAuthentication.java     | 110 +++---
 .../async/TestHttp1ClientAuthentication.java       |  12 +-
 .../testing/sync/TestClientAuthentication.java     | 372 ++++++++++-----------
 .../sync/TestClientAuthenticationFakeNTLM.java     |  38 +--
 .../hc/client5/testing/sync/TestSPNegoScheme.java  |  15 +-
 .../http/impl/auth/BasicCredentialsProvider.java   |  41 +--
 ...ntialsProvider.java => CredentialsMatcher.java} |  53 +--
 .../http/impl/auth/CredentialsProviderBuilder.java | 104 ++++++
 ...eFactory.java => FixedCredentialsProvider.java} |  41 +--
 ...Factory.java => SingleCredentialsProvider.java} |  50 ++-
 .../http/examples/AsyncClientAuthentication.java   |  13 +-
 .../http/examples/ClientAuthentication.java        |  13 +-
 .../client5/http/examples/ClientConfiguration.java |   5 +-
 .../ClientPreemptiveDigestAuthentication.java      |  11 +-
 .../http/examples/ClientProxyAuthentication.java   |  18 +-
 .../http/impl/TestAuthenticationStrategy.java      |  18 +-
 .../hc/client5/http/impl/auth/TestBasicScheme.java |  15 +-
 ...Provider.java => TestCredentialsProviders.java} |  24 +-
 .../client5/http/impl/auth/TestDigestScheme.java   | 129 +++----
 .../http/impl/auth/TestRequestAuthCache.java       |  10 +-
 .../client5/http/impl/classic/TestConnectExec.java |  15 +-
 .../http/impl/classic/TestProtocolExec.java        |  20 +-
 22 files changed, 532 insertions(+), 595 deletions(-)
 copy httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/{BasicCredentialsProvider.java => CredentialsMatcher.java} (59%)
 create mode 100644 httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/CredentialsProviderBuilder.java
 copy httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/{NTLMSchemeFactory.java => FixedCredentialsProvider.java} (61%)
 copy httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/{BasicSchemeFactory.java => SingleCredentialsProvider.java} (55%)
 rename httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/{TestBasicCredentialsProvider.java => TestCredentialsProviders.java} (82%)

[httpcomponents-client] 02/02: Cleanup of authentication test cases

Posted by ol...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

olegk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-client.git

commit a9092e869561353ba9269c662ba9190e3703e0d4
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Fri Sep 24 16:07:20 2021 +0200

    Cleanup of authentication test cases
---
 .../AbstractHttpAsyncClientAuthentication.java     | 101 +++---
 .../async/TestHttp1ClientAuthentication.java       |  12 +-
 .../testing/sync/TestClientAuthentication.java     | 341 ++++++++++-----------
 3 files changed, 199 insertions(+), 255 deletions(-)

diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncClientAuthentication.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncClientAuthentication.java
index 7a0c7e3..d4893b2 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncClientAuthentication.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncClientAuthentication.java
@@ -41,8 +41,7 @@ import org.apache.hc.client5.http.auth.AuthScheme;
 import org.apache.hc.client5.http.auth.AuthSchemeFactory;
 import org.apache.hc.client5.http.auth.AuthScope;
 import org.apache.hc.client5.http.auth.ChallengeType;
-import org.apache.hc.client5.http.auth.Credentials;
-import org.apache.hc.client5.http.auth.CredentialsStore;
+import org.apache.hc.client5.http.auth.CredentialsProvider;
 import org.apache.hc.client5.http.auth.StandardAuthScheme;
 import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
 import org.apache.hc.client5.http.config.RequestConfig;
@@ -76,6 +75,7 @@ import org.apache.hc.core5.http2.impl.H2Processors;
 import org.apache.hc.core5.net.URIAuthority;
 import org.junit.Assert;
 import org.junit.Test;
+import org.mockito.Mockito;
 
 public abstract class AbstractHttpAsyncClientAuthentication<T extends CloseableHttpAsyncClient> extends AbstractIntegrationTestBase<T> {
 
@@ -110,42 +110,12 @@ public abstract class AbstractHttpAsyncClientAuthentication<T extends CloseableH
 
     abstract void setTargetAuthenticationStrategy(AuthenticationStrategy targetAuthStrategy);
 
-    static class TestCredentialsProvider implements CredentialsStore {
-
-        private final Credentials creds;
-        private AuthScope authscope;
-
-        TestCredentialsProvider(final Credentials creds) {
-            super();
-            this.creds = creds;
-        }
-
-        @Override
-        public void clear() {
-        }
-
-        @Override
-        public Credentials getCredentials(final AuthScope authscope, final HttpContext context) {
-            this.authscope = authscope;
-            return this.creds;
-        }
-
-        @Override
-        public void setCredentials(final AuthScope authscope, final Credentials credentials) {
-        }
-
-        public AuthScope getAuthScope() {
-            return this.authscope;
-        }
-
-    }
-
     @Test
     public void testBasicAuthenticationNoCreds() throws Exception {
         server.register("*", AsyncEchoHandler::new);
         final HttpHost target = start();
 
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(null);
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
         final HttpClientContext context = HttpClientContext.create();
         context.setCredentialsProvider(credsProvider);
 
@@ -157,9 +127,8 @@ public abstract class AbstractHttpAsyncClientAuthentication<T extends CloseableH
 
         Assert.assertNotNull(response);
         Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
-        final AuthScope authscope = credsProvider.getAuthScope();
-        Assert.assertNotNull(authscope);
-        Assert.assertEquals("test realm", authscope.getRealm());
+        Mockito.verify(credsProvider).getCredentials(
+                Mockito.eq(new AuthScope(target, "test realm", "basic")), Mockito.any());
     }
 
     @Test
@@ -167,8 +136,9 @@ public abstract class AbstractHttpAsyncClientAuthentication<T extends CloseableH
         server.register("*", AsyncEchoHandler::new);
         final HttpHost target = start();
 
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
-                new UsernamePasswordCredentials("test", "all-wrong".toCharArray()));
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
+        Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any()))
+                .thenReturn(new UsernamePasswordCredentials("test", "all-wrong".toCharArray()));
         final HttpClientContext context = HttpClientContext.create();
         context.setCredentialsProvider(credsProvider);
 
@@ -180,9 +150,8 @@ public abstract class AbstractHttpAsyncClientAuthentication<T extends CloseableH
 
         Assert.assertNotNull(response);
         Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
-        final AuthScope authscope = credsProvider.getAuthScope();
-        Assert.assertNotNull(authscope);
-        Assert.assertEquals("test realm", authscope.getRealm());
+        Mockito.verify(credsProvider).getCredentials(
+                Mockito.eq(new AuthScope(target, "test realm", "basic")), Mockito.any());
     }
 
     @Test
@@ -190,8 +159,9 @@ public abstract class AbstractHttpAsyncClientAuthentication<T extends CloseableH
         server.register("*", AsyncEchoHandler::new);
         final HttpHost target = start();
 
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
-                new UsernamePasswordCredentials("test", "test".toCharArray()));
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
+        Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any()))
+                .thenReturn(new UsernamePasswordCredentials("test", "test".toCharArray()));
         final HttpClientContext context = HttpClientContext.create();
         context.setCredentialsProvider(credsProvider);
 
@@ -204,9 +174,8 @@ public abstract class AbstractHttpAsyncClientAuthentication<T extends CloseableH
 
         Assert.assertNotNull(response);
         Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
-        final AuthScope authscope = credsProvider.getAuthScope();
-        Assert.assertNotNull(authscope);
-        Assert.assertEquals("test realm", authscope.getRealm());
+        Mockito.verify(credsProvider).getCredentials(
+                Mockito.eq(new AuthScope(target, "test realm", "basic")), Mockito.any());
     }
 
     @Test
@@ -214,8 +183,9 @@ public abstract class AbstractHttpAsyncClientAuthentication<T extends CloseableH
         server.register("*", AsyncEchoHandler::new);
         final HttpHost target = start();
 
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
-                new UsernamePasswordCredentials("test", "test".toCharArray()));
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
+        Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any()))
+                .thenReturn(new UsernamePasswordCredentials("test", "test".toCharArray()));
         final HttpClientContext context = HttpClientContext.create();
         context.setCredentialsProvider(credsProvider);
         final Future<SimpleHttpResponse> future = httpclient.execute(
@@ -228,9 +198,8 @@ public abstract class AbstractHttpAsyncClientAuthentication<T extends CloseableH
 
         Assert.assertNotNull(response);
         Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
-        final AuthScope authscope = credsProvider.getAuthScope();
-        Assert.assertNotNull(authscope);
-        Assert.assertEquals("test realm", authscope.getRealm());
+        Mockito.verify(credsProvider).getCredentials(
+                Mockito.eq(new AuthScope(target, "test realm", "basic")), Mockito.any());
     }
 
     @Test
@@ -238,8 +207,9 @@ public abstract class AbstractHttpAsyncClientAuthentication<T extends CloseableH
         server.register("*", AsyncEchoHandler::new);
         final HttpHost target = start();
 
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
-                new UsernamePasswordCredentials("test", "all-wrong".toCharArray()));
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
+        Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any()))
+                .thenReturn(new UsernamePasswordCredentials("test", "all-wrong".toCharArray()));
         final HttpClientContext context = HttpClientContext.create();
         context.setCredentialsProvider(credsProvider);
         context.setRequestConfig(RequestConfig.custom().setExpectContinueEnabled(true).build());
@@ -260,8 +230,9 @@ public abstract class AbstractHttpAsyncClientAuthentication<T extends CloseableH
         server.register("*", AsyncEchoHandler::new);
         final HttpHost target = start();
 
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
-                new UsernamePasswordCredentials("test", "test".toCharArray()));
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
+        Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any()))
+                .thenReturn(new UsernamePasswordCredentials("test", "test".toCharArray()));
         final HttpClientContext context = HttpClientContext.create();
         context.setCredentialsProvider(credsProvider);
         context.setRequestConfig(RequestConfig.custom().setExpectContinueEnabled(true).build());
@@ -275,9 +246,8 @@ public abstract class AbstractHttpAsyncClientAuthentication<T extends CloseableH
 
         Assert.assertNotNull(response);
         Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
-        final AuthScope authscope = credsProvider.getAuthScope();
-        Assert.assertNotNull(authscope);
-        Assert.assertEquals("test realm", authscope.getRealm());
+        Mockito.verify(credsProvider).getCredentials(
+                Mockito.eq(new AuthScope(target, "test realm", "basic")), Mockito.any());
     }
 
     @Test
@@ -388,8 +358,9 @@ public abstract class AbstractHttpAsyncClientAuthentication<T extends CloseableH
     @Test
     public void testReauthentication() throws Exception {
         server.register("*", AsyncEchoHandler::new);
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
-                new UsernamePasswordCredentials("test", "test".toCharArray()));
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
+        Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any()))
+                .thenReturn(new UsernamePasswordCredentials("test", "test".toCharArray()));
 
         final Registry<AuthSchemeFactory> authSchemeRegistry = RegistryBuilder.<AuthSchemeFactory>create()
                 .register("MyBasic", context -> new BasicScheme() {
@@ -462,8 +433,9 @@ public abstract class AbstractHttpAsyncClientAuthentication<T extends CloseableH
 
                 });
 
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
-                new UsernamePasswordCredentials("test", "test".toCharArray()));
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
+        Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any()))
+                .thenReturn(new UsernamePasswordCredentials("test", "test".toCharArray()));
         final HttpClientContext context = HttpClientContext.create();
         context.setCredentialsProvider(credsProvider);
 
@@ -474,9 +446,8 @@ public abstract class AbstractHttpAsyncClientAuthentication<T extends CloseableH
         final SimpleHttpResponse response = future.get();
         Assert.assertNotNull(response);
         Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
-        final AuthScope authscope = credsProvider.getAuthScope();
-        Assert.assertNotNull(authscope);
-        Assert.assertEquals("test realm", authscope.getRealm());
+        Mockito.verify(credsProvider).getCredentials(
+                Mockito.eq(new AuthScope(target, "test realm", "basic")), Mockito.any());
     }
 
 }
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1ClientAuthentication.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1ClientAuthentication.java
index b4b049d..d8ff129 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1ClientAuthentication.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp1ClientAuthentication.java
@@ -36,6 +36,7 @@ import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
 import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
 import org.apache.hc.client5.http.auth.AuthSchemeFactory;
 import org.apache.hc.client5.http.auth.AuthScope;
+import org.apache.hc.client5.http.auth.CredentialsProvider;
 import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
 import org.apache.hc.client5.http.config.ConnectionConfig;
 import org.apache.hc.client5.http.config.RequestConfig;
@@ -63,6 +64,7 @@ import org.junit.Test;
 import org.junit.rules.ExternalResource;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
+import org.mockito.Mockito;
 
 @RunWith(Parameterized.class)
 public class TestHttp1ClientAuthentication extends AbstractHttpAsyncClientAuthentication<CloseableHttpAsyncClient> {
@@ -149,8 +151,9 @@ public class TestHttp1ClientAuthentication extends AbstractHttpAsyncClientAuthen
                 },
                 Http1Config.DEFAULT);
 
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
-                new UsernamePasswordCredentials("test", "test".toCharArray()));
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
+        Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any()))
+                .thenReturn(new UsernamePasswordCredentials("test", "test".toCharArray()));
         final HttpClientContext context = HttpClientContext.create();
         context.setCredentialsProvider(credsProvider);
 
@@ -163,9 +166,8 @@ public class TestHttp1ClientAuthentication extends AbstractHttpAsyncClientAuthen
 
         Assert.assertNotNull(response);
         Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
-        final AuthScope authscope = credsProvider.getAuthScope();
-        Assert.assertNotNull(authscope);
-        Assert.assertEquals("test realm", authscope.getRealm());
+        Mockito.verify(credsProvider).getCredentials(
+                Mockito.eq(new AuthScope(target, "test realm", "basic")), Mockito.any());
     }
 
 }
\ No newline at end of file
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthentication.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthentication.java
index e443375..225b841 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthentication.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthentication.java
@@ -31,17 +31,12 @@ import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.nio.charset.StandardCharsets;
 import java.util.Collections;
-import java.util.List;
-import java.util.Map;
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.hc.client5.http.auth.AuthCache;
-import org.apache.hc.client5.http.auth.AuthChallenge;
 import org.apache.hc.client5.http.auth.AuthScheme;
 import org.apache.hc.client5.http.auth.AuthSchemeFactory;
 import org.apache.hc.client5.http.auth.AuthScope;
-import org.apache.hc.client5.http.auth.ChallengeType;
-import org.apache.hc.client5.http.auth.Credentials;
 import org.apache.hc.client5.http.auth.CredentialsProvider;
 import org.apache.hc.client5.http.auth.StandardAuthScheme;
 import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
@@ -82,6 +77,7 @@ import org.apache.hc.core5.http.protocol.HttpCoreContext;
 import org.apache.hc.core5.net.URIAuthority;
 import org.junit.Assert;
 import org.junit.Test;
+import org.mockito.Mockito;
 
 /**
  * Unit tests for automatic client authentication.
@@ -97,46 +93,24 @@ public class TestClientAuthentication extends LocalServerTestBase {
         return start(new BasicTestAuthenticator("test:test", "test realm"));
     }
 
-    static class TestCredentialsProvider implements CredentialsProvider {
-
-        private final Credentials creds;
-        private AuthScope authscope;
-
-        TestCredentialsProvider(final Credentials creds) {
-            super();
-            this.creds = creds;
-        }
-
-        @Override
-        public Credentials getCredentials(final AuthScope authscope, final HttpContext context) {
-            this.authscope = authscope;
-            return this.creds;
-        }
-
-        public AuthScope getAuthScope() {
-            return this.authscope;
-        }
-
-    }
-
     @Test
     public void testBasicAuthenticationNoCreds() throws Exception {
         this.server.registerHandler("*", new EchoHandler());
         final HttpHost target = start();
 
         final HttpClientContext context = HttpClientContext.create();
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(null);
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
         context.setCredentialsProvider(credsProvider);
         final HttpGet httpget = new HttpGet("/");
 
-        final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
-        final HttpEntity entity = response.getEntity();
-        Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
-        Assert.assertNotNull(entity);
-        EntityUtils.consume(entity);
-        final AuthScope authscope = credsProvider.getAuthScope();
-        Assert.assertNotNull(authscope);
-        Assert.assertEquals("test realm", authscope.getRealm());
+        try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
+            final HttpEntity entity = response.getEntity();
+            Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
+            Assert.assertNotNull(entity);
+            EntityUtils.consume(entity);
+        }
+        Mockito.verify(credsProvider).getCredentials(
+                Mockito.eq(new AuthScope(target, "test realm", "basic")), Mockito.any());
     }
 
     @Test
@@ -145,19 +119,20 @@ public class TestClientAuthentication extends LocalServerTestBase {
         final HttpHost target = start();
 
         final HttpClientContext context = HttpClientContext.create();
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
-                new UsernamePasswordCredentials("test", "all-wrong".toCharArray()));
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
+        Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any()))
+                .thenReturn(new UsernamePasswordCredentials("test", "all-wrong".toCharArray()));
         context.setCredentialsProvider(credsProvider);
         final HttpGet httpget = new HttpGet("/");
 
-        final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
-        final HttpEntity entity = response.getEntity();
-        Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
-        Assert.assertNotNull(entity);
-        EntityUtils.consume(entity);
-        final AuthScope authscope = credsProvider.getAuthScope();
-        Assert.assertNotNull(authscope);
-        Assert.assertEquals("test realm", authscope.getRealm());
+        try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
+            final HttpEntity entity = response.getEntity();
+            Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
+            Assert.assertNotNull(entity);
+            EntityUtils.consume(entity);
+        }
+        Mockito.verify(credsProvider).getCredentials(
+                Mockito.eq(new AuthScope(target, "test realm", "basic")), Mockito.any());
     }
 
     @Test
@@ -165,20 +140,21 @@ public class TestClientAuthentication extends LocalServerTestBase {
         this.server.registerHandler("*", new EchoHandler());
         final HttpGet httpget = new HttpGet("/");
         final HttpClientContext context = HttpClientContext.create();
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
-                new UsernamePasswordCredentials("test", "test".toCharArray()));
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
+        Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any()))
+                .thenReturn(new UsernamePasswordCredentials("test", "test".toCharArray()));
         context.setCredentialsProvider(credsProvider);
 
         final HttpHost target = start();
 
-        final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
-        final HttpEntity entity = response.getEntity();
-        Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
-        Assert.assertNotNull(entity);
-        EntityUtils.consume(entity);
-        final AuthScope authscope = credsProvider.getAuthScope();
-        Assert.assertNotNull(authscope);
-        Assert.assertEquals("test realm", authscope.getRealm());
+        try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
+            final HttpEntity entity = response.getEntity();
+            Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
+            Assert.assertNotNull(entity);
+            EntityUtils.consume(entity);
+        }
+        Mockito.verify(credsProvider).getCredentials(
+                Mockito.eq(new AuthScope(target, "test realm", "basic")), Mockito.any());
     }
 
     @Test
@@ -196,14 +172,16 @@ public class TestClientAuthentication extends LocalServerTestBase {
                         new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 } ),
                         -1, null));
         final HttpClientContext context = HttpClientContext.create();
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
-                new UsernamePasswordCredentials("test", "test".toCharArray()));
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
+        Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any()))
+                .thenReturn(new UsernamePasswordCredentials("test", "test".toCharArray()));
         context.setCredentialsProvider(credsProvider);
 
-        final ClassicHttpResponse response = this.httpclient.execute(target, httpput, context);
-        final HttpEntity entity = response.getEntity();
-        Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
-        Assert.assertNotNull(entity);
+        try (final ClassicHttpResponse response = this.httpclient.execute(target, httpput, context)) {
+            final HttpEntity entity = response.getEntity();
+            Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
+            Assert.assertNotNull(entity);
+        }
     }
 
     @Test
@@ -220,15 +198,17 @@ public class TestClientAuthentication extends LocalServerTestBase {
                         -1, null));
 
         final HttpClientContext context = HttpClientContext.create();
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
-                new UsernamePasswordCredentials("test", "boom".toCharArray()));
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
+        Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any()))
+                .thenReturn(new UsernamePasswordCredentials("test", "boom".toCharArray()));
         context.setCredentialsProvider(credsProvider);
 
-        final CloseableHttpResponse response = this.httpclient.execute(target, httpput, context);
-        final HttpEntity entity = response.getEntity();
-        Assert.assertEquals(401, response.getCode());
-        Assert.assertNotNull(entity);
-        EntityUtils.consume(entity);
+        try (final CloseableHttpResponse response = this.httpclient.execute(target, httpput, context)) {
+            final HttpEntity entity = response.getEntity();
+            Assert.assertEquals(401, response.getCode());
+            Assert.assertNotNull(entity);
+            EntityUtils.consume(entity);
+        }
     }
 
     @Test
@@ -240,18 +220,19 @@ public class TestClientAuthentication extends LocalServerTestBase {
         httppost.setEntity(new StringEntity("some important stuff", StandardCharsets.US_ASCII));
 
         final HttpClientContext context = HttpClientContext.create();
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
-                new UsernamePasswordCredentials("test", "test".toCharArray()));
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
+        Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any()))
+                .thenReturn(new UsernamePasswordCredentials("test", "test".toCharArray()));
         context.setCredentialsProvider(credsProvider);
 
-        final ClassicHttpResponse response = this.httpclient.execute(target, httppost, context);
-        final HttpEntity entity = response.getEntity();
-        Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
-        Assert.assertNotNull(entity);
-        EntityUtils.consume(entity);
-        final AuthScope authscope = credsProvider.getAuthScope();
-        Assert.assertNotNull(authscope);
-        Assert.assertEquals("test realm", authscope.getRealm());
+        try (final ClassicHttpResponse response = this.httpclient.execute(target, httppost, context)) {
+            final HttpEntity entity = response.getEntity();
+            Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
+            Assert.assertNotNull(entity);
+            EntityUtils.consume(entity);
+        }
+        Mockito.verify(credsProvider).getCredentials(
+                Mockito.eq(new AuthScope(target, "test realm", "basic")), Mockito.any());
     }
 
     @Test
@@ -268,46 +249,23 @@ public class TestClientAuthentication extends LocalServerTestBase {
         context.setRequestConfig(RequestConfig.custom()
                 .setExpectContinueEnabled(false)
                 .build());
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
-                new UsernamePasswordCredentials("test", "test".toCharArray()));
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
+        Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any()))
+                .thenReturn(new UsernamePasswordCredentials("test", "test".toCharArray()));
         context.setCredentialsProvider(credsProvider);
 
-        final CloseableHttpResponse response = this.httpclient.execute(target, httppost, context);
-        final HttpEntity entity = response.getEntity();
-        Assert.assertEquals(401, response.getCode());
-        Assert.assertNotNull(entity);
-        EntityUtils.consume(entity);
-    }
-
-    static class TestTargetAuthenticationStrategy extends DefaultAuthenticationStrategy {
-
-        private final AtomicLong count;
-
-        public TestTargetAuthenticationStrategy() {
-            super();
-            this.count = new AtomicLong();
+        try (final CloseableHttpResponse response = this.httpclient.execute(target, httppost, context)) {
+            final HttpEntity entity = response.getEntity();
+            Assert.assertEquals(401, response.getCode());
+            Assert.assertNotNull(entity);
+            EntityUtils.consume(entity);
         }
-
-        @Override
-        public List<AuthScheme> select(
-                final ChallengeType challengeType,
-                final Map<String, AuthChallenge> challenges,
-                final HttpContext context) {
-            final List<AuthScheme> authSchemes = super.select(challengeType, challenges, context);
-            this.count.incrementAndGet();
-            return authSchemes;
-        }
-
-        public long getCount() {
-            return this.count.get();
-        }
-
     }
 
     @Test
     public void testBasicAuthenticationCredentialsCaching() throws Exception {
         this.server.registerHandler("*", new EchoHandler());
-        final TestTargetAuthenticationStrategy authStrategy = new TestTargetAuthenticationStrategy();
+        final DefaultAuthenticationStrategy authStrategy = Mockito.spy(new DefaultAuthenticationStrategy());
         this.clientBuilder.setTargetAuthenticationStrategy(authStrategy);
 
         final HttpHost target = start();
@@ -319,19 +277,21 @@ public class TestClientAuthentication extends LocalServerTestBase {
 
         final HttpGet httpget = new HttpGet("/");
 
-        final ClassicHttpResponse response1 = this.httpclient.execute(target, httpget, context);
-        final HttpEntity entity1 = response1.getEntity();
-        Assert.assertEquals(HttpStatus.SC_OK, response1.getCode());
-        Assert.assertNotNull(entity1);
-        EntityUtils.consume(entity1);
+        try (final ClassicHttpResponse response1 = this.httpclient.execute(target, httpget, context)) {
+            final HttpEntity entity1 = response1.getEntity();
+            Assert.assertEquals(HttpStatus.SC_OK, response1.getCode());
+            Assert.assertNotNull(entity1);
+            EntityUtils.consume(entity1);
+        }
 
-        final ClassicHttpResponse response2 = this.httpclient.execute(target, httpget, context);
-        final HttpEntity entity2 = response1.getEntity();
-        Assert.assertEquals(HttpStatus.SC_OK, response2.getCode());
-        Assert.assertNotNull(entity2);
-        EntityUtils.consume(entity2);
+        try (final ClassicHttpResponse response2 = this.httpclient.execute(target, httpget, context)) {
+            final HttpEntity entity2 = response2.getEntity();
+            Assert.assertEquals(HttpStatus.SC_OK, response2.getCode());
+            Assert.assertNotNull(entity2);
+            EntityUtils.consume(entity2);
+        }
 
-        Assert.assertEquals(1, authStrategy.getCount());
+        Mockito.verify(authStrategy).select(Mockito.any(), Mockito.any(), Mockito.any());
     }
 
     @Test
@@ -363,7 +323,7 @@ public class TestClientAuthentication extends LocalServerTestBase {
 
         });
 
-        final TestTargetAuthenticationStrategy authStrategy = new TestTargetAuthenticationStrategy();
+        final DefaultAuthenticationStrategy authStrategy = Mockito.spy(new DefaultAuthenticationStrategy());
         final CredentialsProvider credsProvider = CredentialsProviderBuilder.create()
                 .add(new AuthScope(target, "this realm", null), "test", "this".toCharArray())
                 .add(new AuthScope(target, "that realm", null), "test", "that".toCharArray())
@@ -377,29 +337,32 @@ public class TestClientAuthentication extends LocalServerTestBase {
 
         final HttpGet httpget1 = new HttpGet("/this");
 
-        final ClassicHttpResponse response1 = this.httpclient.execute(target, httpget1, context);
-        final HttpEntity entity1 = response1.getEntity();
-        Assert.assertEquals(HttpStatus.SC_OK, response1.getCode());
-        Assert.assertNotNull(entity1);
-        EntityUtils.consume(entity1);
+        try (final ClassicHttpResponse response1 = this.httpclient.execute(target, httpget1, context)) {
+            final HttpEntity entity1 = response1.getEntity();
+            Assert.assertEquals(HttpStatus.SC_OK, response1.getCode());
+            Assert.assertNotNull(entity1);
+            EntityUtils.consume(entity1);
+        }
 
         final HttpGet httpget2 = new HttpGet("/this");
 
-        final ClassicHttpResponse response2 = this.httpclient.execute(target, httpget2, context);
-        final HttpEntity entity2 = response1.getEntity();
-        Assert.assertEquals(HttpStatus.SC_OK, response2.getCode());
-        Assert.assertNotNull(entity2);
-        EntityUtils.consume(entity2);
+        try (final ClassicHttpResponse response2 = this.httpclient.execute(target, httpget2, context)) {
+            final HttpEntity entity2 = response2.getEntity();
+            Assert.assertEquals(HttpStatus.SC_OK, response2.getCode());
+            Assert.assertNotNull(entity2);
+            EntityUtils.consume(entity2);
+        }
 
         final HttpGet httpget3 = new HttpGet("/that");
 
-        final ClassicHttpResponse response3 = this.httpclient.execute(target, httpget3, context);
-        final HttpEntity entity3 = response1.getEntity();
-        Assert.assertEquals(HttpStatus.SC_OK, response3.getCode());
-        Assert.assertNotNull(entity3);
-        EntityUtils.consume(entity3);
+        try (final ClassicHttpResponse response3 = this.httpclient.execute(target, httpget3, context)) {
+            final HttpEntity entity3 = response3.getEntity();
+            Assert.assertEquals(HttpStatus.SC_OK, response3.getCode());
+            Assert.assertNotNull(entity3);
+            EntityUtils.consume(entity3);
+        }
 
-        Assert.assertEquals(2, authStrategy.getCount());
+        Mockito.verify(authStrategy, Mockito.times(2)).select(Mockito.any(), Mockito.any(), Mockito.any());
     }
 
     @Test
@@ -409,11 +372,12 @@ public class TestClientAuthentication extends LocalServerTestBase {
         final HttpGet httpget = new HttpGet("http://test:test@" +  target.toHostString() + "/");
 
         final HttpClientContext context = HttpClientContext.create();
-        final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
-        final HttpEntity entity = response.getEntity();
-        Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
-        Assert.assertNotNull(entity);
-        EntityUtils.consume(entity);
+        try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
+            final HttpEntity entity = response.getEntity();
+            Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
+            Assert.assertNotNull(entity);
+            EntityUtils.consume(entity);
+        }
     }
 
     @Test
@@ -423,11 +387,12 @@ public class TestClientAuthentication extends LocalServerTestBase {
         final HttpGet httpget = new HttpGet("http://test:all-wrong@" +  target.toHostString() + "/");
 
         final HttpClientContext context = HttpClientContext.create();
-        final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
-        final HttpEntity entity = response.getEntity();
-        Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
-        Assert.assertNotNull(entity);
-        EntityUtils.consume(entity);
+        try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
+            final HttpEntity entity = response.getEntity();
+            Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
+            Assert.assertNotNull(entity);
+            EntityUtils.consume(entity);
+        }
     }
 
     @Test
@@ -455,11 +420,12 @@ public class TestClientAuthentication extends LocalServerTestBase {
         final HttpGet httpget = new HttpGet("/thatway");
         final HttpClientContext context = HttpClientContext.create();
 
-        final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
-        final HttpEntity entity = response.getEntity();
-        Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
-        Assert.assertNotNull(entity);
-        EntityUtils.consume(entity);
+        try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
+            final HttpEntity entity = response.getEntity();
+            Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
+            Assert.assertNotNull(entity);
+            EntityUtils.consume(entity);
+        }
     }
 
     static class CountingAuthenticator extends BasicTestAuthenticator {
@@ -497,11 +463,12 @@ public class TestClientAuthentication extends LocalServerTestBase {
         context.setAuthCache(authCache);
 
         final HttpGet httpget = new HttpGet("/");
-        final ClassicHttpResponse response1 = this.httpclient.execute(target, httpget, context);
-        final HttpEntity entity1 = response1.getEntity();
-        Assert.assertEquals(HttpStatus.SC_OK, response1.getCode());
-        Assert.assertNotNull(entity1);
-        EntityUtils.consume(entity1);
+        try (final ClassicHttpResponse response1 = this.httpclient.execute(target, httpget, context)) {
+            final HttpEntity entity1 = response1.getEntity();
+            Assert.assertEquals(HttpStatus.SC_OK, response1.getCode());
+            Assert.assertNotNull(entity1);
+            EntityUtils.consume(entity1);
+        }
 
         Assert.assertEquals(1, countingAuthenticator.getCount());
     }
@@ -522,11 +489,12 @@ public class TestClientAuthentication extends LocalServerTestBase {
                 .build());
 
         final HttpGet httpget = new HttpGet("/");
-        final ClassicHttpResponse response1 = this.httpclient.execute(target, httpget, context);
-        final HttpEntity entity1 = response1.getEntity();
-        Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response1.getCode());
-        Assert.assertNotNull(entity1);
-        EntityUtils.consume(entity1);
+        try (final ClassicHttpResponse response1 = this.httpclient.execute(target, httpget, context)) {
+            final HttpEntity entity1 = response1.getEntity();
+            Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response1.getCode());
+            Assert.assertNotNull(entity1);
+            EntityUtils.consume(entity1);
+        }
 
         Assert.assertEquals(1, countingAuthenticator.getCount());
     }
@@ -557,15 +525,15 @@ public class TestClientAuthentication extends LocalServerTestBase {
         final HttpHost target = super.start();
 
         final HttpClientContext context = HttpClientContext.create();
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(null);
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
         context.setCredentialsProvider(credsProvider);
 
         final HttpGet httpget = new HttpGet("/");
-        final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
-        final HttpEntity entity = response.getEntity();
-        Assert.assertEquals(HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED,
-                response.getCode());
-        EntityUtils.consume(entity);
+        try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
+            final HttpEntity entity = response.getEntity();
+            Assert.assertEquals(HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED, response.getCode());
+            EntityUtils.consume(entity);
+        }
     }
 
     @Test
@@ -592,9 +560,10 @@ public class TestClientAuthentication extends LocalServerTestBase {
         for (int i = 0; i < 2; i++) {
             final HttpGet httpget = new HttpGet("/");
 
-            final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
-            EntityUtils.consume(response.getEntity());
-            Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
+            try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
+                EntityUtils.consume(response.getEntity());
+                Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
+            }
         }
     }
 
@@ -619,8 +588,9 @@ public class TestClientAuthentication extends LocalServerTestBase {
 
         };
 
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
-                new UsernamePasswordCredentials("test", "test".toCharArray()));
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
+        Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any()))
+                .thenReturn(new UsernamePasswordCredentials("test", "test".toCharArray()));
 
         final RequestConfig config = RequestConfig.custom()
                 .setTargetPreferredAuthSchemes(Collections.singletonList("MyBasic"))
@@ -688,19 +658,20 @@ public class TestClientAuthentication extends LocalServerTestBase {
                 });
 
         final HttpClientContext context = HttpClientContext.create();
-        final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
-                new UsernamePasswordCredentials("test", "test".toCharArray()));
+        final CredentialsProvider credsProvider = Mockito.mock(CredentialsProvider.class);
+        Mockito.when(credsProvider.getCredentials(Mockito.any(), Mockito.any()))
+                .thenReturn(new UsernamePasswordCredentials("test", "test".toCharArray()));
         context.setCredentialsProvider(credsProvider);
         final HttpGet httpget = new HttpGet("/");
 
-        final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
-        final HttpEntity entity = response.getEntity();
-        Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
-        Assert.assertNotNull(entity);
-        EntityUtils.consume(entity);
-        final AuthScope authscope = credsProvider.getAuthScope();
-        Assert.assertNotNull(authscope);
-        Assert.assertEquals("test realm", authscope.getRealm());
+        try (final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context)) {
+            final HttpEntity entity = response.getEntity();
+            Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
+            Assert.assertNotNull(entity);
+            EntityUtils.consume(entity);
+        }
+        Mockito.verify(credsProvider).getCredentials(
+                Mockito.eq(new AuthScope(target, "test realm", "basic")), Mockito.any());
     }
 
 }

[httpcomponents-client] 01/02: Added immutable CredentialsProvider implementations and a CredentialsProvider builder; changed test cases and examples to use immutable CredentialsProvider where possible

Posted by ol...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

olegk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-client.git

commit 3aeba1ba21f645228f1f9b3cf679fe88f54f7204
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Thu Sep 23 12:34:27 2021 +0200

    Added immutable CredentialsProvider implementations and a CredentialsProvider builder; changed test cases and examples to use immutable CredentialsProvider where possible
---
 .../AbstractHttpAsyncClientAuthentication.java     |   9 +-
 .../testing/sync/TestClientAuthentication.java     |  31 +++--
 .../sync/TestClientAuthenticationFakeNTLM.java     |  38 +++---
 .../hc/client5/testing/sync/TestSPNegoScheme.java  |  15 +--
 .../http/impl/auth/BasicCredentialsProvider.java   |  41 +------
 ...ntialsProvider.java => CredentialsMatcher.java} |  53 +--------
 .../http/impl/auth/CredentialsProviderBuilder.java | 104 +++++++++++++++++
 .../http/impl/auth/FixedCredentialsProvider.java   |  57 +++++++++
 .../http/impl/auth/SingleCredentialsProvider.java  |  61 ++++++++++
 .../http/examples/AsyncClientAuthentication.java   |  13 +--
 .../http/examples/ClientAuthentication.java        |  13 +--
 .../client5/http/examples/ClientConfiguration.java |   5 +-
 .../ClientPreemptiveDigestAuthentication.java      |  11 +-
 .../http/examples/ClientProxyAuthentication.java   |  18 ++-
 .../http/impl/TestAuthenticationStrategy.java      |  18 ++-
 .../hc/client5/http/impl/auth/TestBasicScheme.java |  15 ++-
 ...Provider.java => TestCredentialsProviders.java} |  24 +++-
 .../client5/http/impl/auth/TestDigestScheme.java   | 129 +++++++++------------
 .../http/impl/auth/TestRequestAuthCache.java       |  10 +-
 .../client5/http/impl/classic/TestConnectExec.java |  15 +--
 .../http/impl/classic/TestProtocolExec.java        |  20 ++--
 21 files changed, 410 insertions(+), 290 deletions(-)

diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncClientAuthentication.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncClientAuthentication.java
index 307b82d..7a0c7e3 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncClientAuthentication.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/AbstractHttpAsyncClientAuthentication.java
@@ -48,8 +48,8 @@ import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
 import org.apache.hc.client5.http.config.RequestConfig;
 import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy;
 import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
-import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
 import org.apache.hc.client5.http.impl.auth.BasicScheme;
+import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
 import org.apache.hc.client5.http.protocol.HttpClientContext;
 import org.apache.hc.client5.testing.BasicTestAuthenticator;
 import org.apache.hc.client5.testing.auth.Authenticator;
@@ -298,11 +298,10 @@ public abstract class AbstractHttpAsyncClientAuthentication<T extends CloseableH
         });
         final HttpHost target = start();
 
-        final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
-        credsProvider.setCredentials(new AuthScope(null, null, -1, null ,null),
-                new UsernamePasswordCredentials("test", "test".toCharArray()));
         final HttpClientContext context = HttpClientContext.create();
-        context.setCredentialsProvider(credsProvider);
+        context.setCredentialsProvider(CredentialsProviderBuilder.create()
+                        .add(target, "test", "test".toCharArray())
+                .build());
 
         final Future<SimpleHttpResponse> future1 = httpclient.execute(SimpleRequestBuilder.get()
                         .setHttpHost(target)
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthentication.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthentication.java
index 1473062..e443375 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthentication.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthentication.java
@@ -51,9 +51,9 @@ import org.apache.hc.client5.http.classic.methods.HttpPut;
 import org.apache.hc.client5.http.config.RequestConfig;
 import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy;
 import org.apache.hc.client5.http.impl.auth.BasicAuthCache;
-import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
 import org.apache.hc.client5.http.impl.auth.BasicScheme;
 import org.apache.hc.client5.http.impl.auth.BasicSchemeFactory;
+import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
 import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
 import org.apache.hc.client5.http.protocol.HttpClientContext;
 import org.apache.hc.client5.testing.BasicTestAuthenticator;
@@ -313,10 +313,9 @@ public class TestClientAuthentication extends LocalServerTestBase {
         final HttpHost target = start();
 
         final HttpClientContext context = HttpClientContext.create();
-        final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
-        credsProvider.setCredentials(new AuthScope(null, null, -1, null ,null),
-                new UsernamePasswordCredentials("test", "test".toCharArray()));
-        context.setCredentialsProvider(credsProvider);
+        context.setCredentialsProvider(CredentialsProviderBuilder.create()
+                .add(target, "test", "test".toCharArray())
+                .build());
 
         final HttpGet httpget = new HttpGet("/");
 
@@ -365,11 +364,10 @@ public class TestClientAuthentication extends LocalServerTestBase {
         });
 
         final TestTargetAuthenticationStrategy authStrategy = new TestTargetAuthenticationStrategy();
-        final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
-        credsProvider.setCredentials(new AuthScope(target, "this realm", null),
-                new UsernamePasswordCredentials("test", "this".toCharArray()));
-        credsProvider.setCredentials(new AuthScope(target, "that realm", null),
-                new UsernamePasswordCredentials("test", "that".toCharArray()));
+        final CredentialsProvider credsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(target, "this realm", null), "test", "this".toCharArray())
+                .add(new AuthScope(target, "that realm", null), "test", "that".toCharArray())
+                .build();
 
         this.clientBuilder.setTargetAuthenticationStrategy(authStrategy);
         this.httpclient = this.clientBuilder.build();
@@ -519,10 +517,9 @@ public class TestClientAuthentication extends LocalServerTestBase {
         final AuthCache authCache = new BasicAuthCache();
         authCache.put(target, new BasicScheme());
         context.setAuthCache(authCache);
-        final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
-        credsProvider.setCredentials(new AuthScope(null, null, -1, null ,null),
-                new UsernamePasswordCredentials("test", "stuff".toCharArray()));
-        context.setCredentialsProvider(credsProvider);
+        context.setCredentialsProvider(CredentialsProviderBuilder.create()
+                .add(target, "test", "stuff".toCharArray())
+                .build());
 
         final HttpGet httpget = new HttpGet("/");
         final ClassicHttpResponse response1 = this.httpclient.execute(target, httpget, context);
@@ -587,9 +584,9 @@ public class TestClientAuthentication extends LocalServerTestBase {
                 });
 
         final HttpClientContext context = HttpClientContext.create();
-        final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
-        credsProvider.setCredentials(new AuthScope(null, null, -1, null ,null),
-                new UsernamePasswordCredentials("test", "test".toCharArray()));
+        final CredentialsProvider credsProvider = CredentialsProviderBuilder.create()
+                .add(target, "test", "test".toCharArray())
+                .build();
         context.setCredentialsProvider(credsProvider);
 
         for (int i = 0; i < 2; i++) {
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthenticationFakeNTLM.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthenticationFakeNTLM.java
index 1ca26a8..f4a3d9e 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthenticationFakeNTLM.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestClientAuthenticationFakeNTLM.java
@@ -28,11 +28,11 @@ package org.apache.hc.client5.testing.sync;
 
 import java.io.IOException;
 
-import org.apache.hc.client5.http.auth.StandardAuthScheme;
-import org.apache.hc.client5.http.auth.AuthScope;
+import org.apache.hc.client5.http.auth.CredentialsProvider;
 import org.apache.hc.client5.http.auth.NTCredentials;
+import org.apache.hc.client5.http.auth.StandardAuthScheme;
 import org.apache.hc.client5.http.classic.methods.HttpGet;
-import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
+import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
 import org.apache.hc.client5.http.impl.classic.HttpClients;
 import org.apache.hc.client5.http.protocol.HttpClientContext;
 import org.apache.hc.core5.http.ClassicHttpRequest;
@@ -71,9 +71,9 @@ public class TestClientAuthenticationFakeNTLM extends LocalServerTestBase {
 
         final HttpHost target = start();
 
-        final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
-        credsProvider.setCredentials(new AuthScope(null, null, -1, null ,null),
-                new NTCredentials("test", "test".toCharArray(), null, null));
+        final CredentialsProvider credsProvider = CredentialsProviderBuilder.create()
+                .add(target, new NTCredentials("test", "test".toCharArray(), null, null))
+                .build();
 
         this.httpclient = HttpClients.custom()
                 .setDefaultCredentialsProvider(credsProvider)
@@ -118,9 +118,9 @@ public class TestClientAuthenticationFakeNTLM extends LocalServerTestBase {
                 "AGUAcgB2AGUAcgA="));
         final HttpHost target = start();
 
-        final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
-        credsProvider.setCredentials(new AuthScope(null, null, -1, null ,null),
-                new NTCredentials("test", "test".toCharArray(), null, null));
+        final CredentialsProvider credsProvider = CredentialsProviderBuilder.create()
+                .add(target, new NTCredentials("test", "test".toCharArray(), null, null))
+                .build();
 
         this.httpclient = HttpClients.custom()
                 .setDefaultCredentialsProvider(credsProvider)
@@ -142,9 +142,9 @@ public class TestClientAuthenticationFakeNTLM extends LocalServerTestBase {
                 "AGUAcgB2AGUAcgACAAwARABvAG0AYQBpAG4AAQAMAFMAZQByAHYAZQByAAAAAAA="));
         final HttpHost target = start();
 
-        final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
-        credsProvider.setCredentials(new AuthScope(null, null, -1, null ,null),
-                new NTCredentials("test", "test".toCharArray(), null, null));
+        final CredentialsProvider credsProvider = CredentialsProviderBuilder.create()
+                .add(target, new NTCredentials("test", "test".toCharArray(), null, null))
+                .build();
 
         this.httpclient = HttpClients.custom()
                 .setDefaultCredentialsProvider(credsProvider)
@@ -187,10 +187,9 @@ public class TestClientAuthenticationFakeNTLM extends LocalServerTestBase {
         final HttpHost target = start();
 
         final HttpClientContext context = HttpClientContext.create();
-        final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
-        credsProvider.setCredentials(new AuthScope(null, null, -1, null ,null),
-                new NTCredentials("test", "test".toCharArray(), null, null));
-        context.setCredentialsProvider(credsProvider);
+        context.setCredentialsProvider(CredentialsProviderBuilder.create()
+                .add(target, new NTCredentials("test", "test".toCharArray(), null, null))
+                .build());
         final HttpGet httpget = new HttpGet("/");
 
         final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
@@ -208,10 +207,9 @@ public class TestClientAuthenticationFakeNTLM extends LocalServerTestBase {
         final HttpHost target = start();
 
         final HttpClientContext context = HttpClientContext.create();
-        final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
-        credsProvider.setCredentials(new AuthScope(null, null, -1, null ,null),
-                new NTCredentials("test", "test".toCharArray(), null, null));
-        context.setCredentialsProvider(credsProvider);
+        context.setCredentialsProvider(CredentialsProviderBuilder.create()
+                .add(target, new NTCredentials("test", "test".toCharArray(), null, null))
+                .build());
         final HttpGet httpget = new HttpGet("/");
 
         final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSPNegoScheme.java b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSPNegoScheme.java
index 6947d8f..1a516b1 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSPNegoScheme.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/sync/TestSPNegoScheme.java
@@ -34,10 +34,11 @@ import org.apache.hc.client5.http.auth.AuthScheme;
 import org.apache.hc.client5.http.auth.AuthSchemeFactory;
 import org.apache.hc.client5.http.auth.AuthScope;
 import org.apache.hc.client5.http.auth.Credentials;
+import org.apache.hc.client5.http.auth.CredentialsProvider;
 import org.apache.hc.client5.http.auth.KerberosConfig;
 import org.apache.hc.client5.http.auth.StandardAuthScheme;
 import org.apache.hc.client5.http.classic.methods.HttpGet;
-import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
+import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
 import org.apache.hc.client5.http.impl.auth.SPNegoScheme;
 import org.apache.hc.client5.http.impl.classic.HttpClients;
 import org.apache.hc.core5.http.ClassicHttpRequest;
@@ -153,9 +154,9 @@ public class TestSPNegoScheme extends LocalServerTestBase {
         final HttpHost target = start();
 
         final AuthSchemeFactory nsf = new NegotiateSchemeFactoryWithMockGssManager();
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials use_jaas_creds = new UseJaasCredentials();
-        credentialsProvider.setCredentials(new AuthScope(null, null, -1, null, null), use_jaas_creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(null, null, -1, null, null), new UseJaasCredentials())
+                .build();
 
         final Registry<AuthSchemeFactory> authSchemeRegistry = RegistryBuilder.<AuthSchemeFactory>create()
             .register(StandardAuthScheme.SPNEGO, nsf)
@@ -184,9 +185,9 @@ public class TestSPNegoScheme extends LocalServerTestBase {
 
         final AuthSchemeFactory nsf = new NegotiateSchemeFactoryWithMockGssManager();
 
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials use_jaas_creds = new UseJaasCredentials();
-        credentialsProvider.setCredentials(new AuthScope(null, null, -1, null, null), use_jaas_creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(null, null, -1, null, null), new UseJaasCredentials())
+                .build();
 
         final Registry<AuthSchemeFactory> authSchemeRegistry = RegistryBuilder.<AuthSchemeFactory>create()
             .register(StandardAuthScheme.SPNEGO, nsf)
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/BasicCredentialsProvider.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/BasicCredentialsProvider.java
index 579d8b2..e58dc11 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/BasicCredentialsProvider.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/BasicCredentialsProvider.java
@@ -26,7 +26,6 @@
  */
 package org.apache.hc.client5.http.impl.auth;
 
-import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.hc.client5.http.auth.AuthScope;
@@ -63,43 +62,9 @@ public class BasicCredentialsProvider implements CredentialsStore {
         credMap.put(authScope, credentials);
     }
 
-    /**
-     * Find matching {@link Credentials credentials} for the given authentication scope.
-     *
-     * @param map the credentials hash map
-     * @param authScope the {@link AuthScope authentication scope}
-     * @return the credentials
-     *
-     */
-    private static Credentials matchCredentials(
-            final Map<AuthScope, Credentials> map,
-            final AuthScope authScope) {
-        // see if we get a direct hit
-        Credentials creds = map.get(authScope);
-        if (creds == null) {
-            // Nope.
-            // Do a full scan
-            int bestMatchFactor  = -1;
-            AuthScope bestMatch  = null;
-            for (final AuthScope current: map.keySet()) {
-                final int factor = authScope.match(current);
-                if (factor > bestMatchFactor) {
-                    bestMatchFactor = factor;
-                    bestMatch = current;
-                }
-            }
-            if (bestMatch != null) {
-                creds = map.get(bestMatch);
-            }
-        }
-        return creds;
-    }
-
     @Override
-    public Credentials getCredentials(final AuthScope authScope,
-                                      final HttpContext httpContext) {
-        Args.notNull(authScope, "Authentication scope");
-        return matchCredentials(this.credMap, authScope);
+    public Credentials getCredentials(final AuthScope authScope, final HttpContext context) {
+        return CredentialsMatcher.matchCredentials(this.credMap, authScope);
     }
 
     @Override
@@ -109,7 +74,7 @@ public class BasicCredentialsProvider implements CredentialsStore {
 
     @Override
     public String toString() {
-        return credMap.toString();
+        return credMap.keySet().toString();
     }
 
 }
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/BasicCredentialsProvider.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/CredentialsMatcher.java
similarity index 59%
copy from httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/BasicCredentialsProvider.java
copy to httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/CredentialsMatcher.java
index 579d8b2..ea334f3 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/BasicCredentialsProvider.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/CredentialsMatcher.java
@@ -27,41 +27,11 @@
 package org.apache.hc.client5.http.impl.auth;
 
 import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.hc.client5.http.auth.AuthScope;
 import org.apache.hc.client5.http.auth.Credentials;
-import org.apache.hc.client5.http.auth.CredentialsStore;
-import org.apache.hc.core5.annotation.Contract;
-import org.apache.hc.core5.annotation.ThreadingBehavior;
-import org.apache.hc.core5.http.protocol.HttpContext;
-import org.apache.hc.core5.util.Args;
 
-/**
- * Default implementation of {@link CredentialsStore}.
- *
- * @since 4.0
- */
-@Contract(threading = ThreadingBehavior.SAFE)
-public class BasicCredentialsProvider implements CredentialsStore {
-
-    private final ConcurrentHashMap<AuthScope, Credentials> credMap;
-
-    /**
-     * Default constructor.
-     */
-    public BasicCredentialsProvider() {
-        super();
-        this.credMap = new ConcurrentHashMap<>();
-    }
-
-    @Override
-    public void setCredentials(
-            final AuthScope authScope,
-            final Credentials credentials) {
-        Args.notNull(authScope, "Authentication scope");
-        credMap.put(authScope, credentials);
-    }
+final class CredentialsMatcher {
 
     /**
      * Find matching {@link Credentials credentials} for the given authentication scope.
@@ -71,9 +41,7 @@ public class BasicCredentialsProvider implements CredentialsStore {
      * @return the credentials
      *
      */
-    private static Credentials matchCredentials(
-            final Map<AuthScope, Credentials> map,
-            final AuthScope authScope) {
+    static Credentials matchCredentials(final Map<AuthScope, Credentials> map, final AuthScope authScope) {
         // see if we get a direct hit
         Credentials creds = map.get(authScope);
         if (creds == null) {
@@ -95,21 +63,4 @@ public class BasicCredentialsProvider implements CredentialsStore {
         return creds;
     }
 
-    @Override
-    public Credentials getCredentials(final AuthScope authScope,
-                                      final HttpContext httpContext) {
-        Args.notNull(authScope, "Authentication scope");
-        return matchCredentials(this.credMap, authScope);
-    }
-
-    @Override
-    public void clear() {
-        this.credMap.clear();
-    }
-
-    @Override
-    public String toString() {
-        return credMap.toString();
-    }
-
 }
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/CredentialsProviderBuilder.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/CredentialsProviderBuilder.java
new file mode 100644
index 0000000..74fcc38
--- /dev/null
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/CredentialsProviderBuilder.java
@@ -0,0 +1,104 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.hc.client5.http.impl.auth;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.hc.client5.http.auth.AuthScope;
+import org.apache.hc.client5.http.auth.Credentials;
+import org.apache.hc.client5.http.auth.CredentialsProvider;
+import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.util.Args;
+
+/**
+ * {@link CredentialsProvider} builder.
+ *
+ * @since 5.2
+ */
+public final class CredentialsProviderBuilder {
+
+    private final Map<AuthScope, Credentials> credMap;
+
+    public static CredentialsProviderBuilder create() {
+        return new CredentialsProviderBuilder();
+    }
+
+    public CredentialsProviderBuilder() {
+        super();
+        this.credMap = new HashMap<>();
+    }
+
+    public CredentialsProviderBuilder add(final AuthScope authScope, final Credentials credentials) {
+        Args.notNull(authScope, "Host");
+        credMap.put(authScope, credentials);
+        return this;
+    }
+
+    public CredentialsProviderBuilder add(final AuthScope authScope, final String username, final char[] password) {
+        Args.notNull(authScope, "Host");
+        credMap.put(authScope, new UsernamePasswordCredentials(username, password));
+        return this;
+    }
+
+    public CredentialsProviderBuilder add(final HttpHost httpHost, final Credentials credentials) {
+        Args.notNull(httpHost, "Host");
+        credMap.put(new AuthScope(httpHost), credentials);
+        return this;
+    }
+
+    public CredentialsProviderBuilder add(final HttpHost httpHost, final String username, final char[] password) {
+        Args.notNull(httpHost, "Host");
+        credMap.put(new AuthScope(httpHost), new UsernamePasswordCredentials(username, password));
+        return this;
+    }
+
+    public CredentialsProvider build() {
+        if (credMap.size() == 0) {
+            return new BasicCredentialsProvider();
+        } else if (credMap.size() == 1) {
+            final Map.Entry<AuthScope, Credentials> entry = credMap.entrySet().iterator().next();
+            return new SingleCredentialsProvider(entry.getKey(), entry.getValue());
+        } else {
+            return new FixedCredentialsProvider(credMap);
+        }
+    }
+
+    static class Entry {
+
+        final AuthScope authScope;
+        final Credentials credentials;
+
+        Entry(final AuthScope authScope, final Credentials credentials) {
+            this.authScope = authScope;
+            this.credentials = credentials;
+        }
+
+    }
+
+}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/FixedCredentialsProvider.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/FixedCredentialsProvider.java
new file mode 100644
index 0000000..e42d141
--- /dev/null
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/FixedCredentialsProvider.java
@@ -0,0 +1,57 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.hc.client5.http.impl.auth;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.hc.client5.http.auth.AuthScope;
+import org.apache.hc.client5.http.auth.Credentials;
+import org.apache.hc.client5.http.auth.CredentialsProvider;
+import org.apache.hc.core5.http.protocol.HttpContext;
+
+final class FixedCredentialsProvider implements CredentialsProvider {
+
+    private final Map<AuthScope, Credentials> credMap;
+
+    public FixedCredentialsProvider(final Map<AuthScope, Credentials> credMap) {
+        super();
+        this.credMap = Collections.unmodifiableMap(new HashMap<>(credMap));
+    }
+
+    @Override
+    public Credentials getCredentials(final AuthScope authScope, final HttpContext context) {
+        return CredentialsMatcher.matchCredentials(this.credMap, authScope);
+    }
+
+    @Override
+    public String toString() {
+        return credMap.keySet().toString();
+    }
+
+}
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/SingleCredentialsProvider.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/SingleCredentialsProvider.java
new file mode 100644
index 0000000..c17fd90
--- /dev/null
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/auth/SingleCredentialsProvider.java
@@ -0,0 +1,61 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.hc.client5.http.impl.auth;
+
+import org.apache.hc.client5.http.auth.AuthScope;
+import org.apache.hc.client5.http.auth.Credentials;
+import org.apache.hc.client5.http.auth.CredentialsProvider;
+import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.apache.hc.core5.util.Args;
+
+final class SingleCredentialsProvider implements CredentialsProvider {
+
+    private final AuthScope authScope;
+    private final Credentials credentials;
+
+    public SingleCredentialsProvider(final AuthScope authScope, final Credentials credentials) {
+        super();
+        this.authScope = Args.notNull(authScope, "Auth scope");
+        this.credentials = credentials;
+    }
+
+    public SingleCredentialsProvider(final AuthScope authScope, final String username, final char[] password) {
+        this(authScope, new UsernamePasswordCredentials(username, password));
+    }
+
+    @Override
+    public Credentials getCredentials(final AuthScope authScope, final HttpContext context) {
+        return this.authScope.match(authScope) >= 0 ? credentials : null;
+    }
+
+    @Override
+    public String toString() {
+        return authScope.toString();
+    }
+
+}
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientAuthentication.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientAuthentication.java
index d917e2a..ec40910 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientAuthentication.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/AsyncClientAuthentication.java
@@ -33,12 +33,11 @@ import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
 import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
 import org.apache.hc.client5.http.async.methods.SimpleRequestProducer;
 import org.apache.hc.client5.http.async.methods.SimpleResponseConsumer;
-import org.apache.hc.client5.http.auth.AuthScope;
-import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
 import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
 import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
-import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
+import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
 import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.HttpHost;
 import org.apache.hc.core5.http.message.StatusLine;
 import org.apache.hc.core5.io.CloseMode;
 
@@ -49,12 +48,10 @@ import org.apache.hc.core5.io.CloseMode;
 public class AsyncClientAuthentication {
 
     public static void main(final String[] args) throws Exception {
-        final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
-        credsProvider.setCredentials(
-                new AuthScope("httpbin.org", 80),
-                new UsernamePasswordCredentials("user", "passwd".toCharArray()));
         final CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom()
-                .setDefaultCredentialsProvider(credsProvider)
+                .setDefaultCredentialsProvider(CredentialsProviderBuilder.create()
+                        .add(new HttpHost("httpbin.org", 80), "user", "passwd".toCharArray())
+                        .build())
                 .build();
         httpclient.start();
 
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientAuthentication.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientAuthentication.java
index aa75fef..f8c681c 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientAuthentication.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientAuthentication.java
@@ -26,13 +26,12 @@
  */
 package org.apache.hc.client5.http.examples;
 
-import org.apache.hc.client5.http.auth.AuthScope;
-import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
 import org.apache.hc.client5.http.classic.methods.HttpGet;
-import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
+import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
 import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
 import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
 import org.apache.hc.client5.http.impl.classic.HttpClients;
+import org.apache.hc.core5.http.HttpHost;
 import org.apache.hc.core5.http.io.entity.EntityUtils;
 
 /**
@@ -42,12 +41,10 @@ import org.apache.hc.core5.http.io.entity.EntityUtils;
 public class ClientAuthentication {
 
     public static void main(final String[] args) throws Exception {
-        final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
-        credsProvider.setCredentials(
-                new AuthScope("httpbin.org", 80),
-                new UsernamePasswordCredentials("user", "passwd".toCharArray()));
         try (final CloseableHttpClient httpclient = HttpClients.custom()
-                .setDefaultCredentialsProvider(credsProvider)
+                .setDefaultCredentialsProvider(CredentialsProviderBuilder.create()
+                        .add(new HttpHost("httpbin.org", 80), "user", "passwd".toCharArray())
+                        .build())
                 .build()) {
             final HttpGet httpget = new HttpGet("http://httpbin.org/basic-auth/user/passwd");
 
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientConfiguration.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientConfiguration.java
index 92a494e..42d827e 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientConfiguration.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientConfiguration.java
@@ -47,7 +47,7 @@ import org.apache.hc.client5.http.config.RequestConfig;
 import org.apache.hc.client5.http.cookie.BasicCookieStore;
 import org.apache.hc.client5.http.cookie.CookieStore;
 import org.apache.hc.client5.http.cookie.StandardCookieSpec;
-import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
+import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
 import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
 import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
 import org.apache.hc.client5.http.impl.classic.HttpClients;
@@ -194,7 +194,8 @@ public class ClientConfiguration {
         // Use custom cookie store if necessary.
         final CookieStore cookieStore = new BasicCookieStore();
         // Use custom credentials provider if necessary.
-        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .build();
         // Create global request configuration
         final RequestConfig defaultRequestConfig = RequestConfig.custom()
             .setCookieSpec(StandardCookieSpec.STRICT)
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientPreemptiveDigestAuthentication.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientPreemptiveDigestAuthentication.java
index 08af92d..0dbc463 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientPreemptiveDigestAuthentication.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientPreemptiveDigestAuthentication.java
@@ -28,10 +28,9 @@ package org.apache.hc.client5.http.examples;
 
 import org.apache.hc.client5.http.auth.AuthExchange;
 import org.apache.hc.client5.http.auth.AuthScheme;
-import org.apache.hc.client5.http.auth.AuthScope;
 import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
 import org.apache.hc.client5.http.classic.methods.HttpGet;
-import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
+import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
 import org.apache.hc.client5.http.impl.auth.DigestScheme;
 import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
 import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
@@ -54,11 +53,9 @@ public class ClientPreemptiveDigestAuthentication {
             final HttpHost target = new HttpHost("http", "httpbin.org", 80);
 
             final HttpClientContext localContext = HttpClientContext.create();
-            final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-            credentialsProvider.setCredentials(
-                    new AuthScope(target),
-                    new UsernamePasswordCredentials("user", "passwd".toCharArray()));
-            localContext.setCredentialsProvider(credentialsProvider);
+            localContext.setCredentialsProvider(CredentialsProviderBuilder.create()
+                    .add(target, new UsernamePasswordCredentials("user", "passwd".toCharArray()))
+                    .build());
 
             final HttpGet httpget = new HttpGet("http://httpbin.org/digest-auth/auth/user/passwd");
 
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientProxyAuthentication.java b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientProxyAuthentication.java
index 52bf5bf..d237029 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientProxyAuthentication.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/examples/ClientProxyAuthentication.java
@@ -27,10 +27,10 @@
 package org.apache.hc.client5.http.examples;
 
 import org.apache.hc.client5.http.auth.AuthScope;
-import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
+import org.apache.hc.client5.http.auth.CredentialsProvider;
 import org.apache.hc.client5.http.classic.methods.HttpGet;
 import org.apache.hc.client5.http.config.RequestConfig;
-import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
+import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
 import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
 import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
 import org.apache.hc.client5.http.impl.classic.HttpClients;
@@ -44,18 +44,16 @@ import org.apache.hc.core5.http.io.entity.EntityUtils;
 public class ClientProxyAuthentication {
 
     public static void main(final String[] args) throws Exception {
-        final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
-        credsProvider.setCredentials(
-                new AuthScope("localhost", 8888),
-                new UsernamePasswordCredentials("squid", "squid".toCharArray()));
-        credsProvider.setCredentials(
-                new AuthScope("httpbin.org", 80),
-                new UsernamePasswordCredentials("user", "passwd".toCharArray()));
+        final CredentialsProvider credsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope("localhost", 8888), "squid", "squid".toCharArray())
+                .add(new AuthScope("httpbin.org", 80), "user", "passwd".toCharArray())
+                .build();
         final HttpHost target = new HttpHost("http", "httpbin.org", 80);
         final HttpHost proxy = new HttpHost("localhost", 8888);
         try (final CloseableHttpClient httpclient = HttpClients.custom()
                 .setProxy(proxy)
-                .setDefaultCredentialsProvider(credsProvider).build()) {
+                .setDefaultCredentialsProvider(credsProvider)
+                .build()) {
 
             final RequestConfig config = RequestConfig.custom()
                 .build();
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestAuthenticationStrategy.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestAuthenticationStrategy.java
index 3fff244..508fa14 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestAuthenticationStrategy.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/TestAuthenticationStrategy.java
@@ -38,11 +38,10 @@ import org.apache.hc.client5.http.auth.AuthSchemeFactory;
 import org.apache.hc.client5.http.auth.AuthScope;
 import org.apache.hc.client5.http.auth.ChallengeType;
 import org.apache.hc.client5.http.auth.StandardAuthScheme;
-import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
 import org.apache.hc.client5.http.config.RequestConfig;
-import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
 import org.apache.hc.client5.http.impl.auth.BasicScheme;
 import org.apache.hc.client5.http.impl.auth.BasicSchemeFactory;
+import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
 import org.apache.hc.client5.http.impl.auth.DigestScheme;
 import org.apache.hc.client5.http.impl.auth.DigestSchemeFactory;
 import org.apache.hc.client5.http.protocol.HttpClientContext;
@@ -103,11 +102,9 @@ public class TestAuthenticationStrategy {
             .register(StandardAuthScheme.BASIC, BasicSchemeFactory.INSTANCE)
             .register(StandardAuthScheme.DIGEST, DigestSchemeFactory.INSTANCE).build();
         context.setAuthSchemeRegistry(authSchemeRegistry);
-
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        credentialsProvider.setCredentials(new AuthScope("somehost", 80),
-                new UsernamePasswordCredentials("user", "pwd".toCharArray()));
-        context.setCredentialsProvider(credentialsProvider);
+        context.setCredentialsProvider(CredentialsProviderBuilder.create()
+                .add(new AuthScope("somehost", 80), "user", "pwd".toCharArray())
+                .build());
 
         final List<AuthScheme> authSchemes = authStrategy.select(ChallengeType.TARGET, challenges, context);
         Assert.assertNotNull(authSchemes);
@@ -139,10 +136,9 @@ public class TestAuthenticationStrategy {
         context.setAuthSchemeRegistry(authSchemeRegistry);
         context.setRequestConfig(config);
 
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        credentialsProvider.setCredentials(new AuthScope("somehost", 80),
-                new UsernamePasswordCredentials("user", "pwd".toCharArray()));
-        context.setCredentialsProvider(credentialsProvider);
+        context.setCredentialsProvider(CredentialsProviderBuilder.create()
+                .add(new AuthScope("somehost", 80), "user", "pwd".toCharArray())
+                .build());
 
         final List<AuthScheme> authSchemes = authStrategy.select(ChallengeType.TARGET, challenges, context);
         Assert.assertNotNull(authSchemes);
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestBasicScheme.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestBasicScheme.java
index de2f4ce..675f0c8 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestBasicScheme.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestBasicScheme.java
@@ -39,6 +39,7 @@ import org.apache.hc.client5.http.auth.AuthScheme;
 import org.apache.hc.client5.http.auth.AuthScope;
 import org.apache.hc.client5.http.auth.AuthenticationException;
 import org.apache.hc.client5.http.auth.ChallengeType;
+import org.apache.hc.client5.http.auth.CredentialsProvider;
 import org.apache.hc.client5.http.auth.StandardAuthScheme;
 import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
 import org.apache.hc.core5.http.HttpHost;
@@ -81,10 +82,9 @@ public class TestBasicScheme {
         authscheme.processChallenge(authChallenge, null);
 
         final HttpHost host  = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, "test", null);
-        final UsernamePasswordCredentials creds = new UsernamePasswordCredentials("testuser", "testpass".toCharArray());
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, "test", null), "testuser", "testpass".toCharArray())
+                .build();
 
         final HttpRequest request = new BasicHttpRequest("GET", "/");
         Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
@@ -142,10 +142,9 @@ public class TestBasicScheme {
         authscheme.processChallenge(authChallenge, null);
 
         final HttpHost host  = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, "test", null);
-        final UsernamePasswordCredentials creds = new UsernamePasswordCredentials("test", TEST_UTF8_PASSWORD.toCharArray());
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, "test", null), "test", TEST_UTF8_PASSWORD.toCharArray())
+                .build();
 
         final HttpRequest request = new BasicHttpRequest("GET", "/");
         Assert.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestBasicCredentialsProvider.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestCredentialsProviders.java
similarity index 82%
rename from httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestBasicCredentialsProvider.java
rename to httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestCredentialsProviders.java
index 1e4e3e3..b6c39a1 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestBasicCredentialsProvider.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestCredentialsProviders.java
@@ -26,18 +26,19 @@
  */
 package org.apache.hc.client5.http.impl.auth;
 
-import org.apache.hc.client5.http.auth.StandardAuthScheme;
 import org.apache.hc.client5.http.auth.AuthScope;
 import org.apache.hc.client5.http.auth.Credentials;
+import org.apache.hc.client5.http.auth.CredentialsProvider;
+import org.apache.hc.client5.http.auth.StandardAuthScheme;
 import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
 import org.apache.hc.core5.http.HttpHost;
 import org.junit.Assert;
 import org.junit.Test;
 
 /**
- * Simple tests for {@link BasicCredentialsProvider}.
+ * Tests for {@link org.apache.hc.client5.http.auth.CredentialsProvider} implementations.
  */
-public class TestBasicCredentialsProvider {
+public class TestCredentialsProviders {
 
     public final static Credentials CREDS1 =
         new UsernamePasswordCredentials("user1", "pass1".toCharArray());
@@ -155,4 +156,21 @@ public class TestBasicCredentialsProvider {
         Assert.assertEquals(expected, got);
     }
 
+    @Test
+    public void testSingleCredentialsProvider() {
+        final Credentials creds1 = new UsernamePasswordCredentials("name1", "pass1".toCharArray());
+        final CredentialsProvider credentialsProvider1 = new SingleCredentialsProvider(new AuthScope(null, null, -1, null, null), creds1);
+
+        Assert.assertEquals(creds1, credentialsProvider1.getCredentials(new AuthScope(null, null, -1, null, null), null));
+        Assert.assertEquals(creds1, credentialsProvider1.getCredentials(new AuthScope("http", "someotherhost", 80, "somerealm", StandardAuthScheme.BASIC), null));
+
+        final CredentialsProvider credentialsProvider2 = new SingleCredentialsProvider(new AuthScope(null, "somehost", 80, null, null), creds1);
+
+        Assert.assertEquals(creds1, credentialsProvider2.getCredentials(new AuthScope(null, null, -1, null, null), null));
+        Assert.assertEquals(creds1, credentialsProvider2.getCredentials(new AuthScope(null, "somehost", 80, null, null), null));
+        Assert.assertEquals(creds1, credentialsProvider2.getCredentials(new AuthScope("http", "somehost", 80, "somerealm", StandardAuthScheme.BASIC), null));
+        Assert.assertNull(credentialsProvider2.getCredentials(new AuthScope(null, "someotherhost", 80, null, null), null));
+        Assert.assertNull(credentialsProvider2.getCredentials(new AuthScope(null, "somehost", 8080, null, null), null));
+    }
+
 }
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestDigestScheme.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestDigestScheme.java
index 7a5e430..31bfc63 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestDigestScheme.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestDigestScheme.java
@@ -42,10 +42,9 @@ import org.apache.hc.client5.http.auth.AuthScheme;
 import org.apache.hc.client5.http.auth.AuthScope;
 import org.apache.hc.client5.http.auth.AuthenticationException;
 import org.apache.hc.client5.http.auth.ChallengeType;
-import org.apache.hc.client5.http.auth.Credentials;
+import org.apache.hc.client5.http.auth.CredentialsProvider;
 import org.apache.hc.client5.http.auth.MalformedChallengeException;
 import org.apache.hc.client5.http.auth.StandardAuthScheme;
-import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
 import org.apache.hc.core5.http.ClassicHttpRequest;
 import org.apache.hc.core5.http.ContentType;
 import org.apache.hc.core5.http.HeaderElement;
@@ -96,10 +95,9 @@ public class TestDigestScheme {
     public void testDigestAuthenticationWithDefaultCreds() throws Exception {
         final HttpRequest request = new BasicHttpRequest("Simple", "/");
         final HttpHost host = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, "realm1", null);
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials creds = new UsernamePasswordCredentials("username","password".toCharArray());
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, "realm1", null), "username", "password".toCharArray())
+                .build();
 
         final String challenge = StandardAuthScheme.DIGEST + " realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
         final AuthChallenge authChallenge = parse(challenge);
@@ -123,10 +121,9 @@ public class TestDigestScheme {
     public void testDigestAuthentication() throws Exception {
         final HttpRequest request = new BasicHttpRequest("Simple", "/");
         final HttpHost host = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, "realm1", null);
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials creds = new UsernamePasswordCredentials("username","password".toCharArray());
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, "realm1", null), "username", "password".toCharArray())
+                .build();
 
         final String challenge = StandardAuthScheme.DIGEST + " realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
         final AuthChallenge authChallenge = parse(challenge);
@@ -147,10 +144,9 @@ public class TestDigestScheme {
     @Test
     public void testDigestAuthenticationInvalidInput() throws Exception {
         final HttpHost host = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, "realm1", null);
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials creds = new UsernamePasswordCredentials("username","password".toCharArray());
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, "realm1", null), "username", "password".toCharArray())
+                .build();
 
         final String challenge = StandardAuthScheme.DIGEST + " realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
         final AuthChallenge authChallenge = parse(challenge);
@@ -169,10 +165,9 @@ public class TestDigestScheme {
     public void testDigestAuthenticationWithSHA() throws Exception {
         final HttpRequest request = new BasicHttpRequest("Simple", "/");
         final HttpHost host = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, "realm1", null);
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials creds = new UsernamePasswordCredentials("username","password".toCharArray());
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, "realm1", null), "username", "password".toCharArray())
+                .build();
 
         final String challenge = StandardAuthScheme.DIGEST + " realm=\"realm1\", " +
                 "nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
@@ -196,10 +191,9 @@ public class TestDigestScheme {
     public void testDigestAuthenticationWithQueryStringInDigestURI() throws Exception {
         final HttpRequest request = new BasicHttpRequest("Simple", "/?param=value");
         final HttpHost host = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, "realm1", null);
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials creds = new UsernamePasswordCredentials("username","password".toCharArray());
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, "realm1", null), "username", "password".toCharArray())
+                .build();
 
         final String challenge = StandardAuthScheme.DIGEST + " realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
         final AuthChallenge authChallenge = parse(challenge);
@@ -221,10 +215,9 @@ public class TestDigestScheme {
     public void testDigestAuthenticationNoRealm() throws Exception {
         final HttpRequest request = new BasicHttpRequest("Simple", "/");
         final HttpHost host = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, "realm1", null);
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials creds = new UsernamePasswordCredentials("username","password".toCharArray());
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, "realm1", null), "username", "password".toCharArray())
+                .build();
 
         final String challenge = StandardAuthScheme.DIGEST + " no-realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
         final AuthChallenge authChallenge = parse(challenge);
@@ -240,10 +233,9 @@ public class TestDigestScheme {
     public void testDigestAuthenticationNoNonce() throws Exception {
         final HttpRequest request = new BasicHttpRequest("Simple", "/");
         final HttpHost host = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, "realm1", null);
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials creds = new UsernamePasswordCredentials("username","password".toCharArray());
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, "realm1", null), "username", "password".toCharArray())
+                .build();
 
         final String challenge = StandardAuthScheme.DIGEST + " realm=\"realm1\", no-nonce=\"f2a3f18799759d4f1a1c068b92b573cb\"";
         final AuthChallenge authChallenge = parse(challenge);
@@ -269,10 +261,9 @@ public class TestDigestScheme {
 
         final HttpRequest request = new BasicHttpRequest("Simple", "/");
         final HttpHost host = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, realm, null);
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials creds = new UsernamePasswordCredentials(username, password.toCharArray());
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, realm, null), username, password.toCharArray())
+                .build();
 
         final String challenge=StandardAuthScheme.DIGEST + " realm=\"" + realm + "\", "
             + "nonce=\"" + nonce + "\", "
@@ -320,10 +311,9 @@ public class TestDigestScheme {
 
         final HttpRequest request = new BasicHttpRequest("Simple", "/");
         final HttpHost host = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, realm, null);
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials creds = new UsernamePasswordCredentials(username, password.toCharArray());
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, realm, null), username, password.toCharArray())
+                .build();
 
         final String challenge=StandardAuthScheme.DIGEST + " realm=\"" + realm + "\", "
             + "nonce=\"" + nonce + "\", "
@@ -365,10 +355,9 @@ public class TestDigestScheme {
 
         final HttpRequest request = new BasicHttpRequest("Simple", "/");
         final HttpHost host = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, realm, null);
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials creds = new UsernamePasswordCredentials(username, password.toCharArray());
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, realm, null), username, password.toCharArray())
+                .build();
 
         final String challenge=StandardAuthScheme.DIGEST + " realm=\"" + realm + "\", "
             + "nonce=\"" + nonce + "\", "
@@ -401,10 +390,9 @@ public class TestDigestScheme {
 
         final HttpRequest request = new BasicHttpRequest("Simple", "/");
         final HttpHost host = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, realm, null);
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials creds = new UsernamePasswordCredentials(username, password.toCharArray());
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, realm, null), username, password.toCharArray())
+                .build();
 
         final String challenge=StandardAuthScheme.DIGEST + " realm=\"" + realm + "\", "
             + "nonce=\"" + nonce + "\", "
@@ -452,10 +440,9 @@ public class TestDigestScheme {
     public void testDigestNouceCount() throws Exception {
         final HttpRequest request = new BasicHttpRequest("GET", "/");
         final HttpHost host = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, "realm1", null);
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials creds = new UsernamePasswordCredentials("username","password".toCharArray());
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, "realm1", null), "username", "password".toCharArray())
+                .build();
 
         final String challenge1 = StandardAuthScheme.DIGEST + " realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", qop=auth";
         final AuthChallenge authChallenge1 = parse(challenge1);
@@ -496,11 +483,10 @@ public class TestDigestScheme {
     @Test
     public void testDigestMD5SessA1AndCnonceConsistency() throws Exception {
         final HttpHost host = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, "subnet.domain.com", null);
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
         final HttpRequest request = new BasicHttpRequest("GET", "/");
-        final Credentials creds = new UsernamePasswordCredentials("username","password".toCharArray());
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, "subnet.domain.com", null), "username", "password".toCharArray())
+                .build();
 
         final String challenge1 = StandardAuthScheme.DIGEST + " qop=\"auth\", algorithm=MD5-sess, nonce=\"1234567890abcdef\", " +
                 "charset=utf-8, realm=\"subnet.domain.com\"";
@@ -579,10 +565,9 @@ public class TestDigestScheme {
         final ClassicHttpRequest request = new BasicClassicHttpRequest("Post", "/");
         request.setEntity(new StringEntity("abc\u00e4\u00f6\u00fcabc", StandardCharsets.ISO_8859_1));
         final HttpHost host = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, "realm1", null);
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials creds = new UsernamePasswordCredentials("username","password".toCharArray());
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, "realm1", null), "username", "password".toCharArray())
+                .build();
 
         final String challenge = StandardAuthScheme.DIGEST + " realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
                 "qop=\"auth,auth-int\"";
@@ -606,10 +591,9 @@ public class TestDigestScheme {
     public void testDigestAuthenticationQopAuthIntNullEntity() throws Exception {
         final HttpRequest request = new BasicHttpRequest("Post", "/");
         final HttpHost host = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, "realm1", null);
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials creds = new UsernamePasswordCredentials("username","password".toCharArray());
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, "realm1", null), "username", "password".toCharArray())
+                .build();
 
         final String challenge = StandardAuthScheme.DIGEST + " realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
                 "qop=\"auth-int\"";
@@ -634,10 +618,9 @@ public class TestDigestScheme {
         final ClassicHttpRequest request = new BasicClassicHttpRequest("Post", "/");
         request.setEntity(new InputStreamEntity(new ByteArrayInputStream(new byte[] {'a'}), -1, ContentType.DEFAULT_TEXT));
         final HttpHost host = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, "realm1", null);
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials creds = new UsernamePasswordCredentials("username","password".toCharArray());
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, "realm1", null), "username", "password".toCharArray())
+                .build();
 
         final String challenge = StandardAuthScheme.DIGEST + " realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
                 "qop=\"auth,auth-int\"";
@@ -661,10 +644,9 @@ public class TestDigestScheme {
     public void testParameterCaseSensitivity() throws Exception {
         final HttpRequest request = new BasicHttpRequest("GET", "/");
         final HttpHost host = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, "-", null);
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials creds = new UsernamePasswordCredentials("username","password".toCharArray());
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, "-", null), "username", "password".toCharArray())
+                .build();
 
         final String challenge = StandardAuthScheme.DIGEST + " Realm=\"-\", " +
                 "nonce=\"YjYuNGYyYmJhMzUuY2I5ZDhlZDE5M2ZlZDM 1Mjk3NGJkNTIyYjgyNTcwMjQ=\", " +
@@ -683,10 +665,9 @@ public class TestDigestScheme {
         final ClassicHttpRequest request = new BasicClassicHttpRequest("Post", "/");
         request.setEntity(new InputStreamEntity(new ByteArrayInputStream(new byte[] {'a'}), -1, ContentType.DEFAULT_TEXT));
         final HttpHost host = new HttpHost("somehost", 80);
-        final AuthScope authScope = new AuthScope(host, "realm1", null);
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        final Credentials creds = new UsernamePasswordCredentials("username","password".toCharArray());
-        credentialsProvider.setCredentials(authScope, creds);
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(host, "realm1", null), "username", "password".toCharArray())
+                .build();
 
         final String challenge = StandardAuthScheme.DIGEST + " realm=\"realm1\", nonce=\"f2a3f18799759d4f1a1c068b92b573cb\", " +
                 "qop=\"auth-int\"";
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestRequestAuthCache.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestRequestAuthCache.java
index 88eb72e..d6959c1 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestRequestAuthCache.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/auth/TestRequestAuthCache.java
@@ -31,6 +31,7 @@ import org.apache.hc.client5.http.auth.AuthCache;
 import org.apache.hc.client5.http.auth.AuthExchange;
 import org.apache.hc.client5.http.auth.AuthScope;
 import org.apache.hc.client5.http.auth.Credentials;
+import org.apache.hc.client5.http.auth.CredentialsProvider;
 import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
 import org.apache.hc.client5.http.protocol.HttpClientContext;
 import org.apache.hc.client5.http.protocol.RequestAuthCache;
@@ -52,14 +53,13 @@ public class TestRequestAuthCache {
     private AuthScope authscope2;
     private BasicScheme authscheme1;
     private BasicScheme authscheme2;
-    private BasicCredentialsProvider credProvider;
+    private CredentialsProvider credProvider;
 
     @Before
     public void setUp() {
         this.target = new HttpHost("localhost", 80);
         this.proxy = new HttpHost("localhost", 8080);
 
-        this.credProvider = new BasicCredentialsProvider();
         this.creds1 = new UsernamePasswordCredentials("user1", "secret1".toCharArray());
         this.creds2 = new UsernamePasswordCredentials("user2", "secret2".toCharArray());
         this.authscope1 = new AuthScope(this.target);
@@ -67,8 +67,10 @@ public class TestRequestAuthCache {
         this.authscheme1 = new BasicScheme();
         this.authscheme2 = new BasicScheme();
 
-        this.credProvider.setCredentials(this.authscope1, this.creds1);
-        this.credProvider.setCredentials(this.authscope2, this.creds2);
+        this.credProvider = CredentialsProviderBuilder.create()
+                .add(this.authscope1, this.creds1)
+                .add(this.authscope2, this.creds2)
+                .build();
     }
 
     @Test
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestConnectExec.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestConnectExec.java
index cae10cf..730fbd1 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestConnectExec.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestConnectExec.java
@@ -35,15 +35,15 @@ import org.apache.hc.client5.http.HttpRoute;
 import org.apache.hc.client5.http.RouteInfo;
 import org.apache.hc.client5.http.auth.AuthScope;
 import org.apache.hc.client5.http.auth.ChallengeType;
+import org.apache.hc.client5.http.auth.CredentialsProvider;
 import org.apache.hc.client5.http.auth.StandardAuthScheme;
-import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
 import org.apache.hc.client5.http.classic.ExecChain;
 import org.apache.hc.client5.http.classic.ExecRuntime;
 import org.apache.hc.client5.http.classic.methods.HttpGet;
 import org.apache.hc.client5.http.entity.EntityBuilder;
 import org.apache.hc.client5.http.impl.TunnelRefusedException;
-import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
 import org.apache.hc.client5.http.impl.auth.BasicScheme;
+import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
 import org.apache.hc.client5.http.protocol.HttpClientContext;
 import org.apache.hc.core5.http.ClassicHttpRequest;
 import org.apache.hc.core5.http.ClassicHttpResponse;
@@ -238,9 +238,9 @@ public class TestConnectExec {
                 .build());
         final ClassicHttpResponse response2 = new BasicClassicHttpResponse(200, "OK");
 
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        credentialsProvider.setCredentials(new AuthScope(proxy), new UsernamePasswordCredentials("user", "pass".toCharArray()));
-        context.setCredentialsProvider(credentialsProvider);
+        context.setCredentialsProvider(CredentialsProviderBuilder.create()
+                .add(new AuthScope(proxy), "user", "pass".toCharArray())
+                .build());
 
         final ConnectionState connectionState = new ConnectionState();
         Mockito.doAnswer(connectionState.connectAnswer()).when(execRuntime).connectEndpoint(Mockito.any());
@@ -279,8 +279,9 @@ public class TestConnectExec {
                 .build());
         final ClassicHttpResponse response2 = new BasicClassicHttpResponse(200, "OK");
 
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        credentialsProvider.setCredentials(new AuthScope(proxy), new UsernamePasswordCredentials("user", "pass".toCharArray()));
+        final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
+                .add(new AuthScope(proxy), "user", "pass".toCharArray())
+                .build();
         context.setCredentialsProvider(credentialsProvider);
 
         final ConnectionState connectionState = new ConnectionState();
diff --git a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestProtocolExec.java b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestProtocolExec.java
index 9f0fb6f..3e687cd 100644
--- a/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestProtocolExec.java
+++ b/httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestProtocolExec.java
@@ -41,7 +41,6 @@ import org.apache.hc.client5.http.auth.ChallengeType;
 import org.apache.hc.client5.http.auth.Credentials;
 import org.apache.hc.client5.http.auth.CredentialsProvider;
 import org.apache.hc.client5.http.auth.StandardAuthScheme;
-import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
 import org.apache.hc.client5.http.classic.ExecChain;
 import org.apache.hc.client5.http.classic.ExecRuntime;
 import org.apache.hc.client5.http.classic.methods.HttpGet;
@@ -49,6 +48,7 @@ import org.apache.hc.client5.http.classic.methods.HttpPost;
 import org.apache.hc.client5.http.entity.EntityBuilder;
 import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
 import org.apache.hc.client5.http.impl.auth.BasicScheme;
+import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
 import org.apache.hc.client5.http.impl.auth.NTLMScheme;
 import org.apache.hc.client5.http.protocol.HttpClientContext;
 import org.apache.hc.core5.http.ClassicHttpRequest;
@@ -211,9 +211,9 @@ public class TestProtocolExec {
                 .setStream(inStream2)
                 .build());
 
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        credentialsProvider.setCredentials(new AuthScope(target), new UsernamePasswordCredentials("user", "pass".toCharArray()));
-        context.setCredentialsProvider(credentialsProvider);
+        context.setCredentialsProvider(CredentialsProviderBuilder.create()
+                .add(new AuthScope(target), "user", "pass".toCharArray())
+                .build());
 
         Mockito.when(chain.proceed(
                 Mockito.same(request),
@@ -257,9 +257,9 @@ public class TestProtocolExec {
         authExchange.select(new NTLMScheme());
         context.setAuthExchange(target, authExchange);
 
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        credentialsProvider.setCredentials(new AuthScope(target), new UsernamePasswordCredentials("user", "pass".toCharArray()));
-        context.setCredentialsProvider(credentialsProvider);
+        context.setCredentialsProvider(CredentialsProviderBuilder.create()
+                .add(new AuthScope(target), "user", "pass".toCharArray())
+                .build());
 
         Mockito.when(chain.proceed(
                 Mockito.same(request),
@@ -297,9 +297,9 @@ public class TestProtocolExec {
                 .setStream(inStream1)
                 .build());
 
-        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
-        credentialsProvider.setCredentials(new AuthScope(target), new UsernamePasswordCredentials("user", "pass".toCharArray()));
-        context.setCredentialsProvider(credentialsProvider);
+        context.setCredentialsProvider(CredentialsProviderBuilder.create()
+                .add(new AuthScope(target), "user", "pass".toCharArray())
+                .build());
 
         Mockito.when(chain.proceed(
                 Mockito.same(request),