Repository: incubator-eagle
Updated Branches:
  refs/heads/master 446c22720 -> 164e844c1


[EAGLE-583] implement ldap authentication logic integrated with Basic 
Authentication

implement ldap authentication logic integrated with Basic Authentication

Author: anyway1021 <m...@apache.org>

Closes #649 from anyway1021/EAGLE-583.


Project: http://git-wip-us.apache.org/repos/asf/incubator-eagle/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-eagle/commit/164e844c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-eagle/tree/164e844c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-eagle/diff/164e844c

Branch: refs/heads/master
Commit: 164e844c1ec9e16b4228eddd5fb6a2ba8196e661
Parents: 446c227
Author: anyway1021 <m...@apache.org>
Authored: Tue Nov 15 18:37:10 2016 +0800
Committer: anyway1021 <m...@apache.org>
Committed: Tue Nov 15 18:37:10 2016 +0800

----------------------------------------------------------------------
 .../authenticator/LdapBasicAuthenticator.java   |  55 +++++++++-
 .../authentication/config/LdapSettings.java     | 110 +++++--------------
 .../src/main/resources/configuration.yml        |  31 +++---
 .../LdapBasicAuthenticatorTest.java             |  86 +++++++++++++++
 .../SimpleBasicAuthenticatorTest.java           |  71 ++++++++++++
 .../src/test/resources/configuration.yml        |  31 ++++--
 6 files changed, 270 insertions(+), 114 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/164e844c/eagle-server/src/main/java/org/apache/eagle/server/authentication/authenticator/LdapBasicAuthenticator.java
----------------------------------------------------------------------
diff --git 
a/eagle-server/src/main/java/org/apache/eagle/server/authentication/authenticator/LdapBasicAuthenticator.java
 
b/eagle-server/src/main/java/org/apache/eagle/server/authentication/authenticator/LdapBasicAuthenticator.java
index 87ebb34..14652c3 100644
--- 
a/eagle-server/src/main/java/org/apache/eagle/server/authentication/authenticator/LdapBasicAuthenticator.java
+++ 
b/eagle-server/src/main/java/org/apache/eagle/server/authentication/authenticator/LdapBasicAuthenticator.java
@@ -22,8 +22,18 @@ import io.dropwizard.auth.Authenticator;
 import io.dropwizard.auth.basic.BasicCredentials;
 import org.apache.eagle.common.authentication.User;
 import org.apache.eagle.server.authentication.config.LdapSettings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.naming.Context;
+import javax.naming.directory.InitialDirContext;
+import java.util.Hashtable;
 
 public class LdapBasicAuthenticator implements Authenticator<BasicCredentials, 
