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 <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to