1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.hc.client5.testing.sync;
28
29 import java.io.ByteArrayInputStream;
30 import java.io.IOException;
31 import java.net.InetSocketAddress;
32 import java.nio.charset.StandardCharsets;
33 import java.util.Arrays;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.concurrent.atomic.AtomicLong;
37
38 import org.apache.hc.client5.http.auth.AuthCache;
39 import org.apache.hc.client5.http.auth.AuthChallenge;
40 import org.apache.hc.client5.http.auth.AuthScheme;
41 import org.apache.hc.client5.http.auth.AuthSchemeFactory;
42 import org.apache.hc.client5.http.auth.StandardAuthScheme;
43 import org.apache.hc.client5.http.auth.AuthScope;
44 import org.apache.hc.client5.http.auth.ChallengeType;
45 import org.apache.hc.client5.http.auth.Credentials;
46 import org.apache.hc.client5.http.auth.CredentialsProvider;
47 import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
48 import org.apache.hc.client5.http.classic.methods.HttpGet;
49 import org.apache.hc.client5.http.classic.methods.HttpPost;
50 import org.apache.hc.client5.http.classic.methods.HttpPut;
51 import org.apache.hc.client5.http.config.RequestConfig;
52 import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy;
53 import org.apache.hc.client5.http.impl.auth.BasicAuthCache;
54 import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
55 import org.apache.hc.client5.http.impl.auth.BasicScheme;
56 import org.apache.hc.client5.http.impl.auth.BasicSchemeFactory;
57 import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
58 import org.apache.hc.client5.http.protocol.HttpClientContext;
59 import org.apache.hc.client5.testing.BasicTestAuthenticator;
60 import org.apache.hc.client5.testing.auth.Authenticator;
61 import org.apache.hc.client5.testing.classic.AuthenticatingDecorator;
62 import org.apache.hc.client5.testing.classic.EchoHandler;
63 import org.apache.hc.core5.function.Decorator;
64 import org.apache.hc.core5.http.ClassicHttpRequest;
65 import org.apache.hc.core5.http.ClassicHttpResponse;
66 import org.apache.hc.core5.http.EndpointDetails;
67 import org.apache.hc.core5.http.HeaderElements;
68 import org.apache.hc.core5.http.HttpEntity;
69 import org.apache.hc.core5.http.HttpException;
70 import org.apache.hc.core5.http.HttpHeaders;
71 import org.apache.hc.core5.http.HttpHost;
72 import org.apache.hc.core5.http.HttpStatus;
73 import org.apache.hc.core5.http.config.Registry;
74 import org.apache.hc.core5.http.config.RegistryBuilder;
75 import org.apache.hc.core5.http.impl.HttpProcessors;
76 import org.apache.hc.core5.http.io.HttpRequestHandler;
77 import org.apache.hc.core5.http.io.HttpServerRequestHandler;
78 import org.apache.hc.core5.http.io.entity.EntityUtils;
79 import org.apache.hc.core5.http.io.entity.InputStreamEntity;
80 import org.apache.hc.core5.http.io.entity.StringEntity;
81 import org.apache.hc.core5.http.message.BasicHeader;
82 import org.apache.hc.core5.http.protocol.HttpContext;
83 import org.apache.hc.core5.http.protocol.HttpCoreContext;
84 import org.apache.hc.core5.net.URIAuthority;
85 import org.junit.Assert;
86 import org.junit.Test;
87
88
89
90
91 public class TestClientAuthentication extends LocalServerTestBase {
92
93 public HttpHost start(final Authenticator authenticator) throws IOException {
94 return super.start(null, new Decorator<HttpServerRequestHandler>() {
95
96 @Override
97 public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
98 return new AuthenticatingDecorator(requestHandler, authenticator);
99 }
100
101 });
102 }
103
104 @Override
105 public HttpHost start() throws IOException {
106 return start(new BasicTestAuthenticator("test:test", "test realm"));
107 }
108
109 static class TestCredentialsProvider implements CredentialsProvider {
110
111 private final Credentials creds;
112 private AuthScope authscope;
113
114 TestCredentialsProvider(final Credentials creds) {
115 super();
116 this.creds = creds;
117 }
118
119 @Override
120 public Credentials getCredentials(final AuthScope authscope, final HttpContext context) {
121 this.authscope = authscope;
122 return this.creds;
123 }
124
125 public AuthScope getAuthScope() {
126 return this.authscope;
127 }
128
129 }
130
131 @Test
132 public void testBasicAuthenticationNoCreds() throws Exception {
133 this.server.registerHandler("*", new EchoHandler());
134 final HttpHost target = start();
135
136 final HttpClientContext context = HttpClientContext.create();
137 final TestCredentialsProvider credsProvider = new TestCredentialsProvider(null);
138 context.setCredentialsProvider(credsProvider);
139 final HttpGet httpget = new HttpGet("/");
140
141 final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
142 final HttpEntity entity = response.getEntity();
143 Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
144 Assert.assertNotNull(entity);
145 EntityUtils.consume(entity);
146 final AuthScope authscope = credsProvider.getAuthScope();
147 Assert.assertNotNull(authscope);
148 Assert.assertEquals("test realm", authscope.getRealm());
149 }
150
151 @Test
152 public void testBasicAuthenticationFailure() throws Exception {
153 this.server.registerHandler("*", new EchoHandler());
154 final HttpHost target = start();
155
156 final HttpClientContext context = HttpClientContext.create();
157 final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
158 new UsernamePasswordCredentials("test", "all-wrong".toCharArray()));
159 context.setCredentialsProvider(credsProvider);
160 final HttpGet httpget = new HttpGet("/");
161
162 final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
163 final HttpEntity entity = response.getEntity();
164 Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
165 Assert.assertNotNull(entity);
166 EntityUtils.consume(entity);
167 final AuthScope authscope = credsProvider.getAuthScope();
168 Assert.assertNotNull(authscope);
169 Assert.assertEquals("test realm", authscope.getRealm());
170 }
171
172 @Test
173 public void testBasicAuthenticationSuccess() throws Exception {
174 this.server.registerHandler("*", new EchoHandler());
175 final HttpGet httpget = new HttpGet("/");
176 final HttpClientContext context = HttpClientContext.create();
177 final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
178 new UsernamePasswordCredentials("test", "test".toCharArray()));
179 context.setCredentialsProvider(credsProvider);
180
181 final HttpHost target = start();
182
183 final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
184 final HttpEntity entity = response.getEntity();
185 Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
186 Assert.assertNotNull(entity);
187 EntityUtils.consume(entity);
188 final AuthScope authscope = credsProvider.getAuthScope();
189 Assert.assertNotNull(authscope);
190 Assert.assertEquals("test realm", authscope.getRealm());
191 }
192
193 @Test
194 public void testBasicAuthenticationSuccessOnNonRepeatablePutExpectContinue() throws Exception {
195 this.server.registerHandler("*", new EchoHandler());
196 final HttpHost target = start();
197
198 final RequestConfig config = RequestConfig.custom()
199 .setExpectContinueEnabled(true)
200 .build();
201 final HttpPut httpput = new HttpPut("/");
202 httpput.setConfig(config);
203 httpput.setEntity(new InputStreamEntity(
204 new ByteArrayInputStream(
205 new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 } ),
206 -1, null));
207 final HttpClientContext context = HttpClientContext.create();
208 final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
209 new UsernamePasswordCredentials("test", "test".toCharArray()));
210 context.setCredentialsProvider(credsProvider);
211
212 final ClassicHttpResponse response = this.httpclient.execute(target, httpput, context);
213 final HttpEntity entity = response.getEntity();
214 Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
215 Assert.assertNotNull(entity);
216 }
217
218 @Test
219 public void testBasicAuthenticationFailureOnNonRepeatablePutDontExpectContinue() throws Exception {
220 this.server.registerHandler("*", new EchoHandler());
221 final HttpHost target = start();
222
223 final RequestConfig config = RequestConfig.custom().setExpectContinueEnabled(false).build();
224 final HttpPut httpput = new HttpPut("/");
225 httpput.setConfig(config);
226 httpput.setEntity(new InputStreamEntity(
227 new ByteArrayInputStream(
228 new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 } ),
229 -1, null));
230
231 final HttpClientContext context = HttpClientContext.create();
232 final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
233 new UsernamePasswordCredentials("test", "boom".toCharArray()));
234 context.setCredentialsProvider(credsProvider);
235
236 final CloseableHttpResponse response = this.httpclient.execute(target, httpput, context);
237 final HttpEntity entity = response.getEntity();
238 Assert.assertEquals(401, response.getCode());
239 Assert.assertNotNull(entity);
240 EntityUtils.consume(entity);
241 }
242
243 @Test
244 public void testBasicAuthenticationSuccessOnRepeatablePost() throws Exception {
245 this.server.registerHandler("*", new EchoHandler());
246 final HttpHost target = start();
247
248 final HttpPost httppost = new HttpPost("/");
249 httppost.setEntity(new StringEntity("some important stuff", StandardCharsets.US_ASCII));
250
251 final HttpClientContext context = HttpClientContext.create();
252 final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
253 new UsernamePasswordCredentials("test", "test".toCharArray()));
254 context.setCredentialsProvider(credsProvider);
255
256 final ClassicHttpResponse response = this.httpclient.execute(target, httppost, context);
257 final HttpEntity entity = response.getEntity();
258 Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
259 Assert.assertNotNull(entity);
260 EntityUtils.consume(entity);
261 final AuthScope authscope = credsProvider.getAuthScope();
262 Assert.assertNotNull(authscope);
263 Assert.assertEquals("test realm", authscope.getRealm());
264 }
265
266 @Test
267 public void testBasicAuthenticationFailureOnNonRepeatablePost() throws Exception {
268 this.server.registerHandler("*", new EchoHandler());
269 final HttpHost target = start();
270
271 final HttpPost httppost = new HttpPost("/");
272 httppost.setEntity(new InputStreamEntity(
273 new ByteArrayInputStream(
274 new byte[] { 0,1,2,3,4,5,6,7,8,9 }), -1, null));
275
276 final HttpClientContext context = HttpClientContext.create();
277 context.setRequestConfig(RequestConfig.custom()
278 .setExpectContinueEnabled(false)
279 .build());
280 final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
281 new UsernamePasswordCredentials("test", "test".toCharArray()));
282 context.setCredentialsProvider(credsProvider);
283
284 final CloseableHttpResponse response = this.httpclient.execute(target, httppost, context);
285 final HttpEntity entity = response.getEntity();
286 Assert.assertEquals(401, response.getCode());
287 Assert.assertNotNull(entity);
288 EntityUtils.consume(entity);
289 }
290
291 static class TestTargetAuthenticationStrategy extends DefaultAuthenticationStrategy {
292
293 private final AtomicLong count;
294
295 public TestTargetAuthenticationStrategy() {
296 super();
297 this.count = new AtomicLong();
298 }
299
300 @Override
301 public List<AuthScheme> select(
302 final ChallengeType challengeType,
303 final Map<String, AuthChallenge> challenges,
304 final HttpContext context) {
305 final List<AuthScheme> authSchemes = super.select(challengeType, challenges, context);
306 this.count.incrementAndGet();
307 return authSchemes;
308 }
309
310 public long getCount() {
311 return this.count.get();
312 }
313
314 }
315
316 @Test
317 public void testBasicAuthenticationCredentialsCaching() throws Exception {
318 this.server.registerHandler("*", new EchoHandler());
319 final TestTargetAuthenticationStrategy authStrategy = new TestTargetAuthenticationStrategy();
320 this.clientBuilder.setTargetAuthenticationStrategy(authStrategy);
321
322 final HttpHost target = start();
323
324 final HttpClientContext context = HttpClientContext.create();
325 final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
326 credsProvider.setCredentials(new AuthScope(null, null, -1, null ,null),
327 new UsernamePasswordCredentials("test", "test".toCharArray()));
328 context.setCredentialsProvider(credsProvider);
329
330 final HttpGet httpget = new HttpGet("/");
331
332 final ClassicHttpResponse response1 = this.httpclient.execute(target, httpget, context);
333 final HttpEntity entity1 = response1.getEntity();
334 Assert.assertEquals(HttpStatus.SC_OK, response1.getCode());
335 Assert.assertNotNull(entity1);
336 EntityUtils.consume(entity1);
337
338 final ClassicHttpResponse response2 = this.httpclient.execute(target, httpget, context);
339 final HttpEntity entity2 = response1.getEntity();
340 Assert.assertEquals(HttpStatus.SC_OK, response2.getCode());
341 Assert.assertNotNull(entity2);
342 EntityUtils.consume(entity2);
343
344 Assert.assertEquals(1, authStrategy.getCount());
345 }
346
347 @Test
348 public void testAuthenticationCredentialsCachingReauthenticationOnDifferentRealm() throws Exception {
349 this.server.registerHandler("*", new EchoHandler());
350 final HttpHost target = start(new Authenticator() {
351
352 @Override
353 public boolean authenticate(final URIAuthority authority, final String requestUri, final String credentials) {
354 if (requestUri.equals("/this")) {
355 return "test:this".equals(credentials);
356 } else if (requestUri.equals("/that")) {
357 return "test:that".equals(credentials);
358 } else {
359 return "test:test".equals(credentials);
360 }
361 }
362
363 @Override
364 public String getRealm(final URIAuthority authority, final String requestUri) {
365 if (requestUri.equals("/this")) {
366 return "this realm";
367 } else if (requestUri.equals("/that")) {
368 return "that realm";
369 } else {
370 return "test realm";
371 }
372 }
373
374 });
375
376 final TestTargetAuthenticationStrategy authStrategy = new TestTargetAuthenticationStrategy();
377 final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
378 credsProvider.setCredentials(new AuthScope(target, "this realm", null),
379 new UsernamePasswordCredentials("test", "this".toCharArray()));
380 credsProvider.setCredentials(new AuthScope(target, "that realm", null),
381 new UsernamePasswordCredentials("test", "that".toCharArray()));
382
383 this.clientBuilder.setTargetAuthenticationStrategy(authStrategy);
384 this.httpclient = this.clientBuilder.build();
385
386 final HttpClientContext context = HttpClientContext.create();
387 context.setCredentialsProvider(credsProvider);
388
389 final HttpGet httpget1 = new HttpGet("/this");
390
391 final ClassicHttpResponse response1 = this.httpclient.execute(target, httpget1, context);
392 final HttpEntity entity1 = response1.getEntity();
393 Assert.assertEquals(HttpStatus.SC_OK, response1.getCode());
394 Assert.assertNotNull(entity1);
395 EntityUtils.consume(entity1);
396
397 final HttpGet httpget2 = new HttpGet("/this");
398
399 final ClassicHttpResponse response2 = this.httpclient.execute(target, httpget2, context);
400 final HttpEntity entity2 = response1.getEntity();
401 Assert.assertEquals(HttpStatus.SC_OK, response2.getCode());
402 Assert.assertNotNull(entity2);
403 EntityUtils.consume(entity2);
404
405 final HttpGet httpget3 = new HttpGet("/that");
406
407 final ClassicHttpResponse response3 = this.httpclient.execute(target, httpget3, context);
408 final HttpEntity entity3 = response1.getEntity();
409 Assert.assertEquals(HttpStatus.SC_OK, response3.getCode());
410 Assert.assertNotNull(entity3);
411 EntityUtils.consume(entity3);
412
413 Assert.assertEquals(2, authStrategy.getCount());
414 }
415
416 @Test
417 public void testAuthenticationUserinfoInRequestSuccess() throws Exception {
418 this.server.registerHandler("*", new EchoHandler());
419 final HttpHost target = start();
420 final HttpGet httpget = new HttpGet("http://test:test@" + target.toHostString() + "/");
421
422 final HttpClientContext context = HttpClientContext.create();
423 final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
424 final HttpEntity entity = response.getEntity();
425 Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
426 Assert.assertNotNull(entity);
427 EntityUtils.consume(entity);
428 }
429
430 @Test
431 public void testAuthenticationUserinfoInRequestFailure() throws Exception {
432 this.server.registerHandler("*", new EchoHandler());
433 final HttpHost target = start();
434 final HttpGet httpget = new HttpGet("http://test:all-wrong@" + target.toHostString() + "/");
435
436 final HttpClientContext context = HttpClientContext.create();
437 final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
438 final HttpEntity entity = response.getEntity();
439 Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getCode());
440 Assert.assertNotNull(entity);
441 EntityUtils.consume(entity);
442 }
443
444 @Test
445 public void testAuthenticationUserinfoInRedirectSuccess() throws Exception {
446 this.server.registerHandler("/*", new EchoHandler());
447 this.server.registerHandler("/thatway", new HttpRequestHandler() {
448
449 @Override
450 public void handle(
451 final ClassicHttpRequest request,
452 final ClassicHttpResponse response,
453 final HttpContext context) throws HttpException, IOException {
454 final EndpointDetails endpoint = (EndpointDetails) context.getAttribute(HttpCoreContext.CONNECTION_ENDPOINT);
455 final InetSocketAddress socketAddress = (InetSocketAddress) endpoint.getLocalAddress();
456 final int port = socketAddress.getPort();
457 response.setCode(HttpStatus.SC_MOVED_PERMANENTLY);
458 response.addHeader(new BasicHeader("Location", "http://test:test@localhost:" + port + "/secure"));
459 }
460
461 });
462
463 final HttpHost target = start(new BasicTestAuthenticator("test:test", "test realm") {
464
465 @Override
466 public boolean authenticate(final URIAuthority authority, final String requestUri, final String credentials) {
467 if (requestUri.equals("/secure") || requestUri.startsWith("/secure/")) {
468 return super.authenticate(authority, requestUri, credentials);
469 }
470 return true;
471 }
472 });
473
474 final HttpGet httpget = new HttpGet("/thatway");
475 final HttpClientContext context = HttpClientContext.create();
476
477 final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
478 final HttpEntity entity = response.getEntity();
479 Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
480 Assert.assertNotNull(entity);
481 EntityUtils.consume(entity);
482 }
483
484 static class CountingAuthenticator extends BasicTestAuthenticator {
485
486 private final AtomicLong count;
487
488 public CountingAuthenticator(final String userToken, final String realm) {
489 super(userToken, realm);
490 this.count = new AtomicLong();
491 }
492
493 @Override
494 public boolean authenticate(final URIAuthority authority, final String requestUri, final String credentials) {
495 this.count.incrementAndGet();
496 return super.authenticate(authority, requestUri, credentials);
497 }
498
499 public long getCount() {
500 return this.count.get();
501 }
502
503 }
504
505 @Test
506 public void testPreemptiveAuthentication() throws Exception {
507 this.server.registerHandler("*", new EchoHandler());
508 final CountingAuthenticator countingAuthenticator = new CountingAuthenticator("test:test", "test realm");
509 final HttpHost target = start(countingAuthenticator);
510
511 final BasicScheme basicScheme = new BasicScheme();
512 basicScheme.initPreemptive(new UsernamePasswordCredentials("test", "test".toCharArray()));
513 final HttpClientContext context = HttpClientContext.create();
514 final AuthCache authCache = new BasicAuthCache();
515 authCache.put(target, basicScheme);
516 context.setAuthCache(authCache);
517
518 final HttpGet httpget = new HttpGet("/");
519 final ClassicHttpResponse response1 = this.httpclient.execute(target, httpget, context);
520 final HttpEntity entity1 = response1.getEntity();
521 Assert.assertEquals(HttpStatus.SC_OK, response1.getCode());
522 Assert.assertNotNull(entity1);
523 EntityUtils.consume(entity1);
524
525 Assert.assertEquals(1, countingAuthenticator.getCount());
526 }
527
528 @Test
529 public void testPreemptiveAuthenticationFailure() throws Exception {
530 this.server.registerHandler("*", new EchoHandler());
531 final CountingAuthenticator countingAuthenticator = new CountingAuthenticator("test:test", "test realm");
532
533 final HttpHost target = start(countingAuthenticator);
534
535 final HttpClientContext context = HttpClientContext.create();
536 final AuthCache authCache = new BasicAuthCache();
537 authCache.put(target, new BasicScheme());
538 context.setAuthCache(authCache);
539 final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
540 credsProvider.setCredentials(new AuthScope(null, null, -1, null ,null),
541 new UsernamePasswordCredentials("test", "stuff".toCharArray()));
542 context.setCredentialsProvider(credsProvider);
543
544 final HttpGet httpget = new HttpGet("/");
545 final ClassicHttpResponse response1 = this.httpclient.execute(target, httpget, context);
546 final HttpEntity entity1 = response1.getEntity();
547 Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, response1.getCode());
548 Assert.assertNotNull(entity1);
549 EntityUtils.consume(entity1);
550
551 Assert.assertEquals(1, countingAuthenticator.getCount());
552 }
553
554 static class ProxyAuthHandler implements HttpRequestHandler {
555
556 @Override
557 public void handle(
558 final ClassicHttpRequest request,
559 final ClassicHttpResponse response,
560 final HttpContext context) throws HttpException, IOException {
561 final String creds = (String) context.getAttribute("creds");
562 if (creds == null || !creds.equals("test:test")) {
563 response.setCode(HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED);
564 } else {
565 response.setCode(HttpStatus.SC_OK);
566 final StringEntity entity = new StringEntity("success", StandardCharsets.US_ASCII);
567 response.setEntity(entity);
568 }
569 }
570
571 }
572
573 @Test
574 public void testAuthenticationTargetAsProxy() throws Exception {
575 this.server.registerHandler("*", new ProxyAuthHandler());
576
577 final HttpHost target = super.start();
578
579 final HttpClientContext context = HttpClientContext.create();
580 final TestCredentialsProvider credsProvider = new TestCredentialsProvider(null);
581 context.setCredentialsProvider(credsProvider);
582
583 final HttpGet httpget = new HttpGet("/");
584 final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
585 final HttpEntity entity = response.getEntity();
586 Assert.assertEquals(HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED,
587 response.getCode());
588 EntityUtils.consume(entity);
589 }
590
591 @Test
592 public void testConnectionCloseAfterAuthenticationSuccess() throws Exception {
593 this.server.registerHandler("*", new EchoHandler());
594
595 final HttpHost target = start(
596 HttpProcessors.server(),
597 new Decorator<HttpServerRequestHandler>() {
598
599 @Override
600 public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
601 return new AuthenticatingDecorator(requestHandler, new BasicTestAuthenticator("test:test", "test realm")) {
602
603 @Override
604 protected void customizeUnauthorizedResponse(final ClassicHttpResponse unauthorized) {
605 unauthorized.addHeader(HttpHeaders.CONNECTION, HeaderElements.CLOSE);
606 }
607
608 };
609 }
610
611 });
612
613 final HttpClientContext context = HttpClientContext.create();
614 final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
615 credsProvider.setCredentials(new AuthScope(null, null, -1, null ,null),
616 new UsernamePasswordCredentials("test", "test".toCharArray()));
617 context.setCredentialsProvider(credsProvider);
618
619 for (int i = 0; i < 2; i++) {
620 final HttpGet httpget = new HttpGet("/");
621
622 final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
623 EntityUtils.consume(response.getEntity());
624 Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
625 }
626 }
627
628 @Test
629 public void testReauthentication() throws Exception {
630 this.server.registerHandler("*", new EchoHandler());
631
632 final BasicSchemeFactory myBasicAuthSchemeFactory = new BasicSchemeFactory() {
633
634 @Override
635 public AuthScheme create(final HttpContext context) {
636 return new BasicScheme() {
637 private static final long serialVersionUID = 1L;
638
639 @Override
640 public String getName() {
641 return "MyBasic";
642 }
643
644 };
645 }
646
647 };
648
649 final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
650 new UsernamePasswordCredentials("test", "test".toCharArray()));
651
652 final RequestConfig config = RequestConfig.custom()
653 .setTargetPreferredAuthSchemes(Arrays.asList("MyBasic"))
654 .build();
655 final Registry<AuthSchemeFactory> authSchemeRegistry = RegistryBuilder.<AuthSchemeFactory>create()
656 .register("MyBasic", myBasicAuthSchemeFactory)
657 .build();
658 this.httpclient = this.clientBuilder
659 .setDefaultAuthSchemeRegistry(authSchemeRegistry)
660 .setDefaultCredentialsProvider(credsProvider)
661 .build();
662
663 final Authenticator authenticator = new BasicTestAuthenticator("test:test", "test realm") {
664
665 private final AtomicLong count = new AtomicLong(0);
666
667 @Override
668 public boolean authenticate(final URIAuthority authority, final String requestUri, final String credentials) {
669 final boolean authenticated = super.authenticate(authority, requestUri, credentials);
670 if (authenticated) {
671 return this.count.incrementAndGet() % 4 != 0;
672 }
673 return false;
674 }
675 };
676
677 final HttpHost target = start(
678 HttpProcessors.server(),
679 new Decorator<HttpServerRequestHandler>() {
680
681 @Override
682 public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
683 return new AuthenticatingDecorator(requestHandler, authenticator) {
684
685 @Override
686 protected void customizeUnauthorizedResponse(final ClassicHttpResponse unauthorized) {
687 unauthorized.removeHeaders(HttpHeaders.WWW_AUTHENTICATE);
688 unauthorized.addHeader(HttpHeaders.WWW_AUTHENTICATE, "MyBasic realm=\"test realm\"");
689 }
690
691 };
692 }
693
694 });
695
696 final HttpClientContext context = HttpClientContext.create();
697 for (int i = 0; i < 10; i++) {
698 final HttpGet httpget = new HttpGet("/");
699 httpget.setConfig(config);
700 try (final CloseableHttpResponse response = this.httpclient.execute(target, httpget, context)) {
701 final HttpEntity entity = response.getEntity();
702 Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
703 Assert.assertNotNull(entity);
704 EntityUtils.consume(entity);
705 }
706 }
707 }
708
709 @Test
710 public void testAuthenticationFallback() throws Exception {
711 this.server.registerHandler("*", new EchoHandler());
712
713 final HttpHost target = start(
714 HttpProcessors.server(),
715 new Decorator<HttpServerRequestHandler>() {
716
717 @Override
718 public HttpServerRequestHandler decorate(final HttpServerRequestHandler requestHandler) {
719 return new AuthenticatingDecorator(requestHandler, new BasicTestAuthenticator("test:test", "test realm")) {
720
721 @Override
722 protected void customizeUnauthorizedResponse(final ClassicHttpResponse unauthorized) {
723 unauthorized.addHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.DIGEST + " realm=\"test realm\" invalid");
724 }
725
726 };
727 }
728
729 });
730
731 final HttpClientContext context = HttpClientContext.create();
732 final TestCredentialsProvider credsProvider = new TestCredentialsProvider(
733 new UsernamePasswordCredentials("test", "test".toCharArray()));
734 context.setCredentialsProvider(credsProvider);
735 final HttpGet httpget = new HttpGet("/");
736
737 final ClassicHttpResponse response = this.httpclient.execute(target, httpget, context);
738 final HttpEntity entity = response.getEntity();
739 Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
740 Assert.assertNotNull(entity);
741 EntityUtils.consume(entity);
742 final AuthScope authscope = credsProvider.getAuthScope();
743 Assert.assertNotNull(authscope);
744 Assert.assertEquals("test realm", authscope.getRealm());
745 }
746
747 }