User> {
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(LdapBasicAuthenticator.class);
+    private static final String LDAP_LDAP_CTX_FACTORY_NAME = 
"com.sun.jndi.ldap.LdapCtxFactory";
+    private static final String LDAP_CONNECT_TIMEOUT_KEY = 
"com.sun.jndi.ldap.connect.timeout";
+    private static final String LDAP_READ_TIMEOUT_KEY = 
"com.sun.jndi.ldap.read.timeout";
     private LdapSettings settings = null;
 
     public LdapBasicAuthenticator(LdapSettings settings) {
@@ -31,11 +41,46 @@ public class LdapBasicAuthenticator implements 
Authenticator<BasicCredentials, U
     }
 
     public Optional<User> authenticate(BasicCredentials credentials) throws 
AuthenticationException {
-        // TODO need to implement ldap authentication logic
-        boolean pass = true;
-        if (pass) {
-            return Optional.of(new User("ldap.username"));
+        String sanitizedUsername = sanitizeUsername(credentials.getUsername());
+        try {
+            new InitialDirContext(getContextEnvironment(sanitizedUsername, 
credentials.getPassword()));
+            return Optional.of(new User(sanitizedUsername));
+        } catch (javax.naming.AuthenticationException ae) {
+            LOGGER.warn(String.format("Authentication failed for user[%s]: 
wrong username or password", sanitizedUsername));
+            return Optional.absent();
+        } catch (Exception e) {
+            throw new AuthenticationException(String.format("Error occurs 
while trying to authenticate for user[%s]: %s", sanitizedUsername, 
e.getMessage()), e);
         }
-        return Optional.absent();
     }
+
+    Hashtable<String, String> getContextEnvironment(String sanitizedUsername, 
String password) {
+        String providerUrl = settings.getProviderUrl();
+        if (providerUrl == null) {
+            throw new IllegalArgumentException("providerUrl of the ldap 
service shouldn't be null");
+        }
+
+        Hashtable<String, String> env = new Hashtable<>();
+        env.put(Context.INITIAL_CONTEXT_FACTORY, LDAP_LDAP_CTX_FACTORY_NAME);
+        env.put(Context.PROVIDER_URL, providerUrl);
+        env.put(LDAP_CONNECT_TIMEOUT_KEY, 
String.valueOf(settings.getConnectingTimeout().toMilliseconds()));
+        env.put(LDAP_READ_TIMEOUT_KEY, 
String.valueOf(settings.getReadingTimeout().toMilliseconds()));
+
+        String strategy = settings.getStrategy();
+        if (!"".equals(strategy)) {
+            env.put(Context.SECURITY_AUTHENTICATION, strategy);
+        }
+
+        env.put(Context.SECURITY_PRINCIPAL, 
comprisePrincipal(sanitizedUsername));
+        env.put(Context.SECURITY_CREDENTIALS, password);
+        return env;
+    }
+
+    String comprisePrincipal(String sanitizedUsername) {
+        return settings.getPrincipalTemplate().replaceAll("\\$\\{USERNAME\\}", 
sanitizedUsername);
+    }
+
+    String sanitizeUsername(String username) {
+        return username.replaceAll("[^a-zA-Z0-9_.]", "");
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/164e844c/eagle-server/src/main/java/org/apache/eagle/server/authentication/config/LdapSettings.java
----------------------------------------------------------------------
diff --git 
a/eagle-server/src/main/java/org/apache/eagle/server/authentication/config/LdapSettings.java
 
b/eagle-server/src/main/java/org/apache/eagle/server/authentication/config/LdapSettings.java
index 0d04645..6bb3303 100644
--- 
a/eagle-server/src/main/java/org/apache/eagle/server/authentication/config/LdapSettings.java
+++ 
b/eagle-server/src/main/java/org/apache/eagle/server/authentication/config/LdapSettings.java
@@ -16,127 +16,69 @@
  */
 package org.apache.eagle.server.authentication.config;
 
+import io.dropwizard.util.Duration;
 import org.codehaus.jackson.annotate.JsonProperty;
 
 public class LdapSettings {
-    private String uri = null;
-    private String userFilter = null;
-    private String groupFilter = null;
-    private String userNameAttribute = null;
-    private String groupNameAttribute = null;
-    private String groupMembershipAttribute = null;
-    private String groupClassName = null;
-    private String[] restrictToGroups = null;
-    private String connectTimeout = null;
-    private String readTimeout = null;
 
-    @JsonProperty
-    public String getUri() {
-        return uri;
-    }
-
-    @JsonProperty
-    public LdapSettings setUri(String uri) {
-        this.uri = uri;
-        return this;
-    }
-
-    @JsonProperty
-    public String getUserFilter() {
-        return userFilter;
-    }
-
-    @JsonProperty
-    public LdapSettings setUserFilter(String userFilter) {
-        this.userFilter = userFilter;
-        return this;
-    }
-
-    @JsonProperty
-    public String getGroupFilter() {
-        return groupFilter;
-    }
-
-    @JsonProperty
-    public LdapSettings setGroupFilter(String groupFilter) {
-        this.groupFilter = groupFilter;
-        return this;
-    }
-
-    @JsonProperty
-    public String getUserNameAttribute() {
-        return userNameAttribute;
-    }
-
-    @JsonProperty
-    public LdapSettings setUserNameAttribute(String userNameAttribute) {
-        this.userNameAttribute = userNameAttribute;
-        return this;
-    }
-
-    @JsonProperty
-    public String getGroupNameAttribute() {
-        return groupNameAttribute;
-    }
-
-    @JsonProperty
-    public LdapSettings setGroupNameAttribute(String groupNameAttribute) {
-        this.groupNameAttribute = groupNameAttribute;
-        return this;
-    }
+    private String providerUrl = "";
+    private String strategy = "";
+    private String principalTemplate = "";
+    private Duration connectingTimeout = Duration.parse("500ms");
+    private Duration readingTimeout = Duration.parse("500ms");
 
     @JsonProperty
-    public String getGroupMembershipAttribute() {
-        return groupMembershipAttribute;
+    public String getProviderUrl() {
+        return providerUrl;
     }
 
     @JsonProperty
-    public LdapSettings setGroupMembershipAttribute(String 
groupMembershipAttribute) {
-        this.groupMembershipAttribute = groupMembershipAttribute;
+    public LdapSettings setProviderUrl(String providerUrl) {
+        this.providerUrl = providerUrl;
         return this;
     }
 
     @JsonProperty
-    public String getGroupClassName() {
-        return groupClassName;
+    public String getPrincipalTemplate() {
+        return principalTemplate;
     }
 
     @JsonProperty
-    public LdapSettings setGroupClassName(String groupClassName) {
-        this.groupClassName = groupClassName;
+    public LdapSettings setPrincipalTemplate(String principalTemplate) {
+        this.principalTemplate = principalTemplate;
         return this;
     }
 
     @JsonProperty
-    public String[] getRestrictToGroups() {
-        return restrictToGroups;
+    public String getStrategy() {
+        return strategy;
     }
 
     @JsonProperty
-    public LdapSettings setRestrictToGroups(String[] restrictToGroups) {
-        this.restrictToGroups = restrictToGroups;
+    public LdapSettings setStrategy(String strategy) {
+        this.strategy = strategy;
         return this;
     }
 
     @JsonProperty
-    public String getConnectTimeout() {
-        return connectTimeout;
+    public Duration getConnectingTimeout() {
+        return connectingTimeout;
     }
 
     @JsonProperty
-    public LdapSettings setConnectTimeout(String connectTimeout) {
-        this.connectTimeout = connectTimeout;
+    public LdapSettings setConnectingTimeout(Duration connectingTimeout) {
+        this.connectingTimeout = connectingTimeout;
         return this;
     }
 
     @JsonProperty
-    public String getReadTimeout() {
-        return readTimeout;
+    public Duration getReadingTimeout() {
+        return readingTimeout;
     }
 
     @JsonProperty
-    public LdapSettings setReadTimeout(String readTimeout) {
-        this.readTimeout = readTimeout;
+    public LdapSettings setReadingTimeout(Duration readingTimeout) {
+        this.readingTimeout = readingTimeout;
         return this;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/164e844c/eagle-server/src/main/resources/configuration.yml
----------------------------------------------------------------------
diff --git a/eagle-server/src/main/resources/configuration.yml 
b/eagle-server/src/main/resources/configuration.yml
index 6090c4f..8d388b0 100644
--- a/eagle-server/src/main/resources/configuration.yml
+++ b/eagle-server/src/main/resources/configuration.yml
@@ -21,7 +21,6 @@ server:
     - type: http
       port: 9091
 
-
 # ---------------------------------------------
 # Eagle Authentication Configuration
 # ---------------------------------------------
@@ -54,15 +53,21 @@ auth:
 
   # for ldap authentication, effective only when auth.mode=ldap
   ldap:
-    uri: ldaps://ldap.server.address:636
-    userFilter: ou=x,dc=y,dc=z
-    groupFilter: ou=x,dc=y,dc=z
-    userNameAttribute: cn
-    groupNameAttribute: cn
-    groupMembershipAttribute: memberUid
-    groupClassName: posixGroup
-    restrictToGroups:
-      - user
-      - admin
-    connectTimeout: 500ms
-    readTimeout: 500ms
+    # url providing ldap service. By convention, the port for typical ldap 
service is 389, and ldap service over ssl
+    # uses port 636 with protocol "ldaps", which requires certificates 
pre-installed.
+    providerUrl: ldap://server.address.or.domain:port
+
+    # template string containing ${USERNAME} placeholder. This is designed for 
some orgs who don't use plain usernames
+    # to authenticate, e.g. they may use its members' email address as the 
username: ${USERNAME}@some.org. When username
+    # is supposed to be recognized originally, just configure this parameter 
as ${USERNAME}
+    principalTemplate: ${USERNAME}@maybe.email.suffix
+
+    # string of strategy used by ldap service. "simple" is usually supported 
in most circumstances, we can use it by
+    # default or leave it a blank string.
+    strategy: simple
+
+    # timeout expression for connecting to ldap service endpoint
+    connectingTimeout: 500ms
+
+    # timeout expression for reading from ldap service
+    readingTimeout: 500ms

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/164e844c/eagle-server/src/test/java/org/apache/eagle/server/authentication/authenticator/LdapBasicAuthenticatorTest.java
----------------------------------------------------------------------
diff --git 
a/eagle-server/src/test/java/org/apache/eagle/server/authentication/authenticator/LdapBasicAuthenticatorTest.java
 
b/eagle-server/src/test/java/org/apache/eagle/server/authentication/authenticator/LdapBasicAuthenticatorTest.java
new file mode 100644
index 0000000..492521f
--- /dev/null
+++ 
b/eagle-server/src/test/java/org/apache/eagle/server/authentication/authenticator/LdapBasicAuthenticatorTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.eagle.server.authentication.authenticator;
+
+import io.dropwizard.util.Duration;
+import org.apache.eagle.server.authentication.config.LdapSettings;
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.naming.Context;
+import java.util.Hashtable;
+
+public class LdapBasicAuthenticatorTest {
+
+    private static final String USERNAME_SUFFIX = "@some.emailbox.suffix";
+    private static final String USERNAME_TEMPLATE = "${USERNAME}" + 
USERNAME_SUFFIX;
+    private static final String LDAP_SERVICE_PROVIDER_URL = 
"ldap://some.address:port";;
+    private static final String STRATEGY_SIMPLE = "customized";
+    private static final String CONNECTING_TIMEOUT_VALUE = "500ms";
+    private static final String READING_TIMEOUT_VALUE = "800ms";
+    private static final String LDAP_CTX_FACTORY_NAME = 
"com.sun.jndi.ldap.LdapCtxFactory";
+    private static final String LDAP_CONNECT_TIMEOUT_KEY = 
"com.sun.jndi.ldap.connect.timeout";
+    private static final String LDAP_READ_TIMEOUT_KEY = 
"com.sun.jndi.ldap.read.timeout";
+    private static final LdapBasicAuthenticator AUTHENTICATOR_FOR_UTIL_METHODS 
= new LdapBasicAuthenticator(
+            new LdapSettings()
+                    .setProviderUrl(LDAP_SERVICE_PROVIDER_URL)
+                    .setPrincipalTemplate(USERNAME_TEMPLATE)
+                    .setStrategy(STRATEGY_SIMPLE)
+                    
.setConnectingTimeout(Duration.parse(CONNECTING_TIMEOUT_VALUE))
+                    .setReadingTimeout(Duration.parse(READING_TIMEOUT_VALUE))
+    );
+
+    @Test
+    public void testSanitizeUsername() {
+        String correctUsername = "userNAME_123.45Z";
+        String sanitized = 
AUTHENTICATOR_FOR_UTIL_METHODS.sanitizeUsername(correctUsername);
+        Assert.assertEquals(correctUsername, sanitized);
+
+        String incorrectUsername = 
"userNAME-~!@#$%^&777*()_+-=`[]\\{}|;':\",./<>?ä½ ";
+        sanitized = 
AUTHENTICATOR_FOR_UTIL_METHODS.sanitizeUsername(incorrectUsername);
+        System.out.println(sanitized);
+        Assert.assertEquals("userNAME777_.", sanitized);
+    }
+
+    @Test
+    public void testComprisePrincipal() {
+        String username = "my.userNAME_123";
+        String principal = 
AUTHENTICATOR_FOR_UTIL_METHODS.comprisePrincipal(username);
+        Assert.assertEquals(username+USERNAME_SUFFIX, principal);
+    }
+
+    @Test
+    public void testGetContextEnvironment() {
+        String username = "username";
+        String secret_phrase = "secret-phrase";
+        Hashtable<String, String> env = 
AUTHENTICATOR_FOR_UTIL_METHODS.getContextEnvironment(username, secret_phrase);
+
+        Assert.assertEquals("unexpected ldap context factory name", 
LDAP_CTX_FACTORY_NAME, env.get(Context.INITIAL_CONTEXT_FACTORY));
+        Assert.assertEquals("unexpected ldap serivce provider url", 
LDAP_SERVICE_PROVIDER_URL, env.get(Context.PROVIDER_URL));
+        Assert.assertEquals("unexpected connecting timeout value", 
String.valueOf(Duration.parse(CONNECTING_TIMEOUT_VALUE).toMilliseconds()), 
env.get(LDAP_CONNECT_TIMEOUT_KEY));
+        Assert.assertEquals("unexpected reading timeout value", 
String.valueOf(Duration.parse(READING_TIMEOUT_VALUE).toMilliseconds()), 
env.get(LDAP_READ_TIMEOUT_KEY));
+        Assert.assertEquals("unexpected username", username+USERNAME_SUFFIX, 
env.get(Context.SECURITY_PRINCIPAL));
+        Assert.assertEquals("unexpected secret credentials", secret_phrase, 
env.get(Context.SECURITY_CREDENTIALS));
+        Assert.assertEquals("unexpected strategy", STRATEGY_SIMPLE, 
env.get(Context.SECURITY_AUTHENTICATION));
+
+        // check strategy while it's configured as ""
+        LdapBasicAuthenticator blankStrategyAuthenticator = new 
LdapBasicAuthenticator(new LdapSettings().setStrategy(""));
+        String strategyMaybeBlank = 
blankStrategyAuthenticator.getContextEnvironment(username, 
secret_phrase).get(Context.SECURITY_AUTHENTICATION);
+        Assert.assertNull("unexpected strategy", strategyMaybeBlank);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/164e844c/eagle-server/src/test/java/org/apache/eagle/server/authentication/authenticator/SimpleBasicAuthenticatorTest.java
----------------------------------------------------------------------
diff --git 
a/eagle-server/src/test/java/org/apache/eagle/server/authentication/authenticator/SimpleBasicAuthenticatorTest.java
 
b/eagle-server/src/test/java/org/apache/eagle/server/authentication/authenticator/SimpleBasicAuthenticatorTest.java
new file mode 100644
index 0000000..e896a7c
--- /dev/null
+++ 
b/eagle-server/src/test/java/org/apache/eagle/server/authentication/authenticator/SimpleBasicAuthenticatorTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.eagle.server.authentication.authenticator;
+
+import com.google.common.base.Optional;
+import io.dropwizard.auth.AuthenticationException;
+import io.dropwizard.auth.basic.BasicCredentials;
+import org.apache.eagle.common.authentication.User;
+import org.apache.eagle.server.authentication.config.SimpleSettings;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class SimpleBasicAuthenticatorTest {
+
+    private static final String TEST_USERNAME = "normal-username";
+    private static final String TEST_SECRET_PHRASE = "secret-phrase";
+    private static final String TEST_UNEXISTING_USERNAME = 
"unexisting-username";
+    private static final String TEST_WRONG_SECRET_PHRASE = 
"wrong-secret-phrase";
+    private static SimpleBasicAuthenticator authenticator = new 
SimpleBasicAuthenticator(new 
SimpleSettings().setUsername(TEST_USERNAME).setPassword(TEST_SECRET_PHRASE));
+
+    @Test
+    public void testNormal() {
+        try {
+            BasicCredentials credentials = new BasicCredentials(TEST_USERNAME, 
TEST_SECRET_PHRASE);
+            Optional<User> result = authenticator.authenticate(credentials);
+            Assert.assertTrue("result isn't present when passed correct 
credentials", result.isPresent());
+            User user = result.get();
+            Assert.assertEquals("authenticated user is not expected", 
TEST_USERNAME, user.getName());
+        }
+        catch (AuthenticationException e) {
+            Assert.fail("unexpected error occurs: "+e.getMessage());
+        }
+    }
+
+    @Test
+    public void testUnexistingUsername() {
+        try {
+            Optional<User> result = authenticator.authenticate(new 
BasicCredentials(TEST_UNEXISTING_USERNAME, TEST_SECRET_PHRASE));
+            Assert.assertFalse("result is present when passed unexisting 
username", result.isPresent());
+        }
+        catch (AuthenticationException e) {
+            Assert.fail("unexpected error occurs: "+e.getMessage());
+        }
+    }
+
+    @Test
+    public void testWrongPassword() {
+        try {
+            Optional<User> result = authenticator.authenticate(new 
BasicCredentials(TEST_USERNAME, TEST_WRONG_SECRET_PHRASE));
+            Assert.assertFalse("result is present when passed wrong password", 
result.isPresent());
+        }
+        catch (AuthenticationException e) {
+            Assert.fail("unexpected error occurs: "+e.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/164e844c/eagle-server/src/test/resources/configuration.yml
----------------------------------------------------------------------
diff --git a/eagle-server/src/test/resources/configuration.yml 
b/eagle-server/src/test/resources/configuration.yml
index 6795aac..8d388b0 100644
--- a/eagle-server/src/test/resources/configuration.yml
+++ b/eagle-server/src/test/resources/configuration.yml
@@ -12,6 +12,7 @@
 # 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.
+
 server:
   applicationConnectors:
     - type: http
@@ -52,15 +53,21 @@ auth:
 
   # for ldap authentication, effective only when auth.mode=ldap
   ldap:
-    uri: ldaps://ldap.server.address:636
-    userFilter: ou=x,dc=y,dc=z
-    groupFilter: ou=x,dc=y,dc=z
-    userNameAttribute: cn
-    groupNameAttribute: cn
-    groupMembershipAttribute: memberUid
-    groupClassName: posixGroup
-    restrictToGroups:
-      - user
-      - admin
-    connectTimeout: 500ms
-    readTimeout: 500ms
+    # url providing ldap service. By convention, the port for typical ldap 
service is 389, and ldap service over ssl
+    # uses port 636 with protocol "ldaps", which requires certificates 
pre-installed.
+    providerUrl: ldap://server.address.or.domain:port
+
+    # template string containing ${USERNAME} placeholder. This is designed for 
some orgs who don't use plain usernames
+    # to authenticate, e.g. they may use its members' email address as the 
username: ${USERNAME}@some.org. When username
+    # is supposed to be recognized originally, just configure this parameter 
as ${USERNAME}
+    principalTemplate: ${USERNAME}@maybe.email.suffix
+
+    # string of strategy used by ldap service. "simple" is usually supported 
in most circumstances, we can use it by
+    # default or leave it a blank string.
+    strategy: simple
+
+    # timeout expression for connecting to ldap service endpoint
+    connectingTimeout: 500ms
+
+    # timeout expression for reading from ldap service
+    readingTimeout: 500ms

Reply via email to