From 81bc6cd81b347f178a1a2b85e33b7101d1241c41 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Mon, 05 Oct 2026 12:38:31 +0000
Subject: [PATCH] [#1155] Make the rest2ldap bind templates and HTTP Basic credentials work as documented (#1165)

---
 opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/CredentialExtractors.java |   22 ++++++++++++++++------
 1 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/CredentialExtractors.java b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/CredentialExtractors.java
index 50d5e9a..e576673 100644
--- a/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/CredentialExtractors.java
+++ b/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/authz/CredentialExtractors.java
@@ -12,6 +12,7 @@
  * information: "Portions copyright [year] [name of copyright owner]".
  *
  * Copyright 2016 ForgeRock AS.
+ * Portions Copyright 2026 3A Systems, LLC.
  */
 package org.forgerock.opendj.rest2ldap.authz;
 
@@ -98,6 +99,9 @@
         /** Reference to the HttpBasicExtractor Singleton. */
         public static final HttpBasicExtractor INSTANCE = new HttpBasicExtractor();
 
+        /** The authentication scheme and the space which separates it from the credentials. */
+        private static final String BASIC_SCHEME = "basic ";
+
         private HttpBasicExtractor() { }
 
         @Override
@@ -113,17 +117,23 @@
         }
 
         private Pair<String, String> parseUsernamePassword(String authHeader) {
-            if (authHeader != null && (authHeader.toLowerCase().startsWith("basic"))) {
+            if (authHeader != null && authHeader.regionMatches(true, 0, BASIC_SCHEME, 0, BASIC_SCHEME.length())) {
                 // We received authentication info
                 // Example received header:
                 // "Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
-                final String base64UserCredentials = authHeader.substring("basic".length() + 1);
+                final String base64UserCredentials = authHeader.substring(BASIC_SCHEME.length());
                 // Example usage of base64:
                 // Base64("Aladdin:open sesame") = "QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
-                final String userCredentials = new String(Base64.decode(base64UserCredentials));
-                String[] split = userCredentials.split(":");
-                if (split.length == 2) {
-                    return Pair.of(split[0], split[1]);
+                final byte[] decoded = Base64.decode(base64UserCredentials);
+                if (decoded == null) {
+                    // Not a multiple of 4 characters long once the characters outside base64 are dropped.
+                    return null;
+                }
+                final String userCredentials = new String(decoded);
+                // RFC 7617 section 2: the user-id cannot contain a colon, the password can.
+                final int colon = userCredentials.indexOf(':');
+                if (colon >= 0) {
+                    return Pair.of(userCredentials.substring(0, colon), userCredentials.substring(colon + 1));
                 }
             }
             return null;

--
Gitblit v1.10.0