This is an automated email from the ASF dual-hosted git repository.
reschke pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
The following commit(s) were added to refs/heads/trunk by this push:
new a6f84489b9 oak-http: extract Authorization Field parsing and add test
coverage (#2981)
a6f84489b9 is described below
commit a6f84489b94be7f9d0bb03cc8270c5984cc01344
Author: Julian Reschke <[email protected]>
AuthorDate: Fri Jun 26 16:15:44 2026 +0200
oak-http: extract Authorization Field parsing and add test coverage (#2981)
---
.../jackrabbit/oak/http/AuthorizationField.java | 56 +++++++++++++++++
.../org/apache/jackrabbit/oak/http/OakServlet.java | 13 +---
.../oak/http/AuthorizationFieldTest.java | 72 ++++++++++++++++++++++
3 files changed, 129 insertions(+), 12 deletions(-)
diff --git
a/oak-http/src/main/java/org/apache/jackrabbit/oak/http/AuthorizationField.java
b/oak-http/src/main/java/org/apache/jackrabbit/oak/http/AuthorizationField.java
new file mode 100644
index 0000000000..c572e4a3ed
--- /dev/null
+++
b/oak-http/src/main/java/org/apache/jackrabbit/oak/http/AuthorizationField.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.http;
+
+import org.apache.jackrabbit.util.Base64;
+
+import javax.jcr.SimpleCredentials;
+import javax.security.auth.login.LoginException;
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+public class AuthorizationField {
+
+ private AuthorizationField() {
+ // no constructor
+ }
+
+ public static SimpleCredentials valueOf(Enumeration<String> values) throws
LoginException {
+ String field ;
+ try {
+ field = values.nextElement();
+ } catch (NoSuchElementException ex) {
+ throw new LoginException(ex.getMessage());
+ }
+
+ if (values.hasMoreElements()) {
+ throw new LoginException("Authorization field has multiple field
line values");
+ }
+
+ return parseCredentials(field);
+ }
+
+ private static SimpleCredentials parseCredentials(String fieldValue)
throws LoginException {
+ if (fieldValue.startsWith("Basic ")) {
+ String[] basic =
+ Base64.decode(fieldValue.substring("Basic
".length())).split(":");
+ return new SimpleCredentials(basic[0], basic[1].toCharArray());
+ } else {
+ throw new LoginException("Only Basic Authentication supported");
+ }
+ }
+}
diff --git
a/oak-http/src/main/java/org/apache/jackrabbit/oak/http/OakServlet.java
b/oak-http/src/main/java/org/apache/jackrabbit/oak/http/OakServlet.java
index c6bcd3bc7c..1e000c21b5 100644
--- a/oak-http/src/main/java/org/apache/jackrabbit/oak/http/OakServlet.java
+++ b/oak-http/src/main/java/org/apache/jackrabbit/oak/http/OakServlet.java
@@ -20,7 +20,6 @@ import java.io.IOException;
import java.util.Iterator;
import java.util.Map.Entry;
-import javax.jcr.Credentials;
import javax.jcr.NoSuchWorkspaceException;
import javax.jcr.SimpleCredentials;
import javax.security.auth.login.LoginException;
@@ -39,7 +38,6 @@ import org.apache.jackrabbit.oak.api.ContentSession;
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.commons.PathUtils;
-import org.apache.jackrabbit.util.Base64;
import org.apache.tika.mime.MediaType;
public class OakServlet extends HttpServlet {
@@ -68,16 +66,7 @@ public class OakServlet extends HttpServlet {
HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
- Credentials credentials = null;
-
- String authorization = request.getHeader("Authorization");
- if (authorization != null && authorization.startsWith("Basic ")) {
- String[] basic =
- Base64.decode(authorization.substring("Basic
".length())).split(":");
- credentials = new SimpleCredentials(basic[0],
basic[1].toCharArray());
- } else {
- throw new LoginException();
- }
+ SimpleCredentials credentials =
AuthorizationField.valueOf(request.getHeaders("Authorization"));
ContentSession session = repository.login(credentials, null);
try {
diff --git
a/oak-http/src/test/java/org/apache/jackrabbit/oak/http/AuthorizationFieldTest.java
b/oak-http/src/test/java/org/apache/jackrabbit/oak/http/AuthorizationFieldTest.java
new file mode 100644
index 0000000000..e2a3ab214d
--- /dev/null
+++
b/oak-http/src/test/java/org/apache/jackrabbit/oak/http/AuthorizationFieldTest.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.http;
+
+import org.junit.Test;
+
+import javax.jcr.SimpleCredentials;
+import javax.security.auth.login.LoginException;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+public class AuthorizationFieldTest {
+
+ @Test(expected = LoginException.class)
+ public void testNone() throws LoginException {
+ AuthorizationField.valueOf(Collections.enumeration(List.of()));
+ }
+
+ @Test(expected = LoginException.class)
+ public void testTwo() throws LoginException {
+ AuthorizationField.valueOf(Collections.enumeration(List.of("a", "b")));
+ }
+
+ @Test
+ public void testValid() throws LoginException {
+ String b64 =
Base64.getEncoder().encodeToString("foo:bar".getBytes(StandardCharsets.UTF_8));
+ SimpleCredentials credentials =
AuthorizationField.valueOf(Collections.enumeration(List.of("Basic " + b64)));
+ assertEquals("foo", credentials.getUserID());
+ assertEquals("bar", new String(credentials.getPassword()));
+ }
+
+ @Test(expected = ArrayIndexOutOfBoundsException.class) // BUG: OAK-12259
+ public void testInvalidBase64() throws LoginException {
+ String b64 =
Base64.getEncoder().encodeToString("foo:bar".getBytes(StandardCharsets.UTF_8));
+ SimpleCredentials credentials =
AuthorizationField.valueOf(Collections.enumeration(List.of("Basic dksjdkj" +
b64)));
+ assertEquals("foo", credentials.getUserID());
+ assertEquals("bar", new String(credentials.getPassword()));
+ }
+
+ @Test(expected = LoginException.class)
+ public void testNoScheme() throws LoginException {
+ String b64 =
Base64.getEncoder().encodeToString("foo:bar".getBytes(StandardCharsets.UTF_8));
+ AuthorizationField.valueOf(Collections.enumeration(List.of(b64)));
+ }
+
+ @Test
+ public void testColonInPassword() throws LoginException {
+ String b64 = "Basic " +
Base64.getEncoder().encodeToString("foo:bar:qux".getBytes(StandardCharsets.UTF_8));
+ SimpleCredentials credentials
=AuthorizationField.valueOf(Collections.enumeration(List.of(b64)));
+ assertEquals("foo", credentials.getUserID());
+ // BUG: OAK-12259
+ assertEquals("bar", new String(credentials.getPassword()));
+ }
+}
\ No newline at end of file