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