View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.hc.client5.http.impl.auth;
28  
29  import java.util.LinkedList;
30  import java.util.Queue;
31  
32  import org.apache.hc.client5.http.auth.AuthCache;
33  import org.apache.hc.client5.http.auth.AuthExchange;
34  import org.apache.hc.client5.http.auth.AuthScheme;
35  import org.apache.hc.client5.http.auth.AuthSchemeFactory;
36  import org.apache.hc.client5.http.auth.AuthScope;
37  import org.apache.hc.client5.http.auth.AuthStateCacheable;
38  import org.apache.hc.client5.http.auth.AuthenticationException;
39  import org.apache.hc.client5.http.auth.ChallengeType;
40  import org.apache.hc.client5.http.auth.Credentials;
41  import org.apache.hc.client5.http.auth.CredentialsProvider;
42  import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
43  import org.apache.hc.client5.http.auth.StandardAuthScheme;
44  import org.apache.hc.client5.http.impl.DefaultAuthenticationStrategy;
45  import org.apache.hc.client5.http.protocol.HttpClientContext;
46  import org.apache.hc.core5.http.HttpHeaders;
47  import org.apache.hc.core5.http.HttpHost;
48  import org.apache.hc.core5.http.HttpRequest;
49  import org.apache.hc.core5.http.HttpResponse;
50  import org.apache.hc.core5.http.HttpStatus;
51  import org.apache.hc.core5.http.config.Lookup;
52  import org.apache.hc.core5.http.config.RegistryBuilder;
53  import org.apache.hc.core5.http.message.BasicHeader;
54  import org.apache.hc.core5.http.message.BasicHttpRequest;
55  import org.apache.hc.core5.http.message.BasicHttpResponse;
56  import org.apache.hc.core5.http.protocol.BasicHttpContext;
57  import org.apache.hc.core5.http.protocol.HttpContext;
58  import org.junit.Assert;
59  import org.junit.Before;
60  import org.junit.Test;
61  import org.mockito.Answers;
62  import org.mockito.Mockito;
63  
64  @SuppressWarnings({"boxing","static-access"})
65  public class TestHttpAuthenticator {
66  
67      @AuthStateCacheable
68      abstract class CacheableAuthState implements AuthScheme {
69  
70          @Override
71          public String getName() {
72              return StandardAuthScheme.BASIC;
73          }
74  
75      }
76  
77      private AuthExchange authExchange;
78      private CacheableAuthState authScheme;
79      private HttpContext context;
80      private HttpHost defaultHost;
81      private CredentialsProvider credentialsProvider;
82      private Lookup<AuthSchemeFactory> authSchemeRegistry;
83      private AuthCache authCache;
84      private HttpAuthenticator httpAuthenticator;
85  
86      @Before
87      public void setUp() throws Exception {
88          this.authExchange = new AuthExchange();
89          this.authScheme = Mockito.mock(CacheableAuthState.class, Mockito.withSettings()
90                  .defaultAnswer(Answers.CALLS_REAL_METHODS));
91          Mockito.when(this.authScheme.isChallengeComplete()).thenReturn(Boolean.TRUE);
92          this.context = new BasicHttpContext();
93          this.defaultHost = new HttpHost("localhost", 80);
94          this.credentialsProvider = Mockito.mock(CredentialsProvider.class);
95          this.context.setAttribute(HttpClientContext.CREDS_PROVIDER, this.credentialsProvider);
96          this.authSchemeRegistry = RegistryBuilder.<AuthSchemeFactory>create()
97              .register(StandardAuthScheme.BASIC, BasicSchemeFactory.INSTANCE)
98              .register(StandardAuthScheme.DIGEST, DigestSchemeFactory.INSTANCE)
99              .register(StandardAuthScheme.NTLM, NTLMSchemeFactory.INSTANCE).build();
100         this.context.setAttribute(HttpClientContext.AUTHSCHEME_REGISTRY, this.authSchemeRegistry);
101         this.authCache = Mockito.mock(AuthCache.class);
102         this.context.setAttribute(HttpClientContext.AUTH_CACHE, this.authCache);
103         this.httpAuthenticator = new HttpAuthenticator();
104     }
105 
106     @Test
107     public void testUpdateAuthExchange() throws Exception {
108         final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
109         response.setHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.BASIC + " realm=test");
110         Assert.assertTrue(this.httpAuthenticator.isChallenged(
111                 this.defaultHost, ChallengeType.TARGET, response, this.authExchange, this.context));
112         Mockito.verifyZeroInteractions(this.authCache);
113     }
114 
115     @Test
116     public void testAuthenticationRequestedAfterSuccess() throws Exception {
117         final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
118         response.setHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.BASIC + " realm=test");
119 
120         this.authExchange.select(this.authScheme);
121         this.authExchange.setState(AuthExchange.State.SUCCESS);
122 
123         Assert.assertTrue(this.httpAuthenticator.isChallenged(
124                 this.defaultHost, ChallengeType.TARGET, response, this.authExchange, this.context));
125 
126         Mockito.verify(this.authCache).remove(this.defaultHost);
127     }
128 
129     @Test
130     public void testAuthenticationNotRequestedUnchallenged() throws Exception {
131         final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
132 
133         Assert.assertFalse(this.httpAuthenticator.isChallenged(
134                 this.defaultHost, ChallengeType.TARGET, response, this.authExchange, this.context));
135         Assert.assertEquals(AuthExchange.State.UNCHALLENGED, this.authExchange.getState());
136     }
137 
138     @Test
139     public void testAuthenticationNotRequestedSuccess1() throws Exception {
140         final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
141         this.authExchange.select(this.authScheme);
142         this.authExchange.setState(AuthExchange.State.CHALLENGED);
143 
144         Assert.assertFalse(this.httpAuthenticator.isChallenged(
145                 this.defaultHost, ChallengeType.TARGET, response, this.authExchange, this.context));
146         Assert.assertEquals(AuthExchange.State.SUCCESS, this.authExchange.getState());
147 
148         Mockito.verify(this.authCache).put(this.defaultHost, this.authScheme);
149     }
150 
151     @Test
152     public void testAuthenticationNotRequestedSuccess2() throws Exception {
153         final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_OK, "OK");
154         this.authExchange.select(this.authScheme);
155         this.authExchange.setState(AuthExchange.State.HANDSHAKE);
156 
157         Assert.assertFalse(this.httpAuthenticator.isChallenged(
158                 this.defaultHost, ChallengeType.TARGET, response, this.authExchange, this.context));
159         Assert.assertEquals(AuthExchange.State.SUCCESS, this.authExchange.getState());
160 
161         Mockito.verify(this.authCache).put(this.defaultHost, this.authScheme);
162     }
163 
164     @Test
165     public void testAuthentication() throws Exception {
166         final HttpHost host = new HttpHost("somehost", 80);
167         final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
168         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.BASIC + " realm=\"test\""));
169         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.DIGEST + " realm=\"realm1\", nonce=\"1234\""));
170         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "whatever realm=\"realm1\", stuff=\"1234\""));
171 
172         final Credentials credentials = new UsernamePasswordCredentials("user", "pass".toCharArray());
173         Mockito.when(this.credentialsProvider.getCredentials(Mockito.<AuthScope>any(),
174                                                              Mockito.<HttpContext>any())).thenReturn(credentials);
175 
176         final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
177 
178         Assert.assertTrue(this.httpAuthenticator.updateAuthState(host, ChallengeType.TARGET, response, authStrategy,
179                                                                      this.authExchange, this.context));
180         Assert.assertEquals(AuthExchange.State.CHALLENGED, this.authExchange.getState());
181 
182         final Queue<AuthScheme> options = this.authExchange.getAuthOptions();
183         Assert.assertNotNull(options);
184         final AuthScheme authScheme1 = options.poll();
185         Assert.assertNotNull(authScheme1);
186         Assert.assertEquals(StandardAuthScheme.DIGEST, authScheme1.getName());
187         final AuthScheme authScheme2 = options.poll();
188         Assert.assertNotNull(authScheme2);
189         Assert.assertEquals(StandardAuthScheme.BASIC, authScheme2.getName());
190         Assert.assertNull(options.poll());
191     }
192 
193     @Test
194     public void testAuthenticationCredentialsForBasic() throws Exception {
195         final HttpHost host = new HttpHost("somehost", 80);
196         final HttpResponse response =
197             new BasicHttpResponse(HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
198         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.BASIC + " realm=\"test\""));
199         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.DIGEST + " realm=\"realm1\", nonce=\"1234\""));
200 
201         final Credentials credentials = new UsernamePasswordCredentials("user", "pass".toCharArray());
202         Mockito.when(this.credentialsProvider.getCredentials(Mockito.eq(new AuthScope(host, "test", StandardAuthScheme.BASIC)),
203                                                              Mockito.<HttpContext>any())).thenReturn(credentials);
204 
205         final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
206 
207         Assert.assertTrue(this.httpAuthenticator.updateAuthState(host, ChallengeType.TARGET, response, authStrategy,
208                                                                      this.authExchange, this.context));
209         Assert.assertEquals(AuthExchange.State.CHALLENGED, this.authExchange.getState());
210 
211         final Queue<AuthScheme> options = this.authExchange.getAuthOptions();
212         Assert.assertNotNull(options);
213         final AuthScheme authScheme1 = options.poll();
214         Assert.assertNotNull(authScheme1);
215         Assert.assertEquals(StandardAuthScheme.BASIC, authScheme1.getName());
216         Assert.assertNull(options.poll());
217     }
218 
219     @Test
220     public void testAuthenticationNoChallenges() throws Exception {
221         final HttpHost host = new HttpHost("somehost", 80);
222         final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
223 
224         final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
225 
226         Assert.assertFalse(this.httpAuthenticator.updateAuthState(
227                 host, ChallengeType.TARGET, response, authStrategy, this.authExchange, this.context));
228     }
229 
230     @Test
231     public void testAuthenticationNoSupportedChallenges() throws Exception {
232         final HttpHost host = new HttpHost("somehost", 80);
233         final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
234         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "This realm=\"test\""));
235         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "That realm=\"realm1\", nonce=\"1234\""));
236 
237         final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
238 
239         Assert.assertFalse(this.httpAuthenticator.updateAuthState(
240                 host, ChallengeType.TARGET, response, authStrategy, this.authExchange, this.context));
241     }
242 
243     @Test
244     public void testAuthenticationNoCredentials() throws Exception {
245         final HttpHost host = new HttpHost("somehost", 80);
246         final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
247         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.BASIC + " realm=\"test\""));
248         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.DIGEST + " realm=\"realm1\", nonce=\"1234\""));
249 
250         final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
251 
252         Assert.assertFalse(this.httpAuthenticator.updateAuthState(
253                 host, ChallengeType.TARGET, response, authStrategy, this.authExchange, this.context));
254     }
255 
256     @Test
257     public void testAuthenticationFailed() throws Exception {
258         final HttpHost host = new HttpHost("somehost", 80);
259         final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
260         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.BASIC + " realm=\"test\""));
261         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.DIGEST + " realm=\"realm1\", nonce=\"1234\""));
262 
263         this.authExchange.setState(AuthExchange.State.CHALLENGED);
264         this.authExchange.select(this.authScheme);
265 
266         final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
267 
268         Assert.assertFalse(this.httpAuthenticator.updateAuthState(
269                 host, ChallengeType.TARGET, response, authStrategy, this.authExchange, this.context));
270 
271         Assert.assertEquals(AuthExchange.State.FAILURE, this.authExchange.getState());
272 
273         Mockito.verify(this.authCache).remove(host);
274     }
275 
276     @Test
277     public void testAuthenticationFailedPreviously() throws Exception {
278         final HttpHost host = new HttpHost("somehost", 80);
279         final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
280         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.BASIC + " realm=\"test\""));
281         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.DIGEST + " realm=\"realm1\", nonce=\"1234\""));
282 
283         this.authExchange.setState(AuthExchange.State.FAILURE);
284 
285         final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
286 
287         Assert.assertFalse(this.httpAuthenticator.updateAuthState(
288                 host, ChallengeType.TARGET, response, authStrategy, this.authExchange, this.context));
289 
290         Assert.assertEquals(AuthExchange.State.FAILURE, this.authExchange.getState());
291     }
292 
293     @Test
294     public void testAuthenticationFailure() throws Exception {
295         final HttpHost host = new HttpHost("somehost", 80);
296         final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
297         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.BASIC + " realm=\"test\""));
298         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.DIGEST + " realm=\"realm1\", nonce=\"1234\""));
299         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "whatever realm=\"realm1\", stuff=\"1234\""));
300 
301         final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
302 
303         this.authExchange.setState(AuthExchange.State.CHALLENGED);
304         this.authExchange.select(new BasicScheme());
305 
306         Assert.assertFalse(this.httpAuthenticator.updateAuthState(
307                 host, ChallengeType.TARGET, response, authStrategy, this.authExchange, this.context));
308         Assert.assertEquals(AuthExchange.State.FAILURE, this.authExchange.getState());
309     }
310 
311     @Test
312     public void testAuthenticationHandshaking() throws Exception {
313         final HttpHost host = new HttpHost("somehost", 80);
314         final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
315         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.BASIC + " realm=\"test\""));
316         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.DIGEST + " realm=\"realm1\", stale=true, nonce=\"1234\""));
317         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "whatever realm=\"realm1\", stuff=\"1234\""));
318 
319         final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
320 
321         this.authExchange.setState(AuthExchange.State.CHALLENGED);
322         this.authExchange.select(new DigestScheme());
323 
324         Assert.assertTrue(this.httpAuthenticator.updateAuthState(
325                 host, ChallengeType.TARGET, response, authStrategy, this.authExchange, this.context));
326 
327         Assert.assertEquals(AuthExchange.State.HANDSHAKE, this.authExchange.getState());
328     }
329 
330     @Test
331     public void testAuthenticationNoMatchingChallenge() throws Exception {
332         final HttpHost host = new HttpHost("somehost", 80);
333         final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
334         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, StandardAuthScheme.DIGEST + " realm=\"realm1\", nonce=\"1234\""));
335         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "whatever realm=\"realm1\", stuff=\"1234\""));
336 
337         final Credentials credentials = new UsernamePasswordCredentials("user", "pass".toCharArray());
338         Mockito.when(this.credentialsProvider.getCredentials(Mockito.eq(new AuthScope(host, "realm1", StandardAuthScheme.DIGEST)),
339                                                              Mockito.<HttpContext>any())).thenReturn(credentials);
340 
341         final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
342 
343         this.authExchange.setState(AuthExchange.State.CHALLENGED);
344         this.authExchange.select(new BasicScheme());
345 
346         Assert.assertTrue(this.httpAuthenticator.updateAuthState(
347                 host, ChallengeType.TARGET, response, authStrategy, this.authExchange, this.context));
348         Assert.assertEquals(AuthExchange.State.CHALLENGED, this.authExchange.getState());
349 
350         final Queue<AuthScheme> options = this.authExchange.getAuthOptions();
351         Assert.assertNotNull(options);
352         final AuthScheme authScheme1 = options.poll();
353         Assert.assertNotNull(authScheme1);
354         Assert.assertEquals(StandardAuthScheme.DIGEST, authScheme1.getName());
355         Assert.assertNull(options.poll());
356     }
357 
358     @Test
359     public void testAuthenticationException() throws Exception {
360         final HttpHost host = new HttpHost("somehost", 80);
361         final HttpResponse response = new BasicHttpResponse(HttpStatus.SC_UNAUTHORIZED, "UNAUTHORIZED");
362         response.addHeader(new BasicHeader(HttpHeaders.WWW_AUTHENTICATE, "blah blah blah"));
363 
364         this.authExchange.setState(AuthExchange.State.CHALLENGED);
365 
366         final DefaultAuthenticationStrategy authStrategy = new DefaultAuthenticationStrategy();
367 
368         Assert.assertFalse(this.httpAuthenticator.updateAuthState(
369                 host, ChallengeType.TARGET, response, authStrategy, this.authExchange, this.context));
370 
371         Assert.assertEquals(AuthExchange.State.UNCHALLENGED, this.authExchange.getState());
372         Assert.assertNull(this.authExchange.getAuthScheme());
373     }
374 
375     @Test
376     public void testAuthFailureState() throws Exception {
377         final HttpRequest request = new BasicHttpRequest("GET", "/");
378         this.authExchange.setState(AuthExchange.State.FAILURE);
379         this.authExchange.select(this.authScheme);
380 
381         this.httpAuthenticator.addAuthResponse(defaultHost, ChallengeType.TARGET, request, authExchange, context);
382 
383         Assert.assertFalse(request.containsHeader(HttpHeaders.AUTHORIZATION));
384 
385         Mockito.verify(this.authScheme, Mockito.never()).generateAuthResponse(
386                 Mockito.eq(defaultHost),
387                 Mockito.any(HttpRequest.class),
388                 Mockito.any(HttpContext.class));
389     }
390 
391     @Test
392     public void testAuthChallengeStateNoOption() throws Exception {
393         final HttpRequest request = new BasicHttpRequest("GET", "/");
394         this.authExchange.setState(AuthExchange.State.CHALLENGED);
395         this.authExchange.select(this.authScheme);
396 
397         Mockito.when(this.authScheme.generateAuthResponse(
398                 Mockito.eq(defaultHost),
399                 Mockito.any(HttpRequest.class),
400                 Mockito.any(HttpContext.class))).thenReturn("stuff");
401 
402         this.httpAuthenticator.addAuthResponse(defaultHost, ChallengeType.TARGET, request, authExchange, context);
403 
404         Assert.assertTrue(request.containsHeader(HttpHeaders.AUTHORIZATION));
405     }
406 
407     @Test
408     public void testAuthChallengeStateOneOptions() throws Exception {
409         final HttpRequest request = new BasicHttpRequest("GET", "/");
410         this.authExchange.setState(AuthExchange.State.CHALLENGED);
411         final LinkedList<AuthScheme> authOptions = new LinkedList<>();
412         authOptions.add(this.authScheme);
413         this.authExchange.setOptions(authOptions);
414 
415         Mockito.when(this.authScheme.generateAuthResponse(
416                 Mockito.eq(defaultHost),
417                 Mockito.any(HttpRequest.class),
418                 Mockito.any(HttpContext.class))).thenReturn("stuff");
419 
420         this.httpAuthenticator.addAuthResponse(defaultHost, ChallengeType.TARGET, request, authExchange, context);
421 
422         Assert.assertSame(this.authScheme, this.authExchange.getAuthScheme());
423         Assert.assertNull(this.authExchange.getAuthOptions());
424 
425         Assert.assertTrue(request.containsHeader(HttpHeaders.AUTHORIZATION));
426     }
427 
428     @Test
429     public void testAuthChallengeStateMultipleOption() throws Exception {
430         final HttpRequest request = new BasicHttpRequest("GET", "/");
431         this.authExchange.setState(AuthExchange.State.CHALLENGED);
432 
433         final LinkedList<AuthScheme> authOptions = new LinkedList<>();
434         final AuthScheme authScheme1 = Mockito.mock(AuthScheme.class);
435         Mockito.doThrow(new AuthenticationException()).when(authScheme1).generateAuthResponse(
436                 Mockito.eq(defaultHost),
437                 Mockito.any(HttpRequest.class),
438                 Mockito.any(HttpContext.class));
439         final AuthScheme authScheme2 = Mockito.mock(AuthScheme.class);
440         Mockito.when(authScheme2.generateAuthResponse(
441                 Mockito.eq(defaultHost),
442                 Mockito.any(HttpRequest.class),
443                 Mockito.any(HttpContext.class))).thenReturn("stuff");
444         authOptions.add(authScheme1);
445         authOptions.add(authScheme2);
446         this.authExchange.setOptions(authOptions);
447 
448         this.httpAuthenticator.addAuthResponse(defaultHost, ChallengeType.TARGET, request, authExchange, context);
449 
450         Assert.assertSame(authScheme2, this.authExchange.getAuthScheme());
451         Assert.assertNull(this.authExchange.getAuthOptions());
452 
453         Assert.assertTrue(request.containsHeader(HttpHeaders.AUTHORIZATION));
454     }
455 
456     @Test
457     public void testAuthSuccess() throws Exception {
458         final HttpRequest request = new BasicHttpRequest("GET", "/");
459         this.authExchange.setState(AuthExchange.State.SUCCESS);
460         this.authExchange.select(this.authScheme);
461 
462         Mockito.when(this.authScheme.isConnectionBased()).thenReturn(Boolean.FALSE);
463         Mockito.when(this.authScheme.generateAuthResponse(
464                 Mockito.eq(defaultHost),
465                 Mockito.any(HttpRequest.class),
466                 Mockito.any(HttpContext.class))).thenReturn("stuff");
467 
468         this.httpAuthenticator.addAuthResponse(defaultHost, ChallengeType.TARGET, request, authExchange, context);
469 
470         Assert.assertSame(this.authScheme, this.authExchange.getAuthScheme());
471         Assert.assertNull(this.authExchange.getAuthOptions());
472 
473         Assert.assertTrue(request.containsHeader(HttpHeaders.AUTHORIZATION));
474     }
475 
476     @Test
477     public void testAuthSuccessConnectionBased() throws Exception {
478         final HttpRequest request = new BasicHttpRequest("GET", "/");
479         this.authExchange.setState(AuthExchange.State.SUCCESS);
480         this.authExchange.select(this.authScheme);
481 
482         Mockito.when(this.authScheme.isConnectionBased()).thenReturn(Boolean.TRUE);
483         Mockito.when(this.authScheme.generateAuthResponse(
484                 Mockito.eq(defaultHost),
485                 Mockito.any(HttpRequest.class),
486                 Mockito.any(HttpContext.class))).thenReturn("stuff");
487 
488         this.httpAuthenticator.addAuthResponse(defaultHost, ChallengeType.TARGET, request, authExchange, context);
489 
490         Assert.assertFalse(request.containsHeader(HttpHeaders.AUTHORIZATION));
491 
492         Mockito.verify(this.authScheme, Mockito.never()).generateAuthResponse(
493                 Mockito.eq(defaultHost),
494                 Mockito.any(HttpRequest.class),
495                 Mockito.any(HttpContext.class));
496     }
497 
498 }