You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dlab.apache.org by bh...@apache.org on 2019/03/19 15:20:13 UTC

[incubator-dlab] 01/01: EPMCDLAB-000 refactored ldap authentication

This is an automated email from the ASF dual-hosted git repository.

bhliva pushed a commit to branch ldab_refactored
in repository https://gitbox.apache.org/repos/asf/incubator-dlab.git

commit 9260408088fd9a46f0377055c21a329ccc78b6e7
Author: bhliva <bo...@epam.com>
AuthorDate: Tue Jan 29 17:16:13 2019 +0200

    EPMCDLAB-000 refactored ldap authentication
---
 .../main/java/com/epam/dlab/auth/UserInfoDAO.java  |  11 +-
 .../epam/dlab/auth/UserVerificationService.java    |   2 +-
 .../aws/service/AwsUserVerificationService.java    |  16 +-
 .../auth/azure/AzureAuthenticationResource.java    |  10 +-
 services/security-service/pom.xml                  |   6 +
 services/security-service/security.yml             | 112 +++--------
 .../dlab/auth/SecurityServiceConfiguration.java    |  37 +++-
 .../epam/dlab/auth/core/CacheableReference.java    |  53 -----
 .../epam/dlab/auth/core/DlabLdapConnection.java    |   2 +-
 .../dlab/auth/core/DlabLdapConnectionFactory.java  |  48 +++++
 .../com/epam/dlab/auth/core/LdapFilterCache.java   |  78 -------
 .../java/com/epam/dlab/auth/core/LoginCache.java   |  82 --------
 .../com/epam/dlab/auth/core/LoginConveyor.java     |  66 ------
 .../java/com/epam/dlab/auth/core/LoginStep.java    |  46 -----
 .../com/epam/dlab/auth/core/UserInfoBuilder.java   | 196 ------------------
 .../java/com/epam/dlab/auth/dao/LdapUserDAO.java   | 223 ++-------------------
 .../com/epam/dlab/auth/dao/LdapUserDAOImpl.java    | 164 +++++++++++++++
 .../main/java/com/epam/dlab/auth/dao/Request.java  | 115 ++---------
 .../epam/dlab/auth/dao/SearchRequestBuilder.java   |  25 ---
 .../epam/dlab/auth/dao/UserInfoDAODumbImpl.java    |   6 +-
 .../epam/dlab/auth/dao/UserInfoDAOMongoImpl.java   |  82 ++++----
 .../dlab/auth/dao/filter/SearchResultMapper.java   |  30 ---
 .../auth/dao/filter/SearchResultProcessor.java     |  67 -------
 .../com/epam/dlab/auth/dao/script/DeepMap.java     |  56 ------
 .../epam/dlab/auth/dao/script/ScriptHolder.java    |  58 ------
 .../dao/script/SearchResultToDictionaryMapper.java |  97 ---------
 .../auth/modules/AwsSecurityServiceModule.java     |   4 +-
 .../auth/modules/AzureSecurityServiceModule.java   |   4 +-
 .../auth/modules/GcpSecurityServiceModule.java     |   4 +-
 .../dlab/auth/modules/SecurityServiceModule.java   |  13 +-
 .../SynchronousLdapAuthenticationResource.java     |  77 +++++++
 .../SynchronousLdapAuthenticationService.java      | 183 -----------------
 .../dlab/auth/service/AuthenticationService.java   |  33 +++
 .../service/impl/LdapAuthenticationService.java    |  82 ++++++++
 .../test/java/com/epam/dlab/auth/aws/AwsTest.java  |  77 -------
 .../com/epam/dlab/auth/core/LoginConveyorTest.java | 130 ------------
 .../dlab/auth/dao/script/ScriptHolderTest.java     |  64 ------
 .../java/com/epam/dlab/auth/ldap/AuthTest.java     |  28 ---
 .../java/com/epam/dlab/auth/ldap/BasicTest.java    | 115 -----------
 .../java/com/epam/dlab/auth/ldap/JsonTest.java     |  83 --------
 .../java/com/epam/dlab/auth/ldap/ScriptList.java   |  75 -------
 .../impl/LdapAuthenticationServiceTest.java        | 138 +++++++++++++
 42 files changed, 717 insertions(+), 2081 deletions(-)

diff --git a/services/dlab-auth-common/src/main/java/com/epam/dlab/auth/UserInfoDAO.java b/services/dlab-auth-common/src/main/java/com/epam/dlab/auth/UserInfoDAO.java
index d7c0bbb..931a050 100644
--- a/services/dlab-auth-common/src/main/java/com/epam/dlab/auth/UserInfoDAO.java
+++ b/services/dlab-auth-common/src/main/java/com/epam/dlab/auth/UserInfoDAO.java
@@ -13,17 +13,18 @@
  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 com.epam.dlab.auth;
 
+import java.util.Optional;
+
 public interface UserInfoDAO {
-    UserInfo getUserInfoByAccessToken(String accessToken);
+	Optional<UserInfo> getUserInfoByAccessToken(String accessToken);
 
-    void updateUserInfoTTL(String accessToken, UserInfo ui);
+	void updateUserInfoTTL(String accessToken, UserInfo ui);
 
-    void deleteUserInfo(String accessToken);
+	void deleteUserInfo(String accessToken);
 
-    void saveUserInfo(UserInfo ui);
+	void saveUserInfo(UserInfo ui);
 }
diff --git a/services/dlab-auth-common/src/main/java/com/epam/dlab/auth/UserVerificationService.java b/services/dlab-auth-common/src/main/java/com/epam/dlab/auth/UserVerificationService.java
index 0c9daac..7ceccae 100644
--- a/services/dlab-auth-common/src/main/java/com/epam/dlab/auth/UserVerificationService.java
+++ b/services/dlab-auth-common/src/main/java/com/epam/dlab/auth/UserVerificationService.java
@@ -23,5 +23,5 @@ package com.epam.dlab.auth;
 @FunctionalInterface
 public interface UserVerificationService {
 
-	void verify(String username, UserInfo userInfo);
+	void verify(UserInfo userInfo);
 }
diff --git a/services/security-aws/src/main/java/com/epam/dlab/auth/aws/service/AwsUserVerificationService.java b/services/security-aws/src/main/java/com/epam/dlab/auth/aws/service/AwsUserVerificationService.java
index 9224755..c66f1f8 100644
--- a/services/security-aws/src/main/java/com/epam/dlab/auth/aws/service/AwsUserVerificationService.java
+++ b/services/security-aws/src/main/java/com/epam/dlab/auth/aws/service/AwsUserVerificationService.java
@@ -38,15 +38,15 @@ public class AwsUserVerificationService implements UserVerificationService {
 	}
 
 	@Override
