1   /*
2    * $Header: /home/cvs/jakarta-commons/httpclient/src/test/org/apache/commons/httpclient/auth/TestBasicAuth.java,v 1.2 2004/03/25 20:37:20 olegk Exp $
3    * $Revision: 1.2 $
4    * $Date: 2004/03/25 20:37:20 $
5    * ====================================================================
6    *
7    *  Copyright 1999-2004 The Apache Software Foundation
8    *
9    *  Licensed under the Apache License, Version 2.0 (the "License");
10   *  you may not use this file except in compliance with the License.
11   *  You may obtain a copy of the License at
12   *
13   *      http://www.apache.org/licenses/LICENSE-2.0
14   *
15   *  Unless required by applicable law or agreed to in writing, software
16   *  distributed under the License is distributed on an "AS IS" BASIS,
17   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   *  See the License for the specific language governing permissions and
19   *  limitations under the License.
20   * ====================================================================
21   *
22   * This software consists of voluntary contributions made by many
23   * individuals on behalf of the Apache Software Foundation.  For more
24   * information on the Apache Software Foundation, please see
25   * <http://www.apache.org/>.
26   *
27   * [Additional notices, if required by prior licensing conditions]
28   *
29   */
30  
31  package org.apache.commons.httpclient.auth;
32  
33  import java.io.IOException;
34  
35  import junit.framework.Test;
36  import junit.framework.TestSuite;
37  
38  import org.apache.commons.codec.binary.Base64;
39  import org.apache.commons.httpclient.Header;
40  import org.apache.commons.httpclient.HttpClientTestBase;
41  import org.apache.commons.httpclient.HttpState;
42  import org.apache.commons.httpclient.HttpStatus;
43  import org.apache.commons.httpclient.UsernamePasswordCredentials;
44  import org.apache.commons.httpclient.methods.GetMethod;
45  import org.apache.commons.httpclient.server.HttpService;
46  import org.apache.commons.httpclient.server.RequestLine;
47  import org.apache.commons.httpclient.server.SimpleRequest;
48  import org.apache.commons.httpclient.server.SimpleResponse;
49  import org.apache.commons.httpclient.util.EncodingUtil;
50  
51  /***
52   * Basic authentication test cases.
53   *
54   * @author Oleg Kalnichevski
55   * 
56   * @version $Id: TestBasicAuth.java,v 1.2 2004/03/25 20:37:20 olegk Exp $
57   */
58  public class TestBasicAuth extends HttpClientTestBase {
59  
60      // ------------------------------------------------------------ Constructor
61      public TestBasicAuth(String testName) {
62          super(testName);
63      }
64  
65      // ------------------------------------------------------------------- Main
66      public static void main(String args[]) {
67          String[] testCaseName = { TestBasicAuth.class.getName() };
68          junit.textui.TestRunner.main(testCaseName);
69      }
70  
71      // ------------------------------------------------------- TestCase Methods
72  
73      public static Test suite() {
74          return new TestSuite(TestBasicAuth.class);
75      }
76  
77      private class BasicAuthService implements HttpService {
78  
79          public BasicAuthService() {
80              super();
81          }
82  
83          public boolean process(final SimpleRequest request, final SimpleResponse response)
84              throws IOException
85          {
86              Header challenge = new Header("WWW-Authenticate", "Basic realm=\"test\"");
87              RequestLine requestLine = request.getRequestLine();
88              Header auth = request.getFirstHeader("Authorization");
89              if (auth == null) { 
90                  response.setStatusLine("HTTP/1.1 401 Unauthorized");
91                  response.addHeader(challenge);
92                  response.setBodyString("Authorization required");
93                  return true;
94              }
95              boolean pass = false;
96              String s = auth.getValue();
97              int i = s.indexOf(" ");
98              if (i != -1) {
99                  String authtype = s.substring(0, i);
100                 if ("BASIC".equalsIgnoreCase(authtype)) {
101                     String creds = s.substring(i + 1, s.length());
102                     creds = EncodingUtil.getAsciiString(
103                         Base64.decodeBase64(
104                             EncodingUtil.getAsciiBytes(creds)));
105                     if (creds.equals("test:test")) {
106                         pass = true;    
107                     }
108                 }
109             }
110             if (!pass) {
111                 response.setStatusLine("HTTP/1.1 403 Forbidden");
112                 response.addHeader(challenge);
113                 response.setBodyString("Access forbidden");
114                 return true;
115             }
116             response.setStatusLine("HTTP/1.1 200 OK");
117             response.setBodyString("Authorization successful");
118             return true;
119         }
120     }
121 
122     private class BasicAuthService2 implements HttpService {
123 
124         public BasicAuthService2() {
125             super();
126         }
127 
128         public boolean process(final SimpleRequest request, final SimpleResponse response)
129             throws IOException
130         {
131             Header challenge = new Header("WWW-Authenticate", "Basic realm=\"test2\"");
132             RequestLine requestLine = request.getRequestLine();
133             Header auth = request.getFirstHeader("Authorization");
134             if (auth == null) { 
135                 response.setStatusLine("HTTP/1.1 401 Unauthorized");
136                 response.addHeader(challenge);
137                 response.setBodyString("Authorization required");
138                 return true;
139             }
140             boolean pass = false;
141             String s = auth.getValue();
142             int i = s.indexOf(" ");
143             if (i != -1) {
144                 String authtype = s.substring(0, i);
145                 if ("BASIC".equalsIgnoreCase(authtype)) {
146                     String creds = s.substring(i + 1, s.length());
147                     creds = EncodingUtil.getAsciiString(
148                         Base64.decodeBase64(
149                             EncodingUtil.getAsciiBytes(creds)));
150                     if (creds.equals("test2:test2")) {
151                         pass = true;    
152                     }
153                 }
154             }
155             if (!pass) {
156                 response.setStatusLine("HTTP/1.1 403 Forbidden");
157                 response.addHeader(challenge);
158                 response.setBodyString("Access forbidden");
159                 return true;
160             }
161             response.setStatusLine("HTTP/1.1 200 OK");
162             response.setBodyString("Authorization successful");
163             return true;
164         }
165     }
166 
167     private class BasicAuthService3 implements HttpService {
168 
169         public BasicAuthService3() {
170             super();
171         }
172 
173         public boolean process(final SimpleRequest request, final SimpleResponse response)
174             throws IOException
175         {
176             Header challenge = new Header("WwW-AuThEnTiCaTe", "bAsIc ReAlM=\"test\"");
177             RequestLine requestLine = request.getRequestLine();
178             Header auth = request.getFirstHeader("Authorization");
179             if (auth == null) { 
180                 response.setStatusLine("HTTP/1.1 401 Unauthorized");
181                 response.addHeader(challenge);
182                 response.setBodyString("Authorization required");
183                 return true;
184             }
185             boolean pass = false;
186             String s = auth.getValue();
187             int i = s.indexOf(" ");
188             if (i != -1) {
189                 String authtype = s.substring(0, i);
190                 if ("BASIC".equalsIgnoreCase(authtype)) {
191                     String creds = s.substring(i + 1, s.length());
192                     creds = EncodingUtil.getAsciiString(
193                         Base64.decodeBase64(
194                             EncodingUtil.getAsciiBytes(creds)));
195                     if (creds.equals("test:test")) {
196                         pass = true;    
197                     }
198                 }
199             }
200             if (!pass) {
201                 response.setStatusLine("HTTP/1.1 403 Forbidden");
202                 response.addHeader(challenge);
203                 response.setBodyString("Access forbidden");
204                 return true;
205             }
206             response.setStatusLine("HTTP/1.1 200 OK");
207             response.setBodyString("Authorization successful");
208             return true;
209         }
210     }
211 
212     public void testBasicAuthenticationWithNoCreds() throws IOException {
213         this.server.setHttpService(new BasicAuthService());
214         GetMethod httpget = new GetMethod("/test/");
215         try {
216             this.client.executeMethod(httpget);
217             assertNotNull(httpget.getStatusLine());
218             assertEquals(HttpStatus.SC_UNAUTHORIZED, httpget.getStatusLine().getStatusCode());
219             AuthState authstate = httpget.getHostAuthState();
220             assertNotNull(authstate.getAuthScheme());
221             assertTrue(authstate.getAuthScheme() instanceof BasicScheme);
222             assertEquals("test", authstate.getRealm());
223         } finally {
224             httpget.releaseConnection();
225         }
226     }
227 
228     public void testBasicAuthenticationWithNoRealm() {
229         String challenge = "Basic";
230         try {
231             AuthScheme authscheme = new BasicScheme();
232             authscheme.processChallenge(challenge);
233             fail("Should have thrown MalformedChallengeException");
234         } catch(MalformedChallengeException e) {
235             // expected
236         }
237     }
238 
239     public void testBasicAuthenticationWith88591Chars() throws Exception {
240         int[] germanChars = { 0xE4, 0x2D, 0xF6, 0x2D, 0xFc };
241         StringBuffer buffer = new StringBuffer();
242         for (int i = 0; i < germanChars.length; i++) {
243             buffer.append((char)germanChars[i]); 
244         }
245         
246         UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("dh", buffer.toString());
247         assertEquals("Basic ZGg65C32Lfw=", 
248             BasicScheme.authenticate(credentials, "ISO-8859-1"));
249     }
250     
251     public void testBasicAuthenticationWithDefaultCreds() throws Exception {
252         HttpState state = new HttpState();
253         state.setCredentials(new HttpAuthRealm(), new UsernamePasswordCredentials("test", "test"));
254         this.client.setState(state);
255         this.server.setHttpService(new BasicAuthService());
256         GetMethod httpget = new GetMethod("/test/");
257         try {
258             this.client.executeMethod(httpget);
259         } finally {
260             httpget.releaseConnection();
261         }
262         assertNotNull(httpget.getStatusLine());
263         assertEquals(HttpStatus.SC_OK, httpget.getStatusLine().getStatusCode());
264         Header auth = httpget.getRequestHeader("Authorization");
265         assertNotNull(auth);
266         String expected = "Basic " + EncodingUtil.getAsciiString(
267             Base64.encodeBase64(EncodingUtil.getAsciiBytes("test:test")));
268         assertEquals(expected, auth.getValue());
269         AuthState authstate = httpget.getHostAuthState();
270         assertNotNull(authstate.getAuthScheme());
271         assertTrue(authstate.getAuthScheme() instanceof BasicScheme);
272         assertEquals("test", authstate.getRealm());
273     }
274 
275     public void testBasicAuthentication() throws Exception {
276         HttpState state = new HttpState();
277         HttpAuthRealm realm = new HttpAuthRealm(
278             this.server.getLocalAddress(), 
279             this.server.getLocalPort(),
280             "test");
281         state.setCredentials(realm, new UsernamePasswordCredentials("test", "test"));
282         this.client.setState(state);
283         this.server.setHttpService(new BasicAuthService());
284         GetMethod httpget = new GetMethod("/test/");
285         try {
286             this.client.executeMethod(httpget);
287         } finally {
288             httpget.releaseConnection();
289         }
290         assertNotNull(httpget.getStatusLine());
291         assertEquals(HttpStatus.SC_OK, httpget.getStatusLine().getStatusCode());
292         Header auth = httpget.getRequestHeader("Authorization");
293         assertNotNull(auth);
294         String expected = "Basic " + EncodingUtil.getAsciiString(
295             Base64.encodeBase64(EncodingUtil.getAsciiBytes("test:test")));
296         assertEquals(expected, auth.getValue());
297         AuthState authstate = httpget.getHostAuthState();
298         assertNotNull(authstate.getAuthScheme());
299         assertTrue(authstate.getAuthScheme() instanceof BasicScheme);
300         assertEquals("test", authstate.getRealm());
301     }
302 
303     public void testBasicAuthenticationWithInvalidCredentials() throws Exception {
304         HttpState state = new HttpState();
305         HttpAuthRealm realm = new HttpAuthRealm(
306             this.server.getLocalAddress(), 
307             this.server.getLocalPort(),
308             "test");
309         state.setCredentials(realm, new UsernamePasswordCredentials("test", "stuff"));
310         this.client.setState(state);
311         this.server.setHttpService(new BasicAuthService());
312         GetMethod httpget = new GetMethod("/test/");
313         try {
314             this.client.executeMethod(httpget);
315         } finally {
316             httpget.releaseConnection();
317         }
318         assertNotNull(httpget.getStatusLine());
319         assertEquals(HttpStatus.SC_FORBIDDEN, httpget.getStatusLine().getStatusCode());
320         AuthState authstate = httpget.getHostAuthState();
321         assertNotNull(authstate.getAuthScheme());
322         assertTrue(authstate.getAuthScheme() instanceof BasicScheme);
323         assertEquals("test", authstate.getRealm());
324     }
325 
326     public void testBasicAuthenticationWithMutlipleRealms() throws Exception {
327         HttpState state = new HttpState();
328         HttpAuthRealm realm1 = new HttpAuthRealm(
329             this.server.getLocalAddress(), 
330             this.server.getLocalPort(),
331             "test");
332         HttpAuthRealm realm2 = new HttpAuthRealm(
333             this.server.getLocalAddress(), 
334             this.server.getLocalPort(),
335             "test2");
336         state.setCredentials(realm1, new UsernamePasswordCredentials("test","test"));
337         state.setCredentials(realm2, new UsernamePasswordCredentials("test2","test2"));
338         this.client.setState(state);
339         {
340             this.server.setHttpService(new BasicAuthService());
341             GetMethod httpget = new GetMethod("/test/");
342             try {
343                 this.client.executeMethod(httpget);
344             } finally {
345                 httpget.releaseConnection();
346             }
347             assertNotNull(httpget.getStatusLine());
348             assertEquals(HttpStatus.SC_OK, httpget.getStatusLine().getStatusCode());
349             Header auth = httpget.getRequestHeader("Authorization");
350             assertNotNull(auth);
351             String expected = "Basic " + EncodingUtil.getAsciiString(
352                 Base64.encodeBase64(EncodingUtil.getAsciiBytes("test:test")));
353             assertEquals(expected, auth.getValue());
354             AuthState authstate = httpget.getHostAuthState();
355             assertNotNull(authstate.getAuthScheme());
356             assertTrue(authstate.getAuthScheme() instanceof BasicScheme);
357             assertEquals("test", authstate.getRealm());
358         }
359         {
360             this.server.setHttpService(new BasicAuthService2());
361             GetMethod httpget = new GetMethod("/test2/");
362             try {
363                 this.client.executeMethod(httpget);
364             } finally {
365                 httpget.releaseConnection();
366             }
367             assertNotNull(httpget.getStatusLine());
368             assertEquals(HttpStatus.SC_OK, httpget.getStatusLine().getStatusCode());
369             Header auth = httpget.getRequestHeader("Authorization");
370             assertNotNull(auth);
371             String expected = "Basic " + EncodingUtil.getAsciiString(
372                 Base64.encodeBase64(EncodingUtil.getAsciiBytes("test2:test2")));
373             assertEquals(expected, auth.getValue());
374             AuthState authstate = httpget.getHostAuthState();
375             assertNotNull(authstate.getAuthScheme());
376             assertTrue(authstate.getAuthScheme() instanceof BasicScheme);
377             assertEquals("test2", authstate.getRealm());
378         }
379     }
380 
381     public void testPreemptiveAuthorizationTrueWithCreds() throws Exception {
382         HttpState state = new HttpState();
383         state.setCredentials(new HttpAuthRealm(), new UsernamePasswordCredentials("test", "test"));
384         this.client.setState(state);
385         this.client.getParams().setAuthenticationPreemptive(true);
386         this.server.setHttpService(new BasicAuthService());
387         GetMethod httpget = new GetMethod("/test/");
388         try {
389             this.client.executeMethod(httpget);
390         } finally {
391             httpget.releaseConnection();
392         }
393         assertNotNull(httpget.getStatusLine());
394         assertEquals(HttpStatus.SC_OK, httpget.getStatusLine().getStatusCode());
395         Header auth = httpget.getRequestHeader("Authorization");
396         assertNotNull(auth);
397         String expected = "Basic " + EncodingUtil.getAsciiString(
398             Base64.encodeBase64(EncodingUtil.getAsciiBytes("test:test")));
399         assertEquals(expected, auth.getValue());
400         AuthState authstate = httpget.getHostAuthState();
401         assertNotNull(authstate.getAuthScheme());
402         assertTrue(authstate.getAuthScheme() instanceof BasicScheme);
403         assertNull(authstate.getRealm());
404         assertTrue(authstate.isPreemptive());
405     }
406 
407     public void testBasicAuthenticationCaseInsensitivity() throws Exception {
408         HttpState state = new HttpState();
409         HttpAuthRealm realm = new HttpAuthRealm(
410             this.server.getLocalAddress(), 
411             this.server.getLocalPort(),
412             "test");
413         state.setCredentials(realm, new UsernamePasswordCredentials("test", "test"));
414         this.client.setState(state);
415         this.server.setHttpService(new BasicAuthService3());
416         GetMethod httpget = new GetMethod("/test/");
417         try {
418             this.client.executeMethod(httpget);
419         } finally {
420             httpget.releaseConnection();
421         }
422         assertNotNull(httpget.getStatusLine());
423         assertEquals(HttpStatus.SC_OK, httpget.getStatusLine().getStatusCode());
424         Header auth = httpget.getRequestHeader("Authorization");
425         assertNotNull(auth);
426         String expected = "Basic " + EncodingUtil.getAsciiString(
427             Base64.encodeBase64(EncodingUtil.getAsciiBytes("test:test")));
428         assertEquals(expected, auth.getValue());
429     }
430 
431 
432     public void testCustomAuthorizationHeader() throws Exception {
433         String authResponse = "Basic " + EncodingUtil.getAsciiString(
434             Base64.encodeBase64(EncodingUtil.getAsciiBytes("test:test")));
435         this.server.setHttpService(new BasicAuthService());
436         GetMethod httpget = new GetMethod("/test/");
437         httpget.addRequestHeader(new Header("Authorization", authResponse));
438         try {
439             this.client.executeMethod(httpget);
440         } finally {
441             httpget.releaseConnection();
442         }
443         assertNotNull(httpget.getStatusLine());
444         assertEquals(HttpStatus.SC_OK, httpget.getStatusLine().getStatusCode());
445     }
446 }