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:12 UTC

[incubator-dlab] branch ldab_refactored created (now 9260408)

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

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


      at 9260408  EPMCDLAB-000 refactored ldap authentication

This branch includes the following new commits:

     new 9260408  EPMCDLAB-000 refactored ldap authentication

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



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


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

Posted by bh...@apache.org.
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