-	public void verify(String username, UserInfo userInfo) {
-		verifyAwsUser(username, userInfo);
-		verifyAwsKeys(username, userInfo);
+	public void verify(UserInfo userInfo) {
+		verifyAwsUser(userInfo);
+		verifyAwsKeys(userInfo);
 	}
 
 
-	private User verifyAwsUser(String username, UserInfo userInfo) {
+	private User verifyAwsUser(UserInfo userInfo) {
 		try {
-			User awsUser = awsUserDAO.getAwsUser(username);
+			User awsUser = awsUserDAO.getAwsUser(userInfo.getName());
 			if (awsUser != null) {
 				userInfo.setAwsUser(true);
 				return awsUser;
@@ -58,16 +58,16 @@ public class AwsUserVerificationService implements UserVerificationService {
 		}
 	}
 
-	private List<AccessKeyMetadata> verifyAwsKeys(String username, UserInfo userInfo) {
+	private List<AccessKeyMetadata> verifyAwsKeys(UserInfo userInfo) {
 
 		userInfo.getKeys().clear();
 
 		try {
-			List<AccessKeyMetadata> keys = awsUserDAO.getAwsAccessKeys(username);
+			List<AccessKeyMetadata> keys = awsUserDAO.getAwsAccessKeys(userInfo.getName());
 			if (keys == null || keys.isEmpty()
 					|| keys.stream().noneMatch(k -> "Active".equalsIgnoreCase(k.getStatus()))) {
 
-				throw new DlabException("Cannot get aws access key for user " + username);
+				throw new DlabException("Cannot get aws access key for user " + userInfo.getName());
 			}
 			keys.forEach(e -> userInfo.addKey(e.getAccessKeyId(), e.getStatus()));
 
diff --git a/services/security-azure/src/main/java/com/epam/dlab/auth/azure/AzureAuthenticationResource.java b/services/security-azure/src/main/java/com/epam/dlab/auth/azure/AzureAuthenticationResource.java
index db58e07..622d432 100644
--- a/services/security-azure/src/main/java/com/epam/dlab/auth/azure/AzureAuthenticationResource.java
+++ b/services/security-azure/src/main/java/com/epam/dlab/auth/azure/AzureAuthenticationResource.java
@@ -44,6 +44,7 @@ import java.io.IOException;
 import java.net.URI;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Optional;
 
 /**
  * Used to authenticate users against Azure Active Directory
@@ -105,16 +106,15 @@ public class AzureAuthenticationResource<C extends Configuration> extends Abstra
 	public UserInfo getUserInfo(String accessToken, @Context HttpServletRequest request) {
 		String remoteIp = request.getRemoteAddr();
 
-		UserInfo ui = userInfoDao.getUserInfoByAccessToken(accessToken);
+		final Optional<UserInfo> ui = userInfoDao.getUserInfoByAccessToken(accessToken);
 
-		if (ui != null) {
-			ui = ui.withToken(accessToken);
-			userInfoDao.updateUserInfoTTL(accessToken, ui);
+		if (ui.isPresent()) {
+			userInfoDao.updateUserInfoTTL(accessToken, ui.get().withToken(accessToken));
 			log.debug("restored UserInfo from DB {}", ui);
 		}
 
 		log.debug("Authorized {} {} {}", accessToken, ui, remoteIp);
-		return ui;
+		return ui.get().withToken(accessToken);
 	}
 
 	/**
diff --git a/services/security-service/pom.xml b/services/security-service/pom.xml
index 468c324..e68370b 100644
--- a/services/security-service/pom.xml
+++ b/services/security-service/pom.xml
@@ -123,6 +123,12 @@ limitations under the License.
             <artifactId>dlab-utils</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>${org.mockito.version}</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/services/security-service/security.yml b/services/security-service/security.yml
index aa294e3..c83ca77 100644
--- a/services/security-service/security.yml
+++ b/services/security-service/security.yml
@@ -30,95 +30,29 @@ useLdapBindTemplate: true
 ldapBindTemplate: uid=%s,LDAP_OU,LDAP_DN
 ldapBindAttribute: uid
 ldapSearchAttribute: uid
-ldapSearch:
-  - name: userLookUp
-    cache: true
-    expirationTimeMsec: 600000
-    scope: SUBTREE
-    attributes:
-      - cn
-      - mail
-      - uid
-      - gidNumber
-    timeLimit: 0
-    base: LDAP_DN
-    filter: "(&(objectClass=inetOrgPerson)(uid=%uid%))"
-  - name: userInfo
-    cache: true
-    expirationTimeMsec: 600000
-    scope: SUBTREE
-    attributes:
-      - cn
-      - gidNumber
-    timeLimit: 0
-    base: LDAP_DN
-    filter: "(&(objectClass=inetOrgPerson)(uid=%uid%))"
-    searchResultProcessor:
-      language: python
-#      path: c:\tmp\enrich.py
-      code: |
-        def enrichUserInfo(ui,context):
-          name = ui.getName()
-          key = context['key'].lower()
-          userInfo=context['userInfo']
-          if not key in userInfo:
-            raise Exception('Python LDAP UserInfo not found for '+key)
-          uid= userInfo[key]
-          cn = context['userInfo'][key]['cn'].split(' ')
-          ui.setFirstName(cn[0])
-          ui.setLastName(cn[1])
-          return ui
-  - name: groupInfo
-    cache: true
-    expirationTimeMsec: 600000
-    scope: SUBTREE
-    attributes:
-      - cn
-      - mail
-      - gidNumber
-      - memberUid
-    timeLimit: 0
-    base: LDAP_DN
-    filter: "(&(objectClass=posixGroup))"
-    searchResultProcessor:
-      language: javascript
-#      path: c:\tmp\enrich.js
-      code: |
-        var enrichUserInfo = function(ui,context) {
-          name = ui.getName();
-          key = context['key'].toLowerCase();
-          userInfo=context['userInfo'];
-          if( userInfo[key] == undefined ) {
-            throw 'JavaScript LDAP UserInfo not found for '+key;
-          }
-          uid= userInfo[key];
-          userGid = uid['gidnumber'];
-          groupInfo=context['groupInfo'];
-          for( dn in groupInfo ) {
-            group = groupInfo[dn];
-            if( userGid == group['gidnumber']) {
-              ui.addRole(group['cn']);
-            } else {
-                grMembers = group['memberuid'];
-                if (grMembers != undefined) {
-                  index = grMembers.split(",");
-                  members = new Array();
-                  for(i in index) {
-                    members[i] = grMembers.split(",")[i];
-                  }
-                  for (member in members) {
-                    if (members[member] != undefined) {
-                      if (members[member].toLowerCase() == name.toLowerCase()) {
-                        ui.addRole(group['cn']);
-                      }
-                    }
-                  }
-                }
-              }
-          }
-          return ui;
-        }
-
+ldapGroupAttribute: memberUid
+ldapGroupNameAttribute: cn
+ldapGroupUserAttribute: uid
+ldapSearchRequest:
+  expirationTimeMsec: 600000
+  scope: SUBTREE
+  attributes:
+  - cn
+  - mail
+  - uid
+  - gidNumber
+  timeLimit: 0
+  base: LDAP_DN
+  filter: "(&(objectClass=inetOrgPerson)(uid=$LDAP_SEARCH_ATTRIBUTE))"
+ldapGroupSearchRequest:
+  expirationTimeMsec: 600000
+  scope: SUBTREE
+  attributes:
+  - cn
+  - memberUid
+  timeLimit: 0
+  base: LDAP_DN
+  filter: "(&(objectClass=posixGroup))"
 server:
   requestLog:
     appenders:
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/SecurityServiceConfiguration.java b/services/security-service/src/main/java/com/epam/dlab/auth/SecurityServiceConfiguration.java
index 5593978..3ec3f69 100644
--- a/services/security-service/src/main/java/com/epam/dlab/auth/SecurityServiceConfiguration.java
+++ b/services/security-service/src/main/java/com/epam/dlab/auth/SecurityServiceConfiguration.java
@@ -26,7 +26,6 @@ import org.apache.directory.ldap.client.api.LdapConnectionConfig;
 
 import javax.validation.constraints.Min;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 public class SecurityServiceConfiguration extends ServiceConfiguration {
@@ -40,8 +39,6 @@ public class SecurityServiceConfiguration extends ServiceConfiguration {
 	@Min(5)
 	private int loginAuthenticationTimeout = 10;
 	@JsonProperty
-	private List<Request> ldapSearch;
-	@JsonProperty
 	private String ldapBindTemplate;
 	@JsonProperty
 	private String ldapBindAttribute;
@@ -58,16 +55,38 @@ public class SecurityServiceConfiguration extends ServiceConfiguration {
 
 	private LdapConnectionConfig ldapConfiguration;
 
+	private String ldapGroupAttribute;
+	private String ldapGroupNameAttribute;
+	private String ldapGroupUserAttribute;
+
+	@JsonProperty
+	private Request ldapSearchRequest;
+
+	@JsonProperty
+	private Request ldapGroupSearchRequest;
+
 	public SecurityServiceConfiguration() {
 		super();
 	}
 
-	public boolean isUserInfoPersistenceEnabled() {
-		return userInfoPersistenceEnabled;
+	public String getLdapGroupUserAttribute() {
+		return ldapGroupUserAttribute;
+	}
+
+	public String getLdapGroupAttribute() {
+		return ldapGroupAttribute;
+	}
+
+	public String getLdapGroupNameAttribute() {
+		return ldapGroupNameAttribute;
 	}
 
-	public List<Request> getLdapSearch() {
-		return ldapSearch;
+	public Request getLdapGroupSearchRequest() {
+		return ldapGroupSearchRequest;
+	}
+
+	public boolean isUserInfoPersistenceEnabled() {
+		return userInfoPersistenceEnabled;
 	}
 
 	public LdapConnectionConfig getLdapConnectionConfig() {
@@ -117,4 +136,8 @@ public class SecurityServiceConfiguration extends ServiceConfiguration {
 	public GcpLoginConfiguration getGcpLoginConfiguration() {
 		return gcpLoginConfiguration;
 	}
+
+	public Request getLdapSearchRequest() {
+		return ldapSearchRequest;
+	}
 }
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/core/CacheableReference.java b/services/security-service/src/main/java/com/epam/dlab/auth/core/CacheableReference.java
deleted file mode 100644
index 60ff0d3..0000000
--- a/services/security-service/src/main/java/com/epam/dlab/auth/core/CacheableReference.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2016, EPAM SYSTEMS INC
- *
- * Licensed 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 com.epam.dlab.auth.core;
-
-import com.aegisql.conveyor.BuilderSupplier;
-
-import java.util.function.Supplier;
-
-public class CacheableReference<T> implements Supplier<T> {
-
-    /** The reference. */
-    private final T reference;
-
-    /**
-     * Instantiates a new immutable reference.
-     *
-     * @param ref the ref
-     */
-    private CacheableReference(T ref) {
-        this.reference = ref;
-    }
-
-    /* (non-Javadoc)
-     * @see java.util.function.Supplier#get()
-     */
-    @Override
-    public T get() {
-        return reference;
-    }
-
-    public static <T> BuilderSupplier<T> newInstance(T ref) {
-        return () -> new CacheableReference<>(ref);
-    }
-
-    @Override
-    public String toString() {
-        return ""+reference;
-    }
-}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/core/DlabLdapConnection.java b/services/security-service/src/main/java/com/epam/dlab/auth/core/DlabLdapConnection.java
index 51ee800..0ca2f97 100644
--- a/services/security-service/src/main/java/com/epam/dlab/auth/core/DlabLdapConnection.java
+++ b/services/security-service/src/main/java/com/epam/dlab/auth/core/DlabLdapConnection.java
@@ -27,7 +27,7 @@ public abstract class DlabLdapConnection implements Closeable {
 
 	abstract LdapConnection getConnection() throws Exception;
 
-	public LdapConnection connect() throws Exception {
+	public LdapConnection getBoundConnection() throws Exception {
 		final LdapConnection connection = getConnection();
 		if (!connection.connect()) {
 			log.error("Cannot establish a connection to LDAP server");
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/core/DlabLdapConnectionFactory.java b/services/security-service/src/main/java/com/epam/dlab/auth/core/DlabLdapConnectionFactory.java
new file mode 100644
index 0000000..0a76b53
--- /dev/null
+++ b/services/security-service/src/main/java/com/epam/dlab/auth/core/DlabLdapConnectionFactory.java
@@ -0,0 +1,48 @@
+/*
+ *
+ *  * Copyright (c) 2018, EPAM SYSTEMS INC
+ *  *
+ *  * Licensed 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 com.epam.dlab.auth.core;
+
+import com.epam.dlab.auth.SecurityServiceConfiguration;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import org.apache.directory.ldap.client.api.LdapConnectionConfig;
+import org.apache.directory.ldap.client.api.LdapConnectionPool;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.apache.directory.ldap.client.api.ValidatingPoolableLdapConnectionFactory;
+
+@Singleton
+public class DlabLdapConnectionFactory {
+
+
+	private final LdapConnectionConfig connConfig;
+	private final LdapConnectionPool connectionPool;
+	private final boolean usePool;
+
+	@Inject
+	public DlabLdapConnectionFactory(SecurityServiceConfiguration configuration) {
+		this.connConfig = configuration.getLdapConnectionConfig();
+		this.connectionPool = new LdapConnectionPool(new ValidatingPoolableLdapConnectionFactory(connConfig));
+		this.usePool = configuration.isLdapUseConnectionPool();
+	}
+
+	public DlabLdapConnection newConnection() {
+		return usePool ? new ReturnableConnection(connectionPool) :
+				new SimpleConnection(new LdapNetworkConnection(connConfig));
+	}
+}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/core/LdapFilterCache.java b/services/security-service/src/main/java/com/epam/dlab/auth/core/LdapFilterCache.java
deleted file mode 100644
index 7a37dcc..0000000
--- a/services/security-service/src/main/java/com/epam/dlab/auth/core/LdapFilterCache.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/***************************************************************************
-
- Copyright (c) 2016, EPAM SYSTEMS INC
-
- Licensed 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 com.epam.dlab.auth.core;
-
-import com.aegisql.conveyor.cart.command.CancelCommand;
-import com.aegisql.conveyor.utils.caching.CachingConveyor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.function.Supplier;
-
-public class LdapFilterCache extends CachingConveyor<String,String,Map<String,Object>> {
-
-    private final static Logger LOG = LoggerFactory.getLogger(LdapFilterCache.class);
-
-    private final static LdapFilterCache INSTANCE = new LdapFilterCache();
-
-    public static LdapFilterCache getInstance() {
-        return INSTANCE;
-    }
-
-    private LdapFilterCache() {
-        super();
-        this.setName("LdapFilterCache");
-        this.setIdleHeartBeat(1, TimeUnit.SECONDS);
-        this.setDefaultCartConsumer((b,l,s)-> LOG.debug("LdapFilterCache consume {} {}",l,s.get()));
-        this.setOnTimeoutAction((s)->{
-            LOG.trace("LdapFilterCache Timeout {}",s.get());
-        });
-        this.setScrapConsumer(bin->{
-            LOG.debug("LdapFilterCache {}: {}", bin.failureType, bin.scrap);
-        });
-    }
-
-    public void removeLdapFilterInfo(String token) {
-        this.addCommand(new CancelCommand<>(token));
-    }
-
-    public Map<String,Object> getLdapFilterInfo(String token) {
-        Supplier<? extends Map<String,Object>> s = this.getProductSupplier(token);
-        if( s == null ) {
-            return null;
-        } else {
-            return s.get();
-        }
-    }
-
-    public void save(String token, Map<String,Object> ldapInfo,long expTimeMsec) {
-        CompletableFuture<Boolean> cacheFuture = LdapFilterCache.getInstance().createBuild(token, CacheableReference.newInstance(ldapInfo),expTimeMsec,TimeUnit.MILLISECONDS);
-        try {
-            if(! cacheFuture.get() ) {
-                throw new Exception("Cache offer future returned 'false' for "+ldapInfo);
-            }
-        } catch (Exception e) {
-            throw new RuntimeException("Cache offer failed for "+ldapInfo,e);
-        }
-    }
-
-}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/core/LoginCache.java b/services/security-service/src/main/java/com/epam/dlab/auth/core/LoginCache.java
deleted file mode 100644
index 4c48172..0000000
--- a/services/security-service/src/main/java/com/epam/dlab/auth/core/LoginCache.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/***************************************************************************
-
- Copyright (c) 2016, EPAM SYSTEMS INC
-
- Licensed 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 com.epam.dlab.auth.core;
-
-import com.aegisql.conveyor.cart.command.CancelCommand;
-import com.aegisql.conveyor.utils.caching.CachingConveyor;
-import com.epam.dlab.auth.UserInfo;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.function.Supplier;
-
-public class LoginCache extends CachingConveyor<String,String,UserInfo> {
-
-    private final static Logger LOG = LoggerFactory.getLogger(LoginCache.class);
-
-    private final static LoginCache INSTANCE = new LoginCache();
-
-    public static LoginCache getInstance() {
-        return INSTANCE;
-    }
-
-    private LoginCache() {
-        super();
-        this.setName("UserInfoCache");
-        this.setIdleHeartBeat(1, TimeUnit.SECONDS);
-        this.setDefaultBuilderTimeout(60, TimeUnit.MINUTES);
-        this.enablePostponeExpirationOnTimeout(false);
-        this.enablePostponeExpiration(true);
-        this.setExpirationPostponeTime(60,TimeUnit.MINUTES);
-        this.setDefaultCartConsumer((b,l,s)-> LOG.debug("UserInfoCache consume {} {}",l,s.get()));
-        this.setOnTimeoutAction((s)->{
-            LOG.trace("UserInfoCache Timeout {}",s.get());
-        });
-        this.setScrapConsumer(bin->{
-            LOG.debug("UserInfoCache {}: {}", bin.failureType, bin.scrap);
-        });
-    }
-
-    public void removeUserInfo(String token) {
-        this.addCommand(new CancelCommand<>(token));
-    }
-
-    public UserInfo getUserInfo(String token) {
-        Supplier<? extends UserInfo> s = this.getProductSupplier(token);
-        if( s == null ) {
-            return null;
-        } else {
-            return s.get();
-        }
-    }
-
-    public void save(UserInfo userInfo) {
-        CompletableFuture<Boolean> cacheFuture = LoginCache.getInstance().createBuild(userInfo.getAccessToken(), CacheableReference.newInstance(userInfo));
-        try {
-            if(! cacheFuture.get() ) {
-                throw new Exception("Offer future returned 'false' for "+userInfo);
-            }
-        } catch (Exception e) {
-            throw new RuntimeException("User Info cache offer failure for "+userInfo,e);
-        }
-    }
-
-}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/core/LoginConveyor.java b/services/security-service/src/main/java/com/epam/dlab/auth/core/LoginConveyor.java
deleted file mode 100644
index 9c903ff..0000000
--- a/services/security-service/src/main/java/com/epam/dlab/auth/core/LoginConveyor.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/***************************************************************************
-
- Copyright (c) 2016, EPAM SYSTEMS INC
-
- Licensed 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 com.epam.dlab.auth.core;
-
-import com.aegisql.conveyor.utils.parallel.KBalancedParallelConveyor;
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.auth.UserInfoDAO;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
-
-public class LoginConveyor extends KBalancedParallelConveyor<String,LoginStep,UserInfo>{
-
-    private final static Logger LOG = LoggerFactory.getLogger(LoginConveyor.class);
-
-    private UserInfoDAO userInfoDao;
-
-    public LoginConveyor(long builderTimeout) {
-        super(4);
-        this.setName("LoginConveyor");
-        this.setIdleHeartBeat(1, TimeUnit.SECONDS);
-        this.setDefaultBuilderTimeout(builderTimeout, TimeUnit.SECONDS);
-        this.setResultConsumer(res->{
-            LOG.debug("UserInfo Build Success: {}",res);
-            LoginCache.getInstance().save(res.product);
-            if(userInfoDao != null) {
-                userInfoDao.saveUserInfo(res.product);
-            } else {
-                LOG.warn("UserInfo Build not saved: {}",res);
-            }
-        });
-        this.setScrapConsumer(bin-> LOG.error("UserInfo Build Failed: {}",bin));
-    }
-
-    public void setUserInfoDao(UserInfoDAO userInfoDao) {
-        this.userInfoDao = userInfoDao;
-    }
-
-    public CompletableFuture<UserInfo> startUserInfoBuild(String token, String username) {
-        LOG.debug("startUserInfoBuild {} {} {}",token,username);
-        return this.createBuildFuture(token,UserInfoBuilder.supplier(token,username));
-    }
-
-    public void cancel(String token, LoginStep step, String errorMessage) {
-        LOG.debug("Canceling {}: {}",token,errorMessage);
-        this.add(token,new RuntimeException(errorMessage),step);
-    }
-}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/core/LoginStep.java b/services/security-service/src/main/java/com/epam/dlab/auth/core/LoginStep.java
deleted file mode 100644
index 2f6e4fe..0000000
--- a/services/security-service/src/main/java/com/epam/dlab/auth/core/LoginStep.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/***************************************************************************
-
- Copyright (c) 2016, EPAM SYSTEMS INC
-
- Licensed 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 com.epam.dlab.auth.core;
-
-import com.aegisql.conveyor.SmartLabel;
-
-import java.util.function.BiConsumer;
-
-public enum LoginStep implements SmartLabel<UserInfoBuilder> {
-    LDAP_LOGIN(UserInfoBuilder::ldapLoginPassed),
-    LDAP_USER_INFO(UserInfoBuilder::ldapUserInfo),
-    AWS_USER(UserInfoBuilder::awsUser),
-    AWS_KEYS(UserInfoBuilder::awsKeys),
-    AWS_KEYS_EMPTY(UserInfoBuilder::awsKeysEmpty),
-    REMOTE_IP(UserInfoBuilder::remoteIp),
-    LDAP_USER_INFO_ERROR(UserInfoBuilder::ldapUserInfoError),
-    LDAP_GROUP_INFO_ERROR(UserInfoBuilder::ldapGroupInfoError),
-    AWS_USER_ERROR(UserInfoBuilder::awsUserError),
-    AWS_KEYS_ERROR(UserInfoBuilder::awsKeysError),
-    ;
-    BiConsumer<UserInfoBuilder, Object> setter;
-    @SuppressWarnings("unchecked")
-	<T extends Object> LoginStep (BiConsumer<UserInfoBuilder,T> setter) {
-        this.setter = (BiConsumer<UserInfoBuilder, Object>) setter;
-    }
-    @Override
-    public BiConsumer<UserInfoBuilder, Object> get() {
-        return setter;
-    }
-}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/core/UserInfoBuilder.java b/services/security-service/src/main/java/com/epam/dlab/auth/core/UserInfoBuilder.java
deleted file mode 100644
index 8e7b75e..0000000
--- a/services/security-service/src/main/java/com/epam/dlab/auth/core/UserInfoBuilder.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/***************************************************************************
-
- Copyright (c) 2016, EPAM SYSTEMS INC
-
- Licensed 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 com.epam.dlab.auth.core;
-
-import com.aegisql.conveyor.BuilderSupplier;
-import com.aegisql.conveyor.Testing;
-import com.amazonaws.services.identitymanagement.model.AccessKeyMetadata;
-import com.epam.dlab.auth.UserInfo;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.atomic.LongAdder;
-import java.util.function.Supplier;
-
-public class UserInfoBuilder implements Supplier<UserInfo>, Testing {
-
-    private final static Logger LOG = LoggerFactory.getLogger(UserInfoBuilder.class);
-
-    private UserInfo userInfo;
-
-    private RuntimeException ldapError      = null;
-    private RuntimeException ldapGroupError = null;
-    private RuntimeException awsUserError   = null;
-    private RuntimeException awsKeyError    = null;
-
-
-    private int readinessStatus = 0b00000000;
-
-    public final static int FIRST_NAME      = 0b0000001;
-    public final static int LAST_NAME       = 0b0000010;
-    public final static int AWS_USER_SET    = 0b0000100;
-    public final static int ROLE_SET        = 0b0001000;
-    public final static int REMOTE_IP       = 0b0010000;
-    public final static int AWS_KEYS        = 0b0100000;
-    public final static int LOGIN           = 0b1000000;
-
-    public final static int READYNESS_MASK  = 0b1111111;
-
-    public static boolean testMask(Supplier<? extends UserInfo> supplier, int mask) {
-        UserInfoBuilder builder = (UserInfoBuilder) supplier;
-        LOG.debug("testing {} vs {} = {}",builder.readinessStatus,mask,(builder.readinessStatus & mask) == mask);
-        return (builder.readinessStatus & mask) == mask;
-    }
-
-    public void setMask(int mask) {
-        this.readinessStatus |= mask;
-    }
-
-    public static BuilderSupplier<UserInfo> supplier(final String token, final String username ) {
-        LOG.debug("supplier requested {} {}",token, username);
-        return () -> new UserInfoBuilder(token,username);
-    }
-
-    public static void ldapLoginPassed(UserInfoBuilder b, Object t) {
-        b.setMask( LOGIN );
-    }
-
-    public static void firstName(UserInfoBuilder b, String firstName) {
-        LOG.debug("firstName {}",firstName);
-
-        b.userInfo.setFirstName(firstName);
-        b.setMask( FIRST_NAME );
-    }
-
-    public static void lastName(UserInfoBuilder b, String lastName) {
-        LOG.debug("lastName {}",lastName);
-
-        b.userInfo.setLastName(lastName);
-        b.setMask( LAST_NAME );
-    }
-
-    public static void remoteIp(UserInfoBuilder b, String remoteIp) {
-        LOG.debug("remoteIp {}",remoteIp);
-
-        b.userInfo.setRemoteIp(remoteIp);
-        b.setMask( REMOTE_IP );
-    }
-
-    public static void awsUser(UserInfoBuilder b, Boolean awsUser) {
-        LOG.debug("awsUser {}",awsUser);
-
-        b.userInfo.setAwsUser(awsUser);
-        b.setMask( AWS_USER_SET );
-    }
-
-    public static void roles(UserInfoBuilder b, Collection<String> roles) {
-        LOG.debug("roles {}",roles);
-        roles.forEach( role -> b.userInfo.addRole(role) );
-        b.setMask( ROLE_SET );
-    }
-
-    public static void ldapUserInfo(UserInfoBuilder b, UserInfo ui) {
-        LOG.debug("merge user info{}",ui);
-        UserInfoBuilder.firstName(b,ui.getFirstName());
-        UserInfoBuilder.lastName(b,ui.getLastName());
-        UserInfoBuilder.roles(b,ui.getRoles());
-    }
-
-    public UserInfoBuilder(String token, String username) {
-        this.userInfo = new UserInfo(username, token);
-    }
-
-    public UserInfoBuilder() {
-
-    }
-
-    @Override
-    public UserInfo get() {
-        if( ldapError != null )      throw ldapError;
-        if( ldapGroupError != null ) throw ldapGroupError;
-        if( awsUserError != null )   throw awsUserError;
-        if( awsKeyError != null )    throw awsKeyError;
-        return userInfo;
-    }
-
-    @Override
-    public String toString() {
-        return "UserInfoBuilder{" +
-                "userInfo=" + userInfo +
-                ", readinessStatus=" + readinessStatus +
-                '}';
-    }
-
-    @Override
-    public boolean test() {
-        return UserInfoBuilder.testMask(this,UserInfoBuilder.READYNESS_MASK);
-    }
-
-    public static void awsKeys(UserInfoBuilder b, List<AccessKeyMetadata> keyMetadata) {
-        LOG.debug("AWS Keys {}",keyMetadata);
-        LongAdder counter = new LongAdder();
-        if(keyMetadata != null) {
-            keyMetadata.forEach(k -> {
-                String key = k.getAccessKeyId();
-                String status = k.getStatus();
-                if ("Active".equalsIgnoreCase(status)) {
-                    counter.increment();
-                }
-                b.userInfo.addKey(key, status);
-            });
-        }
-
-        if( counter.intValue() == 0 ) {
-            b.awsKeyError = new RuntimeException("Please contact AWS administrator to activate your Access Key");
-        }
-        b.setMask( AWS_KEYS );
-    }
-
-    public static void awsKeysEmpty(UserInfoBuilder b, List<AccessKeyMetadata> keyMetadata) {
-        LOG.debug("AWS Keys {}",keyMetadata);
-        b.setMask( AWS_KEYS );
-    }
-
-    public static void ldapUserInfoError(UserInfoBuilder b, RuntimeException t) {
-        LOG.error("ldapUserInfoError {}", t.getMessage());
-        b.ldapError = t;
-        b.setMask( LOGIN );
-    }
-
-    public static void ldapGroupInfoError(UserInfoBuilder b, RuntimeException t) {
-        LOG.error("ldapGroupInfoError {}", t.getMessage());
-        b.ldapGroupError = t;
-        b.setMask( FIRST_NAME | LAST_NAME | ROLE_SET );
-    }
-
-    public static void awsUserError(UserInfoBuilder b, RuntimeException t) {
-        LOG.error("awsUserError {}", t.getMessage());
-        b.awsUserError = t;
-        b.setMask( AWS_USER_SET );
-    }
-
-    public static void awsKeysError(UserInfoBuilder b, RuntimeException t) {
-        LOG.error("awsKeysError {}", t.getMessage());
-        b.awsKeyError = t;
-        b.setMask( AWS_KEYS );
-    }
-
-}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/dao/LdapUserDAO.java b/services/security-service/src/main/java/com/epam/dlab/auth/dao/LdapUserDAO.java
index 0b9fa65..9bf1cdd 100644
--- a/services/security-service/src/main/java/com/epam/dlab/auth/dao/LdapUserDAO.java
+++ b/services/security-service/src/main/java/com/epam/dlab/auth/dao/LdapUserDAO.java
@@ -1,210 +1,29 @@
-/***************************************************************************
-
- Copyright (c) 2016, EPAM SYSTEMS INC
-
- Licensed 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.
-
- ****************************************************************************/
+/*
+ *
+ *  * Copyright (c) 2018, EPAM SYSTEMS INC
+ *  *
+ *  * Licensed 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 com.epam.dlab.auth.dao;
 
-import com.epam.dlab.auth.SecurityServiceConfiguration;
 import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.auth.core.DlabLdapConnection;
-import com.epam.dlab.auth.core.LdapFilterCache;
-import com.epam.dlab.auth.core.ReturnableConnection;
-import com.epam.dlab.auth.core.SimpleConnection;
-import com.epam.dlab.auth.dao.filter.SearchResultProcessor;
-import com.epam.dlab.auth.dao.script.ScriptHolder;
-import com.epam.dlab.auth.dao.script.SearchResultToDictionaryMapper;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.pool.PoolableObjectFactory;
-import org.apache.directory.api.ldap.model.cursor.SearchCursor;
-import org.apache.directory.api.ldap.model.exception.LdapException;
-import org.apache.directory.api.ldap.model.message.SearchRequest;
-import org.apache.directory.ldap.client.api.*;
-
-import java.io.IOException;
-import java.util.*;
-import java.util.regex.Pattern;
-
-@Slf4j
-public class LdapUserDAO {
-
-	// the request from security.yml for user look up by one of the parameters (mail or phone).
-	//  configured in the same request configuration under "filter" key: "(&(objectClass=inetOrgPerson)(mail=%mail%))"
-	private static final String USER_LOOK_UP = "userLookUp";
-	private static final String DISTINGUISH_NAME = "dn";
-	private final LdapConnectionConfig connConfig;
-	private final List<Request> requests;
-	private final String bindTemplate;
-	private final String ldapBindAttribute;
-	private final String ldapSearchAttribute;
-	private final LdapConnectionPool usersPool;
-	private final LdapConnectionPool searchPool;
-	private final ScriptHolder script = new ScriptHolder();
-	private final boolean useBindTemplate;
-	private boolean useCache;
-	private boolean ldapUseConnectionPool;
-
-	public LdapUserDAO(SecurityServiceConfiguration config, boolean useCache) {
-		this.connConfig = config.getLdapConnectionConfig();
-		this.requests = config.getLdapSearch();
-		this.useBindTemplate = config.isUseLdapBindTemplate();
-		this.bindTemplate = config.getLdapBindTemplate();
-		this.ldapBindAttribute = config.getLdapBindAttribute();
-		this.ldapSearchAttribute = "%" + config.getLdapSearchAttribute() + "%";
-		PoolableObjectFactory<LdapConnection> userPoolFactory = new ValidatingPoolableLdapConnectionFactory
-				(connConfig);
-		this.usersPool = new LdapConnectionPool(userPoolFactory);
-		PoolableObjectFactory<LdapConnection> searchPoolFactory = new ValidatingPoolableLdapConnectionFactory
-				(connConfig);
-		this.searchPool = new LdapConnectionPool(searchPoolFactory);
-		this.useCache = useCache;
-		this.ldapUseConnectionPool = config.isLdapUseConnectionPool();
-	}
-
-	private DlabLdapConnection getConnection(LdapConnectionPool connectionPool) {
-		return ldapUseConnectionPool ? new ReturnableConnection(connectionPool) :
-				new SimpleConnection(new LdapNetworkConnection(connConfig));
-	}
-
-	public UserInfo getUserInfo(String username, String password) throws Exception {
-		Map<String, Object> userAttributes;
-
-		try (DlabLdapConnection connection = getConnection(usersPool)) {
-			final LdapConnection ldapConnection = connection.connect();
-			userAttributes = searchUsersAttributes(username, ldapConnection);
-			String bindAttribute = userAttributes.get(ldapBindAttribute).toString();
-			bindUser(username, password, bindAttribute, ldapConnection, (String) userAttributes.get(DISTINGUISH_NAME));
-
-			UserInfo userInfo = new UserInfo(username, "******");
-			userAttributes.entrySet().forEach(entry -> addAttribute(userInfo, entry));
-
-			return userInfo;
-		} catch (Exception e) {
-			log.error("LDAP getUserInfo authentication error for username '{}': {}", username, e.getMessage(), e);
-			throw e;
-		}
-	}
-
-	private void bindUser(String username, String password, String cn, LdapConnection userCon, String dn) throws
-			LdapException {
-		userCon.bind(getBind(cn, dn), password);
-		userCon.unBind();
-		log.debug("User '{}' identified.", username);
-	}
-
-	private String getBind(String cn, String dn) {
-		String bind;
-		if (useBindTemplate) {
-			log.info("Biding with template : {} and username/cn: {}", bindTemplate, cn);
-			bind = String.format(bindTemplate, cn);
-		} else {
-			log.info("Biding using dn : {}", dn);
-			bind = dn;
-		}
-		return bind;
-	}
-
-	private Map<String, Object> searchUsersAttributes(final String username, LdapConnection userCon) throws
-			IOException, LdapException {
-		Map<String, Object> contextMap;
-		Map<String, Object> userAttributes = new HashMap<>();
-		for (Request request : requests) {
-			if (request.getName().equalsIgnoreCase(USER_LOOK_UP)) {
-				log.info("Request: {}", request.getName());
-				log.info("Putting user param {} : {}", ldapSearchAttribute, username);
-				SearchRequest sr = request.buildSearchRequest(Collections.
-						singletonMap(Pattern.quote(ldapSearchAttribute), username));
-				String filter = sr.getFilter().toString();
-				contextMap = (useCache) ? LdapFilterCache.getInstance().getLdapFilterInfo(filter) : null;
-				SearchResultToDictionaryMapper mapper = new SearchResultToDictionaryMapper(request.getName(),
-						new HashMap<>());
-				log.debug("Retrieving new branch {} for {}", request.getName(), filter);
-				try (SearchCursor cursor = userCon.search(sr)) {
-					contextMap = mapper.transformSearchResult(cursor);
-					Iterator<Object> iterator = contextMap.values().iterator();
-					if (iterator.hasNext()) {
-						@SuppressWarnings("unchecked")
-						Map<String, Object> ua = (Map<String, Object>) iterator.next();
-						log.info("User atttr {} ", ua);
-						userAttributes = ua;
-					}
-				}
-			}
-		}
-		log.info("User context is: {}", userAttributes);
-		return userAttributes;
-	}
-
-	public UserInfo enrichUserInfo(final UserInfo userInfo) throws Exception {
-		log.debug("Enriching user info for user: {}", userInfo);
 
-		String username = userInfo.getName();
-		UserInfo ui = userInfo.withToken("******");
-		try (DlabLdapConnection connection = getConnection(searchPool)) {
-			final LdapConnection ldapConnection = connection.connect();
-			Map<String, Object> conextTree = new HashMap<>();
-			for (Request req : requests) {
-				if (req.getName().equalsIgnoreCase(USER_LOOK_UP)) {
-					addUserAttributes(username, ui, ldapConnection);
-				}
-				log.info("Request: {}", req.getName());
-				SearchResultProcessor proc = req.getSearchResultProcessor();
-				log.info("Putting user param {} : {} for user enriching", ldapSearchAttribute, username);
-				SearchRequest sr = req.buildSearchRequest(Collections
-						.singletonMap(Pattern.quote(ldapSearchAttribute), username));
-				String filter = sr.getFilter().toString();
-				Map<String, Object> contextMap = (useCache) ? LdapFilterCache.getInstance().getLdapFilterInfo(filter)
-						: null;
-				SearchResultToDictionaryMapper mapper = new SearchResultToDictionaryMapper(req.getName(),
-						conextTree);
-				if (contextMap == null) {
-					log.debug("Retrieving new branch {} for {}", req.getName(), filter);
-					try (SearchCursor cursor = ldapConnection.search(sr)) {
-						contextMap = mapper.transformSearchResult(cursor);
-					}
-					if (req.isCache() && useCache) {
-						LdapFilterCache.getInstance().save(filter, contextMap, req.getExpirationTimeMsec());
-					}
-				} else {
-					log.debug("Restoring old branch {} for {}: {}", req.getName(), filter, contextMap);
-					mapper.getBranch().putAll(contextMap);
-				}
-				if (proc != null) {
-					log.debug("Executing: {}", proc.getLanguage());
-					conextTree.put("key", ui.getKeys().get("dn"));
-					ui = script.evalOnce(req.getName(), proc.getLanguage(), proc.getCode()).apply(ui, conextTree);
-				}
-			}
-		} catch (Exception e) {
-			log.error("LDAP enrichUserInfo authentication error for username '{}': {}", username, e.getMessage(), e);
-			throw e;
-		}
-		return ui;
-	}
+import java.util.Set;
 
-	private void addUserAttributes(String username, UserInfo ui, LdapConnection ldapConnection) throws IOException,
-			LdapException {
-		Map<String, Object> usersAttributes = searchUsersAttributes(username, ldapConnection);
-		usersAttributes.entrySet().stream().filter(e -> Objects.nonNull(e.getValue()))
-				.forEach(attribute -> addAttribute(ui, attribute));
-	}
+public interface LdapUserDAO {
+	UserInfo getUserInfo(String username, String password);
 
-	private void addAttribute(UserInfo ui, Map.Entry<String, Object> attribute) {
-		ui.addKey(attribute.getKey().toLowerCase(), attribute.getValue().toString());
-		log.debug("Adding attribute {} : {}", attribute.getKey().toLowerCase(), attribute.getValue
-				().toString());
-	}
+	Set<String> getUserGroups(UserInfo userInfo);
 }
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/dao/LdapUserDAOImpl.java b/services/security-service/src/main/java/com/epam/dlab/auth/dao/LdapUserDAOImpl.java
new file mode 100644
index 0000000..7c62e64
--- /dev/null
+++ b/services/security-service/src/main/java/com/epam/dlab/auth/dao/LdapUserDAOImpl.java
@@ -0,0 +1,164 @@
+/*
+ *
+ *  * Copyright (c) 2018, EPAM SYSTEMS INC
+ *  *
+ *  * Licensed 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 com.epam.dlab.auth.dao;
+
+import com.epam.dlab.auth.SecurityServiceConfiguration;
+import com.epam.dlab.auth.UserInfo;
+import com.epam.dlab.auth.core.DlabLdapConnection;
+import com.epam.dlab.auth.core.DlabLdapConnectionFactory;
+import com.epam.dlab.exceptions.DlabException;
+import com.google.inject.Inject;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.directory.api.ldap.model.cursor.SearchCursor;
+import org.apache.directory.api.ldap.model.entry.Attribute;
+import org.apache.directory.api.ldap.model.entry.Entry;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
+import org.apache.directory.api.ldap.model.message.SearchResultEntry;
+import org.apache.directory.api.ldap.model.message.SearchScope;
+import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.ldap.client.api.LdapConnection;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+@Slf4j
+public class LdapUserDAOImpl implements LdapUserDAO {
+	private static final String LDAP_SEARCH_ATTRIBUTE = "$LDAP_SEARCH_ATTRIBUTE";
+	private static final String COMMON_NAME_ATTRIBUTE = "cn";
+	private final DlabLdapConnectionFactory connectionFactory;
+	private final SecurityServiceConfiguration configuration;
+
+	@Inject
+	public LdapUserDAOImpl(DlabLdapConnectionFactory connectionFactory, SecurityServiceConfiguration configuration) {
+		this.connectionFactory = connectionFactory;
+		this.configuration = configuration;
+	}
+
+	@Override
+	public UserInfo getUserInfo(String username, String password) {
+
+		try (DlabLdapConnection connection = connectionFactory.newConnection()) {
+			return getUserInfo(username, password, connection.getBoundConnection());
+		} catch (Exception e) {
+			log.error("Can not get user info for user {} due to: {}", username, e.getMessage());
+			throw new DlabException("Can not get user info due to: " + e.getMessage(), e);
+		}
+	}
+
+	@Override
+	public Set<String> getUserGroups(UserInfo userInfo) {
+		final String groupUserAttribute = userInfo.getKeys().get(configuration.getLdapGroupUserAttribute());
+		try (DlabLdapConnection connection = connectionFactory.newConnection()) {
+			final LdapConnection ldapConnection = connection.getBoundConnection();
+			try (SearchCursor result = ldapConnection.search(getGroupSearchRequest())) {
+				return StreamSupport.stream(result.spliterator(), false)
+						.filter(r -> r instanceof SearchResultEntry)
+						.map(r -> ((SearchResultEntry) r).getEntry())
+						.flatMap(e -> groupStream(groupUserAttribute, e)).collect(Collectors.toSet());
+			}
+		} catch (Exception e) {
+			log.error("Can not get user groups for user {} due to: {}", userInfo.getName(), e.getMessage());
+			throw new DlabException("Can not get user groups due to: " + e.getMessage());
+		}
+	}
+
+	private Stream<? extends String> groupStream(String groupUserAttribute, Entry e) {
+		final Attribute groupAttribute = e.get(configuration.getLdapGroupAttribute());
+		return StreamSupport.stream(groupAttribute.spliterator(), false)
+				.anyMatch(v -> v.toString().equals(groupUserAttribute)) ?
+				Stream.of(e.get(configuration.getLdapGroupNameAttribute()).get().toString()) :
+				Stream.empty();
+	}
+
+	private UserInfo getUserInfo(String username, String password, LdapConnection ldapConnection) throws Exception {
+		try (SearchCursor result = ldapConnection.search(getUserSearchRequest(username))) {
+			return StreamSupport.stream(result.spliterator(), false)
+					.filter(r -> r instanceof SearchResultEntry)
+					.map(r -> ((SearchResultEntry) r).getEntry())
+					.map(e -> toUserInfo(e, username))
+					.peek(u -> bind(ldapConnection, u, password))
+					.findAny()
+					.orElseThrow(() -> new DlabException("User " + username + " not found"));
+		}
+	}
+
+	private void bind(LdapConnection ldapConnection, UserInfo u, String password) {
+		if (configuration.isUseLdapBindTemplate()) {
+			final String bindTemplate = configuration.getLdapBindTemplate();
+			final String ldapBindAttrName = configuration.getLdapBindAttribute();
+			final String bindAttrValue = Optional.ofNullable(u.getKeys().get(ldapBindAttrName))
+					.orElseThrow(() -> new DlabException("Bind attribute " + ldapBindAttrName + " is not found"));
+			log.info("Biding with template: {} and attribute {} with value: {}", bindTemplate, ldapBindAttrName,
+					bindAttrValue);
+			try {
+				ldapConnection.bind(String.format(bindTemplate, bindAttrValue), password);
+				ldapConnection.unBind();
+			} catch (LdapException e) {
+				log.error("Can not bind user due to: {}", e.getMessage());
+				throw new DlabException("Can not bind user due to: " + e.getMessage(), e);
+			}
+		}
+	}
+
+	private UserInfo toUserInfo(Entry e, String username) {
+		final Dn dn = e.getDn();
+		log.debug("Entry dn: {}", dn);
+		final UserInfo userInfo = new UserInfo(username, null);
+		e.getAttributes()
+				.forEach(a -> userInfo.addKey(a.getId(), a.get().toString()));
+		final String cn = userInfo.getKeys().get(COMMON_NAME_ATTRIBUTE);
+		final String[] splittedCommonName = cn.split(" ");
+		if (splittedCommonName.length == 2) {
+			userInfo.setFirstName(splittedCommonName[0]);
+			userInfo.setLastName(splittedCommonName[1]);
+		}
+
+		return userInfo;
+	}
+
+	private SearchRequestImpl getUserSearchRequest(String username) throws LdapException {
+		final SearchRequestImpl searchRequest = new SearchRequestImpl();
+		final Request searchRequestParams = configuration.getLdapSearchRequest();
+		searchRequest.setBase(new Dn(searchRequestParams.getBase()));
+		searchRequest.setFilter(searchRequestParams.getFilter().replace(LDAP_SEARCH_ATTRIBUTE, username));
+		searchRequest.setScope(SearchScope.valueOf(searchRequestParams.getScope()));
+		searchRequest.setTimeLimit(searchRequestParams.getTimeLimit());
+		final List<String> attributes = searchRequestParams.getAttributes();
+		searchRequest.addAttributes(attributes.toArray(new String[BigDecimal.ZERO.intValue()]));
+		return searchRequest;
+	}
+
+	private SearchRequestImpl getGroupSearchRequest() throws LdapException {
+		final SearchRequestImpl searchRequest = new SearchRequestImpl();
+		final Request searchRequestParams = configuration.getLdapGroupSearchRequest();
+		searchRequest.setBase(new Dn(searchRequestParams.getBase()));
+		searchRequest.setFilter(searchRequestParams.getFilter());
+		searchRequest.setScope(SearchScope.valueOf(searchRequestParams.getScope()));
+		searchRequest.setTimeLimit(searchRequestParams.getTimeLimit());
+		final List<String> attributes = searchRequestParams.getAttributes();
+		searchRequest.addAttributes(attributes.toArray(new String[BigDecimal.ZERO.intValue()]));
+		return searchRequest;
+	}
+}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/dao/Request.java b/services/security-service/src/main/java/com/epam/dlab/auth/dao/Request.java
index 64f0f39..e58a7a6 100644
--- a/services/security-service/src/main/java/com/epam/dlab/auth/dao/Request.java
+++ b/services/security-service/src/main/java/com/epam/dlab/auth/dao/Request.java
@@ -1,118 +1,33 @@
 /***************************************************************************
 
-Copyright (c) 2016, EPAM SYSTEMS INC
+ Copyright (c) 2016, EPAM SYSTEMS INC
 
-Licensed 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
+ Licensed 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
+ 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.
-
-****************************************************************************/
+ 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 com.epam.dlab.auth.dao;
 
-import com.epam.dlab.auth.dao.filter.SearchResultProcessor;
-import org.apache.directory.api.ldap.model.message.SearchRequest;
-import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
-import org.apache.directory.api.ldap.model.message.SearchScope;
-import org.apache.directory.api.ldap.model.name.Dn;
+import lombok.Data;
 
 import java.util.List;
-import java.util.Map;
 
+@Data
 public class Request {
-/*  
--   request: 
-    scope: SUBTREE
-    attributes: 
-      - "*"
-    timeLimit: 0
-    base: dc=example,dc=com
-    filter: 
- * */
-	
 	private String name;
 	private String scope;
 	private List<String> attributes;
-	private int timeLimit = 0;
+	private int timeLimit;
 	private String base;
 	private String filter = "";
-	private SearchResultProcessor searchResultProcessor;
-	private boolean cache = false;
-	private long expirationTimeMsec = 600000; //10 minutes
-	public String getScope() {
-		return scope;
-	}
-	public String[] getAttributes() {
-		return attributes.toArray(new String[]{});
-	}
-	public int getTimeLimit() {
-		return timeLimit;
-	}
-	public String getBase() {
-		return base;
-	}
-	public String getFilter() {
-		return filter;
-	}
-	
-	public SearchResultProcessor getSearchResultProcessor() {
-		return searchResultProcessor;
-	}
-	public void setSearchResultProcessor(SearchResultProcessor searchResultProcessor) {
-		this.searchResultProcessor = searchResultProcessor;
-	}
-	public String getName() {
-		return name;
-	}
-	public void setName(String name) {
-		this.name = name;
-	}
-	public boolean isCache() {
-		return cache;
-	}
-	public void setCache(boolean cache) {
-		this.cache = cache;
-	}
-	public long getExpirationTimeMsec() {
-		return expirationTimeMsec;
-	}
-	public void setExpirationTimeMsec(long expirationTimeMsec) {
-		this.expirationTimeMsec = expirationTimeMsec;
-	}
-	public SearchRequest buildSearchRequest(Map<String,Object> replace) {
-		SearchRequest sr = new SearchRequestImpl();
-		try {
-			sr.setBase(new Dn(this.base));
-			sr.addAttributes(this.getAttributes());
-			if(this.filter != null && ! "".equals(this.filter ) ){
-				String f = filter;
-				for(String key:replace.keySet()) {
-					f = f.replaceAll(key, replace.get(key).toString());
-				}
-				sr.setFilter(f);				
-			}
-			sr.setScope(SearchScope.valueOf(this.scope));
-			sr.setTimeLimit(this.timeLimit);
-		} catch (Exception e) {
-			throw new RuntimeException(e);
-		}
-		return sr;
-	}
-	
-	@Override
-	public String toString() {
-		return "RequestConfig [scope=" + scope + ", attributes=" + attributes + ", timeLimit=" + timeLimit + ", base=" + base
-				+ ", filter=" + filter + "]";
-	}
-
-
-	
+	private long expirationTimeMsec = 600000;
 }
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/dao/SearchRequestBuilder.java b/services/security-service/src/main/java/com/epam/dlab/auth/dao/SearchRequestBuilder.java
deleted file mode 100644
index 3d608ac..0000000
--- a/services/security-service/src/main/java/com/epam/dlab/auth/dao/SearchRequestBuilder.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/***************************************************************************
-
-Copyright (c) 2016, EPAM SYSTEMS INC
-
-Licensed 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 com.epam.dlab.auth.dao;
-
-public class SearchRequestBuilder {
-	public SearchRequestBuilder() {
-		
-	}
-}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/dao/UserInfoDAODumbImpl.java b/services/security-service/src/main/java/com/epam/dlab/auth/dao/UserInfoDAODumbImpl.java
index 1ecf642..690d93c 100644
--- a/services/security-service/src/main/java/com/epam/dlab/auth/dao/UserInfoDAODumbImpl.java
+++ b/services/security-service/src/main/java/com/epam/dlab/auth/dao/UserInfoDAODumbImpl.java
@@ -23,14 +23,16 @@ import com.epam.dlab.auth.UserInfoDAO;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.Optional;
+
 public class UserInfoDAODumbImpl implements UserInfoDAO {
 	
 	private static final Logger LOG = LoggerFactory.getLogger(UserInfoDAODumbImpl.class);
 
 	@Override
-	public UserInfo getUserInfoByAccessToken(String accessToken) {
+	public Optional<UserInfo> getUserInfoByAccessToken(String accessToken) {
 		LOG.debug("UserInfo persistence find unavailable: {}",accessToken);
-		return null;
+		return Optional.empty();
 	}
 
 	@Override
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/dao/UserInfoDAOMongoImpl.java b/services/security-service/src/main/java/com/epam/dlab/auth/dao/UserInfoDAOMongoImpl.java
index 67b28ea..b5c91be 100644
--- a/services/security-service/src/main/java/com/epam/dlab/auth/dao/UserInfoDAOMongoImpl.java
+++ b/services/security-service/src/main/java/com/epam/dlab/auth/dao/UserInfoDAOMongoImpl.java
@@ -13,7 +13,6 @@
  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 com.epam.dlab.auth.dao;
@@ -31,10 +30,13 @@ import com.mongodb.client.MongoCollection;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.Date;
+import java.util.Optional;
 
 @Singleton
 @Slf4j
 public class UserInfoDAOMongoImpl implements UserInfoDAO {
+	private static final String EXPIRE_AT_COLUMN = "expireAt";
+	private static final String SECURITY_COLLECTION = "security";
 	private final MongoService ms;
 	private final long inactiveUserTimeoutMsec;
 
@@ -45,52 +47,24 @@ public class UserInfoDAOMongoImpl implements UserInfoDAO {
 	}
 
 	@Override
-	public UserInfo getUserInfoByAccessToken(String accessToken) {
+	public Optional<UserInfo> getUserInfoByAccessToken(String accessToken) {
 		BasicDBObject uiSearchDoc = new BasicDBObject();
 		uiSearchDoc.put("_id", accessToken);
-		MongoCollection<BasicDBObject> mc = ms.getCollection("security", BasicDBObject.class);
+		MongoCollection<BasicDBObject> mc = ms.getCollection(SECURITY_COLLECTION, BasicDBObject.class);
 		FindIterable<BasicDBObject> res = mc.find(uiSearchDoc);
 		BasicDBObject uiDoc = res.first();
-		if (uiDoc == null) {
-			log.warn("UI not found {}", accessToken);
-			return null;
-		}
-		Date lastAccess = uiDoc.getDate("expireAt");
-		if (inactiveUserTimeoutMsec < Math.abs(new Date().getTime() - lastAccess.getTime())) {
-			log.warn("UI for {} expired but were not evicted from DB. Contact MongoDB admin to create expireable " +
-					"index" +
-					" on 'expireAt' key.", accessToken);
-			this.deleteUserInfo(accessToken);
-			return null;
-		}
-		String name = uiDoc.get("name").toString();
-		String firstName = uiDoc.getString("firstName", "");
-		String lastName = uiDoc.getString("lastName", "");
-		String remoteIp = uiDoc.getString("remoteIp", "");
-		BasicDBList roles = (BasicDBList) uiDoc.get("roles");
-		Boolean awsUser = uiDoc.getBoolean("awsUser", false);
-		UserInfo ui = new UserInfo(name, accessToken);
-		ui.setFirstName(firstName);
-		ui.setLastName(lastName);
-		ui.setRemoteIp(remoteIp);
-		ui.setAwsUser(awsUser);
-		Object awsKeys = uiDoc.get("awsKeys");
-		if (awsKeys != null) {
-			((BasicDBObject) awsKeys).forEach((key, val) -> ui.addKey(key, val.toString()));
-		}
-		roles.forEach(o -> ui.addRole("" + o));
-		log.debug("Found persistent {}", ui);
-		return ui;
+		return Optional.ofNullable(uiDoc)
+				.filter(doc -> !isExpired(accessToken, doc.getDate(EXPIRE_AT_COLUMN)))
+				.map(doc -> toUserInfo(accessToken, doc));
 	}
 
 	@Override
 	public void updateUserInfoTTL(String accessToken, UserInfo ui) {
-		//Update is caleed often, but does not need to be synchronized with the main thread
 
 		BasicDBObject uiDoc = new BasicDBObject();
 		uiDoc.put("_id", accessToken);
-		uiDoc.put("expireAt", new Date(System.currentTimeMillis()));
-		MongoCollection<BasicDBObject> security = ms.getCollection("security", BasicDBObject.class);
+		uiDoc.put(EXPIRE_AT_COLUMN, new Date(System.currentTimeMillis()));
+		MongoCollection<BasicDBObject> security = ms.getCollection(SECURITY_COLLECTION, BasicDBObject.class);
 		security.updateOne(new BasicDBObject("_id", accessToken), new BasicDBObject("$set", uiDoc));
 		log.debug("Updated persistent {}", accessToken);
 
@@ -101,7 +75,7 @@ public class UserInfoDAOMongoImpl implements UserInfoDAO {
 		//delete used in logout and has to be synchronized
 		BasicDBObject uiDoc = new BasicDBObject();
 		uiDoc.put("_id", accessToken);
-		MongoCollection<BasicDBObject> security = ms.getCollection("security", BasicDBObject.class);
+		MongoCollection<BasicDBObject> security = ms.getCollection(SECURITY_COLLECTION, BasicDBObject.class);
 		security.deleteOne(uiDoc);
 		log.debug("Deleted persistent {}", accessToken);
 	}
@@ -119,12 +93,42 @@ public class UserInfoDAOMongoImpl implements UserInfoDAO {
 		uiDoc.put("roles", ui.getRoles());
 		uiDoc.put("remoteIp", ui.getRemoteIp());
 		uiDoc.put("awsUser", ui.isAwsUser());
-		uiDoc.put("expireAt", new Date(System.currentTimeMillis()));
+		uiDoc.put(EXPIRE_AT_COLUMN, new Date(System.currentTimeMillis()));
 		uiDoc.put("awsKeys", ui.getKeys());
-		MongoCollection<BasicDBObject> security = ms.getCollection("security", BasicDBObject.class);
+		MongoCollection<BasicDBObject> security = ms.getCollection(SECURITY_COLLECTION, BasicDBObject.class);
 		security.insertOne(uiDoc);
 		log.debug("Saved persistent {}", ui);
 
 	}
 
+	private UserInfo toUserInfo(String accessToken, BasicDBObject uiDoc) {
+		String name = uiDoc.get("name").toString();
+		String firstName = uiDoc.getString("firstName", "");
+		String lastName = uiDoc.getString("lastName", "");
+		String remoteIp = uiDoc.getString("remoteIp", "");
+		BasicDBList roles = (BasicDBList) uiDoc.get("roles");
+		boolean awsUser = uiDoc.getBoolean("awsUser", false);
+		UserInfo ui = new UserInfo(name, accessToken);
+		ui.setFirstName(firstName);
+		ui.setLastName(lastName);
+		ui.setRemoteIp(remoteIp);
+		ui.setAwsUser(awsUser);
+		Object awsKeys = uiDoc.get("awsKeys");
+		if (awsKeys != null) {
+			((BasicDBObject) awsKeys).forEach((key, val) -> ui.addKey(key, val.toString()));
+		}
+		roles.forEach(o -> ui.addRole("" + o));
+		return ui;
+	}
+
+	private boolean isExpired(String accessToken, Date lastAccess) {
+		if (inactiveUserTimeoutMsec < Math.abs(new Date().getTime() - lastAccess.getTime())) {
+			log.warn("UI for {} expired but were not evicted from DB. Contact MongoDB admin to create expireable " +
+					"index on 'expireAt' key.", accessToken);
+			this.deleteUserInfo(accessToken);
+			return true;
+		}
+		return false;
+	}
+
 }
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/dao/filter/SearchResultMapper.java b/services/security-service/src/main/java/com/epam/dlab/auth/dao/filter/SearchResultMapper.java
deleted file mode 100644
index 7b51a98..0000000
--- a/services/security-service/src/main/java/com/epam/dlab/auth/dao/filter/SearchResultMapper.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/***************************************************************************
-
- Copyright (c) 2016, EPAM SYSTEMS INC
-
- Licensed 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 com.epam.dlab.auth.dao.filter;
-
-import org.apache.directory.api.ldap.model.cursor.SearchCursor;
-
-import java.io.IOException;
-import java.util.Map;
-
-public interface SearchResultMapper<M extends Map<String, Object>> {
-	M transformSearchResult(SearchCursor cursor) throws IOException;
-
-	M getBranch();
-}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/dao/filter/SearchResultProcessor.java b/services/security-service/src/main/java/com/epam/dlab/auth/dao/filter/SearchResultProcessor.java
deleted file mode 100644
index 936ac05..0000000
--- a/services/security-service/src/main/java/com/epam/dlab/auth/dao/filter/SearchResultProcessor.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/***************************************************************************
-
- Copyright (c) 2016, EPAM SYSTEMS INC
-
- Licensed 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 com.epam.dlab.auth.dao.filter;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-
-public class SearchResultProcessor {
-	private String language;
-	private String code;
-	private String path;
-
-	public String getLanguage() {
-		return language;
-	}
-
-	public void setLanguage(String language) {
-		this.language = language;
-	}
-
-	public String getCode() {
-		if (code == null || "".equals(code)) {
-			try {
-				code = new String(Files.readAllBytes(Paths.get(path)));
-			} catch (IOException e) {
-				throw new RuntimeException(e);
-			}
-		}
-		return code;
-	}
-
-	public void setCode(String code) {
-		this.code = code;
-	}
-
-	public String getPath() {
-		return path;
-	}
-
-	public void setPath(String path) {
-		this.path = path;
-	}
-
-	@Override
-	public String toString() {
-		return "SearchResultProcessor [language=" + language + ", path=" + path + ", code=" + code + "]";
-	}
-
-
-}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/dao/script/DeepMap.java b/services/security-service/src/main/java/com/epam/dlab/auth/dao/script/DeepMap.java
deleted file mode 100644
index 9d54a8b..0000000
--- a/services/security-service/src/main/java/com/epam/dlab/auth/dao/script/DeepMap.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/***************************************************************************
-
-Copyright (c) 2016, EPAM SYSTEMS INC
-
-Licensed 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 com.epam.dlab.auth.dao.script;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class DeepMap {
-	
-	private final Map<String, Object> root;
-	
-	public DeepMap(Map<String, Object> parent) {
-		super();
-		this.root = parent;
-	}
-
-	public DeepMap() {
-		super();
-		this.root = new HashMap<>();
-	}
-
-	public Map<String, Object> getRoot() {
-		return root;
-	}
-	
-	public DeepMap getBranch(String branchName) {
-		@SuppressWarnings("unchecked")
-		Map<String, Object> branch = (Map<String, Object>) root.get(branchName);
-		if( branch == null ) {
-			branch = new HashMap<>();
-			root.put(branchName, branch);
-		}
-		return new DeepMap(branch);
-	}
-	
-	public void put(String key,Object val) {
-		root.put(key, val);
-	}
-	
-}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/dao/script/ScriptHolder.java b/services/security-service/src/main/java/com/epam/dlab/auth/dao/script/ScriptHolder.java
deleted file mode 100644
index 83cd4b5..0000000
--- a/services/security-service/src/main/java/com/epam/dlab/auth/dao/script/ScriptHolder.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/***************************************************************************
-
-Copyright (c) 2016, EPAM SYSTEMS INC
-
-Licensed 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 com.epam.dlab.auth.dao.script;
-
-import com.epam.dlab.auth.UserInfo;
-
-import javax.script.Invocable;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.function.BiFunction;
-
-public class ScriptHolder {
-	
-	private final static String FUNCTION    = "enrichUserInfo";
-	
-	private final ScriptEngineManager   mgr = new ScriptEngineManager();
-	private final Map<String,Invocable> map = new HashMap<>();
-	
-	public ScriptHolder() {
-		
-	}
-	
-	public BiFunction<UserInfo,Map<String,?>,UserInfo> evalOnce(String name, String language, String code) throws ScriptException {
-		if( ! map.containsKey(name)) {
-			ScriptEngine engine = mgr.getEngineByName( language );
-			engine.eval(code);
-			map.put(name, (Invocable) engine);
-		}
-		return (ui,context)->{
-			try {
-				return (UserInfo) map.get(name).invokeFunction(FUNCTION, ui,context);
-			} catch (Exception e) {
-				throw new RuntimeException(e);
-			}
-		};
-	}
-	
-	
-}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/dao/script/SearchResultToDictionaryMapper.java b/services/security-service/src/main/java/com/epam/dlab/auth/dao/script/SearchResultToDictionaryMapper.java
deleted file mode 100644
index f9c7a47..0000000
--- a/services/security-service/src/main/java/com/epam/dlab/auth/dao/script/SearchResultToDictionaryMapper.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/***************************************************************************
-
- Copyright (c) 2016, EPAM SYSTEMS INC
-
- Licensed 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 com.epam.dlab.auth.dao.script;
-
-import com.epam.dlab.auth.dao.filter.SearchResultMapper;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.directory.api.ldap.model.cursor.SearchCursor;
-import org.apache.directory.api.ldap.model.entry.Entry;
-import org.apache.directory.api.ldap.model.message.SearchResultEntry;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-public class SearchResultToDictionaryMapper implements SearchResultMapper<Map<String, Object>> {
-
-	private static final Logger LOG = LoggerFactory.getLogger(SearchResultToDictionaryMapper.class);
-	private static final String DISTINGUISH_NAME = "dn";
-
-	private final DeepMap root;
-	private final DeepMap reqBranch;
-	private final String name;
-
-	public SearchResultToDictionaryMapper(String name) {
-		this.name = name;
-		this.root = new DeepMap();
-		reqBranch = root.getBranch(name);
-	}
-
-	public SearchResultToDictionaryMapper(String name, Map<String, Object> context) {
-		this.name = name;
-		this.root = new DeepMap(context);
-		reqBranch = root.getBranch(name);
-	}
-
-	@Override
-	public Map<String, Object> transformSearchResult(SearchCursor cursor) throws IOException {
-		LOG.debug(name);
-		cursor.forEach(response -> {
-			if (response instanceof SearchResultEntry) {
-				Entry resultEntry = ((SearchResultEntry) response).getEntry();
-				String dn = resultEntry.getDn().toString();
-				LOG.debug("\tEntryDN {}", dn);
-				DeepMap dnBranch = reqBranch.getBranch(dn.toLowerCase());
-				dnBranch.put(DISTINGUISH_NAME, dn);
-				resultEntry.forEach(attr -> {
-
-					// Since there might be multiple attributes with the same name, it is required to collect all their values (i.e. memberUid in group)
-					if (attr.size() > 1) {
-
-						List<Object> list = new ArrayList<>();
-						attr.iterator().forEachRemaining(list::add);
-
-						String join = StringUtils.join(list, ",");
-						dnBranch.put(attr.getId() + "", join);
-						LOG.debug("\t\tAttr {} : {} ", attr.getId(), join);
-					} else {
-						dnBranch.put(attr.getId() + "", attr.get() + "");
-						LOG.debug("\t\tAttr {}", attr);
-					}
-				});
-			}
-		});
-		return reqBranch.getRoot();
-	}
-
-	@Override
-	public Map<String, Object> getBranch() {
-		return reqBranch.getRoot();
-	}
-
-	@Override
-	public String toString() {
-		return "SearchResultToDictionaryMapper [name=" + name + ", parent=" + root + ", branch=" + reqBranch + "]";
-	}
-
-
-}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/modules/AwsSecurityServiceModule.java b/services/security-service/src/main/java/com/epam/dlab/auth/modules/AwsSecurityServiceModule.java
index d07bb7a..43683fe 100644
--- a/services/security-service/src/main/java/com/epam/dlab/auth/modules/AwsSecurityServiceModule.java
+++ b/services/security-service/src/main/java/com/epam/dlab/auth/modules/AwsSecurityServiceModule.java
@@ -25,7 +25,7 @@ import com.epam.dlab.auth.aws.dao.AwsUserDAO;
 import com.epam.dlab.auth.aws.dao.AwsUserDAOImpl;
 import com.epam.dlab.auth.aws.service.AwsCredentialRefreshService;
 import com.epam.dlab.auth.aws.service.AwsUserVerificationService;
-import com.epam.dlab.auth.resources.SynchronousLdapAuthenticationService;
+import com.epam.dlab.auth.resources.SynchronousLdapAuthenticationResource;
 import com.epam.dlab.cloud.CloudModule;
 import com.google.inject.Injector;
 import com.google.inject.Provides;
@@ -51,7 +51,7 @@ public class AwsSecurityServiceModule extends CloudModule {
 
 	@Override
 	public void init(Environment environment, Injector injector) {
-		environment.jersey().register(injector.getInstance(SynchronousLdapAuthenticationService.class));
+		environment.jersey().register(injector.getInstance(SynchronousLdapAuthenticationResource.class));
 		if (conf.isAwsUserIdentificationEnabled()) {
 			environment.lifecycle().manage(injector.getInstance(AwsCredentialRefreshService.class));
 		}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/modules/AzureSecurityServiceModule.java b/services/security-service/src/main/java/com/epam/dlab/auth/modules/AzureSecurityServiceModule.java
index e517093..9b02044 100644
--- a/services/security-service/src/main/java/com/epam/dlab/auth/modules/AzureSecurityServiceModule.java
+++ b/services/security-service/src/main/java/com/epam/dlab/auth/modules/AzureSecurityServiceModule.java
@@ -25,7 +25,7 @@ import com.epam.dlab.auth.azure.AzureSecurityResource;
 import com.epam.dlab.auth.azure.service.AzureAuthorizationCodeService;
 import com.epam.dlab.auth.azure.service.AzureAuthorizationCodeServiceImpl;
 import com.epam.dlab.auth.conf.AzureLoginConfiguration;
-import com.epam.dlab.auth.resources.SynchronousLdapAuthenticationService;
+import com.epam.dlab.auth.resources.SynchronousLdapAuthenticationResource;
 import com.epam.dlab.cloud.CloudModule;
 import com.google.inject.Injector;
 import io.dropwizard.setup.Environment;
@@ -63,7 +63,7 @@ public class AzureSecurityServiceModule extends CloudModule {
 	public void init(Environment environment, Injector injector) {
 
 		if (conf.getAzureLoginConfiguration().isUseLdap()) {
-			environment.jersey().register(injector.getInstance(SynchronousLdapAuthenticationService.class));
+			environment.jersey().register(injector.getInstance(SynchronousLdapAuthenticationResource.class));
 		} else {
 			final AzureAuthenticationResource azureAuthenticationResource = new AzureAuthenticationResource(conf,
 					injector.getInstance(UserInfoDAO.class), conf.getAzureLoginConfiguration(),
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/modules/GcpSecurityServiceModule.java b/services/security-service/src/main/java/com/epam/dlab/auth/modules/GcpSecurityServiceModule.java
index ff59a84..c8de7dd 100644
--- a/services/security-service/src/main/java/com/epam/dlab/auth/modules/GcpSecurityServiceModule.java
+++ b/services/security-service/src/main/java/com/epam/dlab/auth/modules/GcpSecurityServiceModule.java
@@ -21,7 +21,7 @@ import com.epam.dlab.auth.UserVerificationService;
 import com.epam.dlab.auth.gcp.resources.GcpOauth2SecurityResource;
 import com.epam.dlab.auth.gcp.service.GcpAuthenticationService;
 import com.epam.dlab.auth.oauth2.Oauth2AuthenticationService;
-import com.epam.dlab.auth.resources.SynchronousLdapAuthenticationService;
+import com.epam.dlab.auth.resources.SynchronousLdapAuthenticationResource;
 import com.epam.dlab.cloud.CloudModule;
 import com.google.api.client.auth.oauth2.AuthorizationCodeFlow;
 import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
@@ -60,7 +60,7 @@ public class GcpSecurityServiceModule extends CloudModule {
 
 	@Override
 	public void init(Environment environment, Injector injector) {
-		environment.jersey().register(injector.getInstance(SynchronousLdapAuthenticationService.class));
+		environment.jersey().register(injector.getInstance(SynchronousLdapAuthenticationResource.class));
 		if (conf.isOauth2authenticationEnabled()) {
 			environment.jersey().register(injector.getInstance(GcpOauth2SecurityResource.class));
 		}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/modules/SecurityServiceModule.java b/services/security-service/src/main/java/com/epam/dlab/auth/modules/SecurityServiceModule.java
index b2ba95d..7672faa 100644
--- a/services/security-service/src/main/java/com/epam/dlab/auth/modules/SecurityServiceModule.java
+++ b/services/security-service/src/main/java/com/epam/dlab/auth/modules/SecurityServiceModule.java
@@ -21,8 +21,11 @@ import com.epam.dlab.auth.SecurityServiceConfiguration;
 import com.epam.dlab.auth.UserInfoDAO;
 import com.epam.dlab.auth.UserVerificationService;
 import com.epam.dlab.auth.dao.LdapUserDAO;
+import com.epam.dlab.auth.dao.LdapUserDAOImpl;
 import com.epam.dlab.auth.dao.UserInfoDAODumbImpl;
 import com.epam.dlab.auth.dao.UserInfoDAOMongoImpl;
+import com.epam.dlab.auth.service.AuthenticationService;
+import com.epam.dlab.auth.service.impl.LdapAuthenticationService;
 import com.epam.dlab.mongo.MongoService;
 import com.google.inject.Provides;
 import com.google.inject.Singleton;
@@ -39,6 +42,8 @@ public class SecurityServiceModule extends ModuleBase<SecurityServiceConfigurati
 	@Override
 	protected void configure() {
 		bind(SecurityServiceConfiguration.class).toInstance(configuration);
+		bind(LdapUserDAO.class).to(LdapUserDAOImpl.class);
+		bind(AuthenticationService.class).to(LdapAuthenticationService.class);
 		if (configuration.isUserInfoPersistenceEnabled()) {
 			bind(UserInfoDAO.class).to(UserInfoDAOMongoImpl.class);
 		} else {
@@ -52,13 +57,7 @@ public class SecurityServiceModule extends ModuleBase<SecurityServiceConfigurati
 		return configuration.getMongoFactory().build(environment);
 	}
 
-	@Provides
-	@Singleton
-	private LdapUserDAO ldapUserDAOWithoutCache() {
-		return new LdapUserDAO(configuration, false);
-	}
-
 	public static UserVerificationService defaultUserVerificationService() {
-		return (username, userInfo) -> log.debug("No additional user verification configured");
+		return userInfo -> log.debug("No additional user verification configured");
 	}
 }
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/resources/SynchronousLdapAuthenticationResource.java b/services/security-service/src/main/java/com/epam/dlab/auth/resources/SynchronousLdapAuthenticationResource.java
new file mode 100644
index 0000000..113208d
--- /dev/null
+++ b/services/security-service/src/main/java/com/epam/dlab/auth/resources/SynchronousLdapAuthenticationResource.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017, EPAM SYSTEMS INC
+ *
+ * Licensed 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 com.epam.dlab.auth.resources;
+
+import com.epam.dlab.auth.UserInfo;
+import com.epam.dlab.auth.dto.UserCredentialDTO;
+import com.epam.dlab.auth.service.AuthenticationService;
+import com.epam.dlab.rest.dto.ErrorDTO;
+import com.google.inject.Inject;
+import lombok.extern.slf4j.Slf4j;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+/**
+ * Used for authentication against LDAP server
+ */
+@Path("/")
+@Consumes(MediaType.APPLICATION_JSON)
+@Produces(MediaType.APPLICATION_JSON)
+@Slf4j
+public class SynchronousLdapAuthenticationResource {
+	private static final String INVALID_CREDENTIALS = "Username or password is invalid";
+	private final AuthenticationService authenticationService;
+
+	@Inject
+	public SynchronousLdapAuthenticationResource(AuthenticationService authenticationService) {
+		this.authenticationService = authenticationService;
+	}
+
+	@POST
+	@Path("/login")
+	public Response login(UserCredentialDTO cred) {
+		log.debug("validating username:{} password:****** token:{}", cred.getUsername(), cred.getAccessToken());
+		return authenticationService.login(cred)
+				.map(userInfo -> Response.ok(userInfo.getAccessToken()).build())
+				.orElse(unauthorizedResponse());
+	}
+
+	@POST
+	@Path("/getuserinfo")
+	public UserInfo getUserInfo(String accessToken) {
+		return authenticationService.getUserInfo(accessToken).orElse(null);
+	}
+
+	@POST
+	@Path("/logout")
+	public Response logout(String accessToken) {
+		authenticationService.logout(accessToken);
+		return Response.ok().build();
+	}
+
+	private Response unauthorizedResponse() {
+		return Response.status(Response.Status.UNAUTHORIZED)
+				.entity(new ErrorDTO(Response.Status.UNAUTHORIZED.getStatusCode(), INVALID_CREDENTIALS))
+				.type(MediaType.APPLICATION_JSON)
+				.build();
+	}
+}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/resources/SynchronousLdapAuthenticationService.java b/services/security-service/src/main/java/com/epam/dlab/auth/resources/SynchronousLdapAuthenticationService.java
deleted file mode 100644
index 2194215..0000000
--- a/services/security-service/src/main/java/com/epam/dlab/auth/resources/SynchronousLdapAuthenticationService.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (c) 2017, EPAM SYSTEMS INC
- *
- * Licensed 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 com.epam.dlab.auth.resources;
-
-import com.epam.dlab.auth.SecurityServiceConfiguration;
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.auth.UserInfoDAO;
-import com.epam.dlab.auth.UserVerificationService;
-import com.epam.dlab.auth.dao.LdapUserDAO;
-import com.epam.dlab.auth.dto.UserCredentialDTO;
-import com.epam.dlab.auth.rest.AbstractAuthenticationService;
-import com.epam.dlab.constants.ServiceConsts;
-import com.epam.dlab.exceptions.DlabException;
-import com.epam.dlab.rest.dto.ErrorDTO;
-import com.google.inject.Inject;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-/**
- * Used for authentication against LDAP server
- */
-@Path("/")
-@Consumes(MediaType.APPLICATION_JSON)
-@Produces(MediaType.APPLICATION_JSON)
-public class SynchronousLdapAuthenticationService extends AbstractAuthenticationService<SecurityServiceConfiguration> {
-	private final LdapUserDAO ldapUserDAO;
-	private final UserInfoDAO userInfoDao;
-	private final UserVerificationService userVerificationService;
-
-	@Inject
-	public SynchronousLdapAuthenticationService(SecurityServiceConfiguration config, UserInfoDAO userInfoDao,
-												LdapUserDAO ldapUserDAO,
-												UserVerificationService userVerificationService) {
-		super(config);
-		this.ldapUserDAO = ldapUserDAO;
-		this.userInfoDao = userInfoDao;
-		this.userVerificationService = userVerificationService;
-	}
-
-	@Override
-	@POST
-	@Path("/login")
-	public Response login(UserCredentialDTO credential, @Context HttpServletRequest request) {
-
-		String username = credential.getUsername();
-		String password = credential.getPassword();
-		String accessToken = credential.getAccessToken();
-		String remoteIp = request.getRemoteAddr();
-		String userAgent = request.getHeader(HttpHeaders.USER_AGENT);
-
-		log.debug("validating username:{} password:****** token:{} ip:{}", username, accessToken, remoteIp);
-
-		final Response.Status unauthorized = Response.Status.UNAUTHORIZED;
-		if (accessToken != null && !accessToken.isEmpty()) {
-			UserInfo ui = getUserInfo(accessToken, userAgent, remoteIp);
-			if (ui != null) {
-				return Response.ok(accessToken).build();
-			} else {
-				log.debug("User info not found on login by access_token for user {}", username);
-				return Response.status(unauthorized).build();
-			}
-		}
-
-		try {
-
-			login(username, password);
-			UserInfo enriched = enrichUser(username);
-			userVerificationService.verify(username, enriched);
-
-			enriched.setRemoteIp(remoteIp);
-			log.info("User authenticated is {}", enriched);
-			String token = getRandomToken();
-
-			userInfoDao.saveUserInfo(enriched.withToken(token));
-			return Response.ok(token).build();
-
-		} catch (Exception e) {
-			log.error("User {} is not authenticated", username, e);
-			return Response.status(unauthorized)
-					.entity(new ErrorDTO(unauthorized.getStatusCode(), e.getMessage()))
-					.type(MediaType.APPLICATION_JSON).build();
-		}
-	}
-
-	@Override
-	@POST
-	@Path("/getuserinfo")
-	public UserInfo getUserInfo(String accessToken, @Context HttpServletRequest request) {
-		String userAgent = request.getHeader(HttpHeaders.USER_AGENT);
-		String remoteIp = request.getRemoteAddr();
-
-		UserInfo ui = getUserInfo(accessToken, userAgent, remoteIp);
-
-		if (ui != null) {
-			return ui;
-		}
-
-		log.debug("Session {} is expired", accessToken);
-
-		return null;
-	}
-
-	private UserInfo getUserInfo(String accessToken, String userAgent, String remoteIp) {
-
-		UserInfo ui = userInfoDao.getUserInfoByAccessToken(accessToken);
-
-		if (ui != null) {
-			ui = ui.withToken(accessToken);
-			updateTTL(accessToken, ui, userAgent);
-			log.debug("restored UserInfo from DB {}", ui);
-
-			log.debug("Authorized {} {} {}", accessToken, ui, remoteIp);
-			return ui;
-		}
-
-		return null;
-
-	}
-
-	@Override
-	@POST
-	@Path("/logout")
-	public Response logout(String accessToken) {
-		userInfoDao.deleteUserInfo(accessToken);
-		log.info("Logged out user {}", accessToken);
-		return Response.ok().build();
-	}
-
-	private UserInfo login(String username, String password) {
-		try {
-			UserInfo userInfo = ldapUserDAO.getUserInfo(username, password);
-			log.debug("User Authenticated: {}", username);
-			return userInfo;
-		} catch (Exception e) {
-			log.error("Authentication error", e);
-			throw new DlabException("Username or password are not valid", e);
-		}
-	}
-
-	private UserInfo enrichUser(String username) {
-
-		try {
-			UserInfo userInfo = ldapUserDAO.enrichUserInfo(new UserInfo(username, null));
-			log.debug("User Enriched: {}", username);
-			return userInfo;
-		} catch (Exception e) {
-			log.error("Authentication error", e);
-			throw new DlabException("User not authorized. Please contact DLAB administrator.");
-		}
-	}
-
-
-	private void updateTTL(String accessToken, UserInfo ui, String userAgent) {
-		log.debug("updating TTL agent {} {}", userAgent, ui);
-		if (ServiceConsts.PROVISIONING_USER_AGENT.equals(userAgent)) {
-			return;
-		}
-
-		userInfoDao.updateUserInfoTTL(accessToken, ui);
-	}
-}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/service/AuthenticationService.java b/services/security-service/src/main/java/com/epam/dlab/auth/service/AuthenticationService.java
new file mode 100644
index 0000000..fde6a82
--- /dev/null
+++ b/services/security-service/src/main/java/com/epam/dlab/auth/service/AuthenticationService.java
@@ -0,0 +1,33 @@
+/*
+ *
+ *  * Copyright (c) 2018, EPAM SYSTEMS INC
+ *  *
+ *  * Licensed 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 com.epam.dlab.auth.service;
+
+import com.epam.dlab.auth.UserInfo;
+import com.epam.dlab.auth.dto.UserCredentialDTO;
+
+import java.util.Optional;
+
+public interface AuthenticationService {
+
+	Optional<UserInfo> getUserInfo(String token);
+
+	Optional<UserInfo> login(UserCredentialDTO credentialDTO);
+
+	void logout(String token);
+}
diff --git a/services/security-service/src/main/java/com/epam/dlab/auth/service/impl/LdapAuthenticationService.java b/services/security-service/src/main/java/com/epam/dlab/auth/service/impl/LdapAuthenticationService.java
new file mode 100644
index 0000000..d17cd85
--- /dev/null
+++ b/services/security-service/src/main/java/com/epam/dlab/auth/service/impl/LdapAuthenticationService.java
@@ -0,0 +1,82 @@
+/*
+ *
+ *  * Copyright (c) 2018, EPAM SYSTEMS INC
+ *  *
+ *  * Licensed 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 com.epam.dlab.auth.service.impl;
+
+import com.epam.dlab.auth.UserInfo;
+import com.epam.dlab.auth.UserInfoDAO;
+import com.epam.dlab.auth.UserVerificationService;
+import com.epam.dlab.auth.dao.LdapUserDAO;
+import com.epam.dlab.auth.dto.UserCredentialDTO;
+import com.epam.dlab.auth.service.AuthenticationService;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Optional;
+
+import static com.epam.dlab.auth.rest.AbstractAuthenticationService.getRandomToken;
+
+@Singleton
+@Slf4j
+public class LdapAuthenticationService implements AuthenticationService {
+	private final UserInfoDAO userInfoDAO;
+	private final LdapUserDAO ldapUserDAO;
+	private final UserVerificationService verificationService;
+
+	@Inject
+	public LdapAuthenticationService(UserInfoDAO userInfoDAO, LdapUserDAO ldapUserDAO,
+									 UserVerificationService verificationService) {
+		this.userInfoDAO = userInfoDAO;
+		this.ldapUserDAO = ldapUserDAO;
+		this.verificationService = verificationService;
+	}
+
+	@Override
+	public Optional<UserInfo> getUserInfo(String token) {
+		return userInfoDAO.getUserInfoByAccessToken(token)
+				.map(userInfo -> touchedUser(token, userInfo));
+	}
+
+	@Override
+	public Optional<UserInfo> login(UserCredentialDTO credentialDTO) {
+		final String token = credentialDTO.getAccessToken();
+		return StringUtils.isNoneBlank(token) ? getUserInfo(token) : getLdapUserInfo(credentialDTO);
+	}
+
+	@Override
+	public void logout(String token) {
+		userInfoDAO.deleteUserInfo(token);
+	}
+
+	private Optional<UserInfo> getLdapUserInfo(UserCredentialDTO credentialDTO) {
+		final UserInfo user = ldapUserDAO.getUserInfo(credentialDTO.getUsername(), credentialDTO.getPassword());
+		user.addRoles(ldapUserDAO.getUserGroups(user));
+		verificationService.verify(user);
+		final String token = getRandomToken();
+		final UserInfo userWithToken = user.withToken(token);
+		userInfoDAO.saveUserInfo(userWithToken);
+		return Optional.of(userWithToken);
+	}
+
+	private UserInfo touchedUser(String token, UserInfo userInfo) {
+		userInfoDAO.updateUserInfoTTL(token, userInfo);
+		return userInfo.withToken(token);
+	}
+}
diff --git a/services/security-service/src/test/java/com/epam/dlab/auth/aws/AwsTest.java b/services/security-service/src/test/java/com/epam/dlab/auth/aws/AwsTest.java
deleted file mode 100644
index 15c5b9d..0000000
--- a/services/security-service/src/test/java/com/epam/dlab/auth/aws/AwsTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/***************************************************************************
-
-Copyright (c) 2016, EPAM SYSTEMS INC
-
-Licensed 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 com.epam.dlab.auth.aws;
-
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.auth.core.LdapFilterCache;
-import com.epam.dlab.auth.core.LoginCache;
-import org.junit.*;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-public class AwsTest {
-    @BeforeClass
-    public static void setUpBeforeClass() throws Exception {
-    }
-
-    @AfterClass
-    public static void tearDownAfterClass() throws Exception {
-    }
-
-    @Before
-    public void setUp() throws Exception {
-    }
-
-    @After
-    public void tearDown() throws Exception {
-    }
-
-    @Test
-    public void testLoginCache() throws InterruptedException {
-        LoginCache c = LoginCache.getInstance();
-        c.setDefaultBuilderTimeout(1, TimeUnit.SECONDS);
-        c.setIdleHeartBeat(100,TimeUnit.MILLISECONDS);
-        c.save(new UserInfo("test","a"));
-        UserInfo u = c.getUserInfo("a");
-        assertNotNull(u);
-        System.out.println(u);
-    }
-
-    @Test
-    public void testLdapCache() throws InterruptedException {
-        LdapFilterCache c = LdapFilterCache.getInstance();
-        c.setIdleHeartBeat(100,TimeUnit.MILLISECONDS);
-        Map<String,Object> m = new HashMap<>();
-        m.put("name","a");
-        c.save("a",m,100);
-        Map<String,Object> m2 = c.getLdapFilterInfo("a");
-        assertNotNull(m2);
-        assertTrue(m==m2);
-        m2.put("test","me");
-        System.out.println(m);
-        Thread.sleep(1000);
-    }
-
-
-}
diff --git a/services/security-service/src/test/java/com/epam/dlab/auth/core/LoginConveyorTest.java b/services/security-service/src/test/java/com/epam/dlab/auth/core/LoginConveyorTest.java
deleted file mode 100644
index 4e7406b..0000000
--- a/services/security-service/src/test/java/com/epam/dlab/auth/core/LoginConveyorTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/***************************************************************************
-
- Copyright (c) 2016, EPAM SYSTEMS INC
-
- Licensed 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 com.epam.dlab.auth.core;
-
-import com.amazonaws.services.identitymanagement.model.AccessKeyMetadata;
-import com.epam.dlab.auth.UserInfo;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.ArrayList;
-import java.util.concurrent.*;
-
-public class LoginConveyorTest {
-
-    LoginConveyor lc = new LoginConveyor(10);
-
-    @Before
-    public void createCOnveyor(){
-    }
-
-    @After
-    public void stopConveyor() {
-    }
-
-    @Test
-    public void setUserInfoDao() throws Exception {
-
-    }
-
-    @SuppressWarnings("serial")
-	@Test
-    public void startUserInfoBuild() throws Exception {
-        CompletableFuture<UserInfo> uf = lc.startUserInfoBuild("1","test");
-        UserInfo uiSource = new UserInfo("a","b");
-        uiSource.setFirstName("test");
-        uiSource.setLastName("user");
-        uiSource.addRole("admin");
-
-        lc.add("1","127.0.0.1",LoginStep.REMOTE_IP);
-        lc.add("1","OK",LoginStep.LDAP_LOGIN);
-        lc.add("1",uiSource, LoginStep.LDAP_USER_INFO);
-        lc.add("1",true, LoginStep.AWS_USER);
-        lc.add("1",new ArrayList<AccessKeyMetadata>() {
-        		{	add(new AccessKeyMetadata()
-        				.withAccessKeyId("a")
-        				.withStatus("Active"));
-        		}} ,LoginStep.AWS_KEYS);
-
-
-
-        UserInfo ui = uf.get(15, TimeUnit.SECONDS);
-        System.out.println("Future now: "+ui);
-    }
-
-    @Test
-    public void startUserInfoBuildWithoutAws() throws Exception {
-        CompletableFuture<UserInfo> uf = lc.startUserInfoBuild("1","test");
-        UserInfo uiSource = new UserInfo("a","b");
-        uiSource.setFirstName("test");
-        uiSource.setLastName("user");
-        uiSource.addRole("admin");
-
-        lc.add("1","127.0.0.1",LoginStep.REMOTE_IP);
-        lc.add("1","OK",LoginStep.LDAP_LOGIN);
-        lc.add("1",uiSource, LoginStep.LDAP_USER_INFO);
-        lc.add("1",true, LoginStep.AWS_USER);
-        lc.add("1",new ArrayList<AccessKeyMetadata>() ,LoginStep.AWS_KEYS_EMPTY);
-
-
-
-        UserInfo ui = uf.get(15, TimeUnit.SECONDS);
-        System.out.println("Future now: "+ui);
-    }
-
-    @Test(expected = CancellationException.class)
-    public void cacheTest() throws ExecutionException, InterruptedException, TimeoutException {
-        LoginCache cache = LoginCache.getInstance();
-        System.out.println("---cacheTest");
-        //Just for this test
-        cache.setDefaultBuilderTimeout(1,TimeUnit.SECONDS);
-        cache.setExpirationPostponeTime(1,TimeUnit.SECONDS);
-
-        UserInfo userInfo = new UserInfo("test","user");
-        userInfo.setFirstName("Mike");
-        userInfo.setLastName("T");
-        userInfo.addRole("tr");
-        userInfo.setAwsUser(true);
-        userInfo.addKey("a","Active");
-
-        CompletableFuture<Boolean> f = cache.createBuild("2", CacheableReference.newInstance(userInfo));
-        CompletableFuture<UserInfo> uif = cache.getFuture("2");
-        f.get();
-        //this will take at least 2 seconds
-        for(int i = 0; i < 10; i++) {
-            UserInfo ui = cache.getUserInfo("2");
-            System.out.println(i+": "+ui);
-            Thread.sleep(200);
-        }
-        //and finally will exit with timeout
-        uif.get(5,TimeUnit.SECONDS);
-    }
-
-    @Test
-    public void add() throws Exception {
-
-    }
-
-    @Test
-    public void cancel() throws Exception {
-
-    }
-
-}
\ No newline at end of file
diff --git a/services/security-service/src/test/java/com/epam/dlab/auth/dao/script/ScriptHolderTest.java b/services/security-service/src/test/java/com/epam/dlab/auth/dao/script/ScriptHolderTest.java
deleted file mode 100644
index b449ae2..0000000
--- a/services/security-service/src/test/java/com/epam/dlab/auth/dao/script/ScriptHolderTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/***************************************************************************
-
-Copyright (c) 2016, EPAM SYSTEMS INC
-
-Licensed 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 com.epam.dlab.auth.dao.script;
-
-import com.epam.dlab.auth.UserInfo;
-import org.junit.*;
-
-import javax.script.ScriptException;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.Assert.assertNotNull;
-
-public class ScriptHolderTest {
-
-	@BeforeClass
-	public static void setUpBeforeClass() throws Exception {
-	}
-
-	@AfterClass
-	public static void tearDownAfterClass() throws Exception {
-	}
-
-	@Before
-	public void setUp() throws Exception {
-	}
-
-	@After
-	public void tearDown() throws Exception {
-	}
-
-	@Test
-	public void test() throws ScriptException {
-		ScriptHolder sh = new ScriptHolder();
-		Map<String,Object> map = new HashMap<>();
-		map.put("key1", "val1");
-		map.put("key2", "val2");
-		UserInfo ui1 = sh.evalOnce("first", "javascript", "var enrichUserInfo=function(ui,context){ui.addRole(context['key1']);ui.setFirstName(\"Mike\");return ui;}").apply(new UserInfo("",""), map);
-		System.out.println(ui1);
-		assertNotNull(ui1);
-
-		UserInfo ui2 = sh.evalOnce("second", "python", "def enrichUserInfo(ui,context):\n   ui.addRole(context['key2'])\n   ui.setLastName(\"Teplitskiy\")\n   return ui\n").apply(ui1, map);
-		System.out.println(ui2);
-		assertNotNull(ui2);
-
-	}
-
-}
diff --git a/services/security-service/src/test/java/com/epam/dlab/auth/ldap/AuthTest.java b/services/security-service/src/test/java/com/epam/dlab/auth/ldap/AuthTest.java
deleted file mode 100644
index c0a1110..0000000
--- a/services/security-service/src/test/java/com/epam/dlab/auth/ldap/AuthTest.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/***************************************************************************
-
-Copyright (c) 2016, EPAM SYSTEMS INC
-
-Licensed 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 com.epam.dlab.auth.ldap;
-
-public class AuthTest {
-
-	public static void main(String[] args) {
-		System.out.println("auth test");
-
-	}
-
-}
diff --git a/services/security-service/src/test/java/com/epam/dlab/auth/ldap/BasicTest.java b/services/security-service/src/test/java/com/epam/dlab/auth/ldap/BasicTest.java
deleted file mode 100644
index c976925..0000000
--- a/services/security-service/src/test/java/com/epam/dlab/auth/ldap/BasicTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/***************************************************************************
-
-Copyright (c) 2016, EPAM SYSTEMS INC
-
-Licensed 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 com.epam.dlab.auth.ldap;
-
-import org.apache.commons.pool.PoolableObjectFactory;
-import org.apache.directory.api.ldap.model.cursor.SearchCursor;
-import org.apache.directory.api.ldap.model.entry.Entry;
-import org.apache.directory.api.ldap.model.message.SearchRequest;
-import org.apache.directory.api.ldap.model.message.SearchRequestImpl;
-import org.apache.directory.api.ldap.model.message.SearchResultEntry;
-import org.apache.directory.api.ldap.model.message.SearchScope;
-import org.apache.directory.api.ldap.model.name.Dn;
-import org.apache.directory.ldap.client.api.LdapConnection;
-import org.apache.directory.ldap.client.api.LdapConnectionConfig;
-import org.apache.directory.ldap.client.api.LdapConnectionPool;
-import org.apache.directory.ldap.client.api.ValidatingPoolableLdapConnectionFactory;
-//import org.apache.directory.ldap.client.api.PoolableLdapConnectionFactory;
-
-public class BasicTest {
-
-	public static void main(String[] args) throws Exception {
-		System.out.println("Basic test");
-		LdapConnectionConfig config = new LdapConnectionConfig();
-		config.setLdapHost( "localhost" );
-		config.setLdapPort( 3890 );
-		config.setName( "cn=admin,dc=example,dc=com" );
-		config.setCredentials( "ldap" );
-		PoolableObjectFactory<LdapConnection> poolFactory = new ValidatingPoolableLdapConnectionFactory( config );
-		LdapConnectionPool pool = new LdapConnectionPool( poolFactory );
-		pool.setTestOnBorrow( true );
-		LdapConnection con = pool.borrowObject();
-		
-		SearchRequest sr = new SearchRequestImpl();
-	    sr.setScope(SearchScope.SUBTREE);
-	    sr.addAttributes("*");
-	    sr.setTimeLimit(0);
-	    sr.setBase(new Dn("dc=example,dc=com"));
-	    sr.setFilter("(cn=Mike Teplitskiy)");
-	    sr.setMessageId(1);
-		
-//		EntryCursor cursor = con.search( "dc=example,dc=com", "(objectclass=*)", SearchScope.SUBTREE );
-		SearchCursor cursor = con.search( sr );
-//
-//		cursor.forEach(entry->{
-//	    	System.out.println( "---- DN "+entry.getDn() );
-//		    entry.forEach(attr->{
-//		    	System.out.println( "---- ATTR "+attr );
-//		    });
-//			
-//		});
-		
-		cursor.forEach(response->{
-		    if ( response instanceof SearchResultEntry )
-		    {
-		        Entry resultEntry = ( ( SearchResultEntry ) response ).getEntry();
-		        System.out.println( "---- DN "+resultEntry.getDn() );
-		        resultEntry.forEach(attr-> System.out.println( "---- ATTR "+attr ));
-		    }
-		});
-		cursor.close();
-		
-	    sr.setFilter("(cn=John Doe)");
-	    sr.setMessageId(1);
-	    cursor = con.search( sr );
-		cursor.forEach(response->{
-		    if ( response instanceof SearchResultEntry )
-		    {
-		        Entry resultEntry = ( ( SearchResultEntry ) response ).getEntry();
-		        System.out.println( "---- DN "+resultEntry.getDn() );
-		        resultEntry.forEach(attr-> System.out.println( "---- ATTR "+attr ));
-		    }
-		});
-		cursor.close();
-	    
-
-		
-		con.unBind();
-		
-		con.bind("uid=mike,ou=People,dc=example,dc=com","test");
-	    sr.setFilter("(uid=mike)");
-	    sr.setMessageId(2);
-	    cursor = con.search( sr );
-		cursor.forEach(response->{
-		    if ( response instanceof SearchResultEntry )
-		    {
-		        Entry resultEntry = ( ( SearchResultEntry ) response ).getEntry();
-		        System.out.println( "---- DN "+resultEntry.getDn() );
-		        resultEntry.forEach(attr-> System.out.println( "---- ATTR "+attr ));
-		    }
-		});
-		cursor.close();
-		
-		System.out.println("Press ENTER");
-		pool.releaseConnection(con);
-		pool.close();
-		
-	}
-
-}
diff --git a/services/security-service/src/test/java/com/epam/dlab/auth/ldap/JsonTest.java b/services/security-service/src/test/java/com/epam/dlab/auth/ldap/JsonTest.java
deleted file mode 100644
index 932f60e..0000000
--- a/services/security-service/src/test/java/com/epam/dlab/auth/ldap/JsonTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/***************************************************************************
-
-Copyright (c) 2016, EPAM SYSTEMS INC
-
-Licensed 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 com.epam.dlab.auth.ldap;
-
-import com.epam.dlab.auth.UserInfo;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.junit.*;
-
-import java.io.IOException;
-
-import static org.junit.Assert.assertNotNull;
-
-public class JsonTest {
-
-	@BeforeClass
-	public static void setUpBeforeClass() throws Exception {
-	}
-
-	@AfterClass
-	public static void tearDownAfterClass() throws Exception {
-	}
-
-	@Before
-	public void setUp() throws Exception {
-	}
-
-	@After
-	public void tearDown() throws Exception {
-	}
-
-	@Test
-	public void test1() throws IOException {
-		ObjectMapper om = new ObjectMapper();
-		String jv = om.writeValueAsString(new UserInfo("user","info"));
-		assertNotNull(jv);
-		System.out.println(jv);
-		UserInfo ui = om.readerFor(UserInfo.class).readValue(jv);
-		assertNotNull(ui);
-		System.out.println(ui);
-		//String js = "{\\\"username\\\":\"user\",\\\"access_token\\\":\"info\",\\\"firstName\\\":null,\\\"lastName\\\":null,\\\"roles\\\":[]}";
-		//System.out.println(js);
-		//UserInfo ui2 = om.readerFor(UserInfo.class).readValue(js);
-		
-		
-	}
-	@Test
-	public void test2() throws IOException {
-		ObjectMapper om = new ObjectMapper();
-		UserInfo ui = new UserInfo("user","info");
-		ui.setFirstName("first");
-		ui.setLastName("last");
-		ui.addRole("r1");
-		ui.addRole("r2");
-		String jv = om.writeValueAsString(ui);
-		assertNotNull(jv);
-		System.out.println(jv);
-		UserInfo ui2 = om.readerFor(UserInfo.class).readValue(jv);
-		assertNotNull(ui2);
-		System.out.println(ui2);
-		//String js = "{\\\"username\\\":\"user\",\\\"access_token\\\":\"info\",\\\"firstName\\\":null,\\\"lastName\\\":null,\\\"roles\\\":[]}";
-		//System.out.println(js);
-		//UserInfo ui2 = om.readerFor(UserInfo.class).readValue(js);
-		
-		
-	}
-
-}
diff --git a/services/security-service/src/test/java/com/epam/dlab/auth/ldap/ScriptList.java b/services/security-service/src/test/java/com/epam/dlab/auth/ldap/ScriptList.java
deleted file mode 100644
index 75763a1..0000000
--- a/services/security-service/src/test/java/com/epam/dlab/auth/ldap/ScriptList.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/***************************************************************************
-
-Copyright (c) 2016, EPAM SYSTEMS INC
-
-Licensed 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 com.epam.dlab.auth.ldap;
-
-import com.epam.dlab.auth.UserInfo;
-
-import javax.script.*;
-import java.util.List;
-
-public class ScriptList {
-
-    public static void main( String[] args ) throws ScriptException, NoSuchMethodException {
-
-        ScriptEngineManager mgr = new ScriptEngineManager();
-        List<ScriptEngineFactory> factories = mgr.getEngineFactories();
-
-        for (ScriptEngineFactory factory : factories) {
-
-            System.out.println("ScriptEngineFactory Info");
-
-            String engName = factory.getEngineName();
-            String engVersion = factory.getEngineVersion();
-            String langName = factory.getLanguageName();
-            String langVersion = factory.getLanguageVersion();
-
-            System.out.printf("\tScript Engine: %s (%s)%n", engName, engVersion);
-
-            List<String> engNames = factory.getNames();
-            for(String name : engNames) {
-                System.out.printf("\tEngine Alias: %s%n", name);
-            }
-
-            System.out.printf("\tLanguage: %s (%s)%n", langName, langVersion);
-
-        }
-        
-        ScriptEngine python = mgr.getEngineByName("python");
-        ScriptEngine js = mgr.getEngineByName("javascript");
-        python.eval("print \"Hello Python!\"");
-
-        js.eval("print('Hello JavaScript!');");
-
-        Invocable ijs = (Invocable) js;
-        Invocable ipy = (Invocable) python;
-        
-        js.eval("var f=function(ui){print(ui);ui.setFirstName(\"Mike\");return ui;};");
-        
-        Object res = ijs.invokeFunction("f", new UserInfo("test", "pass"));
-        System.out.println(res);
-        
-        python.eval("def f(ui):\n   print ui\n   ui.setLastName(\"Teplitskiy\")\n   return ui\n");
-        Object res2 = ipy.invokeFunction("f", new UserInfo("test", "pass"));
-        System.out.println(res2);        
-     
-        
-        
-    }
-
-}
\ No newline at end of file
diff --git a/services/security-service/src/test/java/com/epam/dlab/auth/service/impl/LdapAuthenticationServiceTest.java b/services/security-service/src/test/java/com/epam/dlab/auth/service/impl/LdapAuthenticationServiceTest.java
new file mode 100644
index 0000000..ac4a258
--- /dev/null
+++ b/services/security-service/src/test/java/com/epam/dlab/auth/service/impl/LdapAuthenticationServiceTest.java
@@ -0,0 +1,138 @@
+/*
+ *
+ *  * Copyright (c) 2018, EPAM SYSTEMS INC
+ *  *
+ *  * Licensed 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 com.epam.dlab.auth.service.impl;
+
+import com.epam.dlab.auth.UserInfo;
+import com.epam.dlab.auth.UserInfoDAO;
+import com.epam.dlab.auth.UserVerificationService;
+import com.epam.dlab.auth.dao.LdapUserDAO;
+import com.epam.dlab.auth.dto.UserCredentialDTO;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import java.util.Optional;
+
+import static org.junit.Assert.*;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.refEq;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class LdapAuthenticationServiceTest {
+
+	private static final String TOKEN = "token123";
+	private static final String USER = "user";
+	private static final String PASSWORD = "password";
+	@Mock
+	private LdapUserDAO ldapUserDAO;
+	@Mock
+	private UserInfoDAO userInfoDAO;
+	@Mock
+	private UserVerificationService verificationService;
+	@InjectMocks
+	private LdapAuthenticationService ldapAuthenticationService;
+
+	@Test
+	public void getUserInfo() {
+
+		when(userInfoDAO.getUserInfoByAccessToken(anyString())).thenReturn(Optional.of(userInfo()));
+		final Optional<UserInfo> userInfo = ldapAuthenticationService.getUserInfo(TOKEN);
+
+		assertTrue(userInfo.isPresent());
+		assertEquals(USER.toLowerCase(), userInfo.get().getName());
+		assertEquals(TOKEN, userInfo.get().getAccessToken());
+
+		verify(userInfoDAO).getUserInfoByAccessToken(TOKEN);
+		verify(userInfoDAO).updateUserInfoTTL(eq(TOKEN), refEq(userInfo()));
+		verifyNoMoreInteractions(userInfoDAO);
+	}
+
+	@Test
+	public void getUserInfoWhenUserNotFound() {
+
+		when(userInfoDAO.getUserInfoByAccessToken(anyString())).thenReturn(Optional.empty());
+		final Optional<UserInfo> userInfo = ldapAuthenticationService.getUserInfo(TOKEN);
+
+		assertFalse(userInfo.isPresent());
+
+		verify(userInfoDAO).getUserInfoByAccessToken(TOKEN);
+		verifyNoMoreInteractions(userInfoDAO);
+	}
+
+	@Test
+	public void loginWithoutAccessToken() {
+
+		when(ldapUserDAO.getUserInfo(anyString(), anyString())).thenReturn(userInfo());
+		final Optional<UserInfo> userInfo = ldapAuthenticationService.login(getCredentialDTO());
+
+		assertTrue(userInfo.isPresent());
+		assertEquals(USER, userInfo.get().getName());
+		assertNotNull(userInfo.get().getAccessToken());
+
+		verify(verificationService).verify(refEq(userInfo()));
+		verify(ldapUserDAO).getUserInfo(USER, PASSWORD);
+		verify(ldapUserDAO).getUserGroups(refEq(userInfo()));
+		verify(userInfoDAO).saveUserInfo(refEq(userInfo().withToken(TOKEN), "accessToken"));
+		verifyNoMoreInteractions(ldapUserDAO, userInfoDAO);
+	}
+
+	@Test
+	public void loginWithAccessToken() {
+
+		when(userInfoDAO.getUserInfoByAccessToken(anyString())).thenReturn(Optional.of(userInfo()));
+		final UserCredentialDTO credentialDTO = getCredentialDTO();
+		credentialDTO.setAccessToken(TOKEN);
+		final Optional<UserInfo> userInfo = ldapAuthenticationService.login(credentialDTO);
+
+		assertTrue(userInfo.isPresent());
+		assertEquals(USER, userInfo.get().getName());
+		assertNotNull(userInfo.get().getAccessToken());
+
+		verify(userInfoDAO).getUserInfoByAccessToken(TOKEN);
+		verify(userInfoDAO).updateUserInfoTTL(eq(TOKEN), refEq(userInfo()));
+		verifyNoMoreInteractions(userInfoDAO);
+		verifyZeroInteractions(ldapUserDAO, verificationService);
+	}
+
+	@Test
+	public void logout() {
+
+		ldapAuthenticationService.logout(TOKEN);
+
+		verify(userInfoDAO).deleteUserInfo(TOKEN);
+		verifyNoMoreInteractions(userInfoDAO);
+		verifyZeroInteractions(ldapUserDAO);
+	}
+
+	private UserInfo userInfo() {
+		return new UserInfo(USER, null);
+	}
+
+	private UserCredentialDTO getCredentialDTO() {
+		final UserCredentialDTO dto = new UserCredentialDTO();
+		dto.setUsername(USER);
+		dto.setPassword(PASSWORD);
+		return dto;
+	}
+
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@dlab.apache.org
For additional commands, e-mail: commits-help@dlab.apache.org