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.http.impl.auth;
28
29 import java.io.ByteArrayInputStream;
30 import java.io.ByteArrayOutputStream;
31 import java.io.ObjectInputStream;
32 import java.io.ObjectOutputStream;
33 import java.nio.charset.StandardCharsets;
34 import java.util.Base64;
35 import java.util.List;
36
37 import org.apache.hc.client5.http.auth.AuthChallenge;
38 import org.apache.hc.client5.http.auth.AuthScheme;
39 import org.apache.hc.client5.http.auth.AuthScope;
40 import org.apache.hc.client5.http.auth.AuthenticationException;
41 import org.apache.hc.client5.http.auth.ChallengeType;
42 import org.apache.hc.client5.http.auth.CredentialsProvider;
43 import org.apache.hc.client5.http.auth.StandardAuthScheme;
44 import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
45 import org.apache.hc.core5.http.HttpHost;
46 import org.apache.hc.core5.http.HttpRequest;
47 import org.apache.hc.core5.http.ParseException;
48 import org.apache.hc.core5.http.message.BasicHttpRequest;
49 import org.apache.hc.core5.http.message.ParserCursor;
50 import org.apache.hc.core5.util.CharArrayBuffer;
51 import org.junit.jupiter.api.Assertions;
52 import org.junit.jupiter.api.Test;
53
54
55
56
57 public class TestBasicScheme {
58 private static final Base64.Encoder BASE64_ENC = Base64.getEncoder();
59
60 private static AuthChallenge parse(final String s) throws ParseException {
61 final CharArrayBuffer buffer = new CharArrayBuffer(s.length());
62 buffer.append(s);
63 final ParserCursor cursor = new ParserCursor(0, buffer.length());
64 final List<AuthChallenge> authChallenges = AuthChallengeParser.INSTANCE.parse(ChallengeType.TARGET, buffer, cursor);
65 Assertions.assertEquals(1, authChallenges.size());
66 return authChallenges.get(0);
67 }
68
69 @Test
70 public void testBasicAuthenticationEmptyChallenge() throws Exception {
71 final String challenge = StandardAuthScheme.BASIC;
72 final AuthChallenge authChallenge = parse(challenge);
73 final AuthScheme authscheme = new BasicScheme();
74 authscheme.processChallenge(authChallenge, null);
75 Assertions.assertNull(authscheme.getRealm());
76 }
77
78 @Test
79 public void testBasicAuthentication() throws Exception {
80 final AuthChallenge authChallenge = parse("Basic realm=\"test\"");
81
82 final BasicScheme authscheme = new BasicScheme();
83 authscheme.processChallenge(authChallenge, null);
84
85 final HttpHost host = new HttpHost("somehost", 80);
86 final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
87 .add(new AuthScope(host, "test", null), "testuser", "testpass".toCharArray())
88 .build();
89
90 final HttpRequest request = new BasicHttpRequest("GET", "/");
91 Assertions.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
92 final String authResponse = authscheme.generateAuthResponse(host, request, null);
93
94 final byte[] testCreds = "testuser:testpass".getBytes(StandardCharsets.US_ASCII);
95
96 final String expected = "Basic " + BASE64_ENC.encodeToString(testCreds);
97
98 Assertions.assertEquals(expected, authResponse);
99 Assertions.assertEquals("test", authscheme.getRealm());
100 Assertions.assertTrue(authscheme.isChallengeComplete());
101 Assertions.assertFalse(authscheme.isConnectionBased());
102 }
103
104 static final String TEST_UTF8_PASSWORD = "123\u00A3";
105
106 @Test
107 public void testBasicAuthenticationDefaultCharset() throws Exception {
108 final HttpHost host = new HttpHost("somehost", 80);
109 final UsernamePasswordCredentials creds = new UsernamePasswordCredentials("test", TEST_UTF8_PASSWORD.toCharArray());
110 final BasicScheme authscheme = new BasicScheme();
111 final HttpRequest request = new BasicHttpRequest("GET", "/");
112 authscheme.initPreemptive(creds);
113 final String authResponse = authscheme.generateAuthResponse(host, request, null);
114 Assertions.assertEquals("Basic dGVzdDoxMjPCow==", authResponse);
115 }
116
117 @Test
118 public void testBasicAuthenticationDefaultCharsetUTF8() throws Exception {
119 final HttpHost host = new HttpHost("somehost", 80);
120 final UsernamePasswordCredentials creds = new UsernamePasswordCredentials("test", TEST_UTF8_PASSWORD.toCharArray());
121 final BasicScheme authscheme = new BasicScheme();
122 final HttpRequest request = new BasicHttpRequest("GET", "/");
123 authscheme.initPreemptive(creds);
124 final String authResponse = authscheme.generateAuthResponse(host, request, null);
125 Assertions.assertEquals("Basic dGVzdDoxMjPCow==", authResponse);
126 }
127
128 @Test
129 public void testBasicAuthenticationWithCharset() throws Exception {
130 final AuthChallenge authChallenge = parse("Basic realm=\"test\", charset=\"utf-8\"");
131
132 final BasicScheme authscheme = new BasicScheme();
133 authscheme.processChallenge(authChallenge, null);
134
135 final HttpHost host = new HttpHost("somehost", 80);
136 final CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
137 .add(new AuthScope(host, "test", null), "test", TEST_UTF8_PASSWORD.toCharArray())
138 .build();
139
140 final HttpRequest request = new BasicHttpRequest("GET", "/");
141 Assertions.assertTrue(authscheme.isResponseReady(host, credentialsProvider, null));
142 final String authResponse = authscheme.generateAuthResponse(host, request, null);
143 Assertions.assertEquals("Basic dGVzdDoxMjPCow==", authResponse);
144 Assertions.assertEquals("test", authscheme.getRealm());
145 Assertions.assertTrue(authscheme.isChallengeComplete());
146 Assertions.assertFalse(authscheme.isConnectionBased());
147 }
148
149 @Test
150 public void testSerialization() throws Exception {
151 final AuthChallenge authChallenge = parse("Basic realm=\"test\"");
152
153 final BasicScheme basicScheme = new BasicScheme();
154 basicScheme.processChallenge(authChallenge, null);
155
156 final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
157 final ObjectOutputStream out = new ObjectOutputStream(buffer);
158 out.writeObject(basicScheme);
159 out.flush();
160 final byte[] raw = buffer.toByteArray();
161 final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(raw));
162 final BasicScheme authScheme = (BasicScheme) in.readObject();
163
164 Assertions.assertEquals(basicScheme.getName(), authScheme.getName());
165 Assertions.assertEquals(basicScheme.getRealm(), authScheme.getRealm());
166 Assertions.assertEquals(basicScheme.isChallengeComplete(), authScheme.isChallengeComplete());
167 }
168
169 @Test
170 public void testSerializationUnchallenged() throws Exception {
171 final BasicScheme basicScheme = new BasicScheme();
172
173 final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
174 final ObjectOutputStream out = new ObjectOutputStream(buffer);
175 out.writeObject(basicScheme);
176 out.flush();
177 final byte[] raw = buffer.toByteArray();
178 final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(raw));
179 final BasicScheme authScheme = (BasicScheme) in.readObject();
180
181 Assertions.assertEquals(basicScheme.getName(), authScheme.getName());
182 Assertions.assertEquals(basicScheme.getRealm(), authScheme.getRealm());
183 Assertions.assertEquals(basicScheme.isChallengeComplete(), authScheme.isChallengeComplete());
184 }
185
186 @Test
187 public void testBasicAuthenticationUserCredentialsMissing() throws Exception {
188 final BasicScheme authscheme = new BasicScheme();
189 final HttpHost host = new HttpHost("somehost", 80);
190 final HttpRequest request = new BasicHttpRequest("GET", "/");
191 Assertions.assertThrows(AuthenticationException.class, () -> authscheme.generateAuthResponse(host, request, null));
192 }
193
194 @Test
195 public void testBasicAuthenticationUsernameWithBlank() throws Exception {
196 final BasicScheme authscheme = new BasicScheme();
197 final HttpHost host = new HttpHost("somehost", 80);
198 final HttpRequest request = new BasicHttpRequest("GET", "/");
199 authscheme.initPreemptive(new UsernamePasswordCredentials("blah blah", null));
200 authscheme.generateAuthResponse(host, request, null);
201 }
202
203 @Test
204 public void testBasicAuthenticationUsernameWithTab() throws Exception {
205 final BasicScheme authscheme = new BasicScheme();
206 final HttpHost host = new HttpHost("somehost", 80);
207 final HttpRequest request = new BasicHttpRequest("GET", "/");
208 authscheme.initPreemptive(new UsernamePasswordCredentials("blah\tblah", null));
209 Assertions.assertThrows(AuthenticationException.class, () -> authscheme.generateAuthResponse(host, request, null));
210 }
211
212 @Test
213 public void testBasicAuthenticationUsernameWithColon() throws Exception {
214 final BasicScheme authscheme = new BasicScheme();
215 final HttpHost host = new HttpHost("somehost", 80);
216 final HttpRequest request = new BasicHttpRequest("GET", "/");
217 authscheme.initPreemptive(new UsernamePasswordCredentials("blah:blah", null));
218 Assertions.assertThrows(AuthenticationException.class, () -> authscheme.generateAuthResponse(host, request, null));
219 }
220
221 @Test
222 public void testBasicAuthenticationPasswordWithControlCharacters() throws Exception {
223 final BasicScheme authscheme = new BasicScheme();
224 final HttpHost host = new HttpHost("somehost", 80);
225 final HttpRequest request = new BasicHttpRequest("GET", "/");
226
227
228 final char[] password = new char[]{'p', 'a', 's', 's', 0x1F, 'w', 'o', 'r', 'd'};
229 authscheme.initPreemptive(new UsernamePasswordCredentials("username", password));
230
231
232 Assertions.assertThrows(AuthenticationException.class, () -> authscheme.generateAuthResponse(host, request, null));
233 }
234
235 }