All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.gravitee.management.idp.ldap.lookup.LdapIdentityLookup Maven / Gradle / Ivy

There is a newer version: 1.30.31
Show newest version
/**
 * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
 *
 * 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 io.gravitee.management.idp.ldap.lookup;

import io.gravitee.management.idp.api.identity.IdentityLookup;
import io.gravitee.management.idp.api.identity.IdentityReference;
import io.gravitee.management.idp.api.identity.User;
import io.gravitee.management.idp.ldap.LdapIdentityProvider;
import io.gravitee.management.idp.ldap.lookup.spring.LdapIdentityLookupConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;
import org.springframework.ldap.LimitExceededException;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.AbstractContextMapper;
import org.springframework.ldap.filter.*;
import org.springframework.ldap.query.LdapQuery;
import org.springframework.ldap.query.LdapQueryBuilder;
import org.springframework.ldap.query.SearchScope;
import org.springframework.ldap.support.LdapNameBuilder;

import javax.naming.ldap.LdapName;
import java.util.Collection;
import java.util.Collections;

/**
 * @author David BRASSELY (david.brassely at graviteesource.com)
 * @author GraviteeSource Team
 */
@Import(LdapIdentityLookupConfiguration.class)
public class LdapIdentityLookup implements IdentityLookup, InitializingBean {

    private final Logger LOGGER = LoggerFactory.getLogger(LdapIdentityLookup.class);

    private final static String LDAP_DEFAULT_OBJECT_CLASS = "person";

    private final static String LDAP_ATTRIBUTE_COMMONNAME = "cn";
    private final static String LDAP_ATTRIBUTE_USERID = "uid";
    private final static String LDAP_ATTRIBUTE_GIVENNAME = "givenName";
    private final static String LDAP_ATTRIBUTE_SURNAME = "sn";
    private final static String LDAP_ATTRIBUTE_MAIL = "mail";
    private final static String LDAP_ATTRIBUTE_DISPLAYNAME = "displayName";

    @Autowired
    private LdapTemplate ldapTemplate;

    @Autowired
    private Environment environment;

    private String identifierAttribute = "uid";

    private LdapName baseDn;

    @Override
    public void afterPropertiesSet() throws Exception {
        String searchFilter = environment.getProperty("user-search-filter");
        LOGGER.debug("Looking for a LDAP user's identifier using search filter [{}]", searchFilter);

        if (searchFilter != null) {
            // Search filter can be uid={0} or mail={0}
            identifierAttribute = searchFilter.split("=")[0];
        }

        LOGGER.info("User identifier is based on the [{}] attribute", identifierAttribute);

        // Base DN to search for users
        baseDn = LdapNameBuilder
                .newInstance(environment.getProperty("context-source-base"))
                .add(environment.getProperty("user-search-base"))
                .build();

        LOGGER.info("User search is based on DN [{}]", baseDn);
    }

    @Override
    public Collection search(String query) {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        try {
            Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
            Filter classFilter = new EqualsFilter("objectclass",
                    environment.getProperty(
                            "user-search-objectclass",
                            LDAP_DEFAULT_OBJECT_CLASS));

            Filter queryFilter = new OrFilter()
                    .or(new WhitespaceWildcardsFilter(LDAP_ATTRIBUTE_COMMONNAME, query))
                    .or(new EqualsFilter(LDAP_ATTRIBUTE_USERID, query));

            LdapQuery ldapQuery = LdapQueryBuilder
                    .query()
                    .base(baseDn)
                    .countLimit(20)
                    .timeLimit(5000)
                    .searchScope(SearchScope.SUBTREE)
                    .attributes(
                            LDAP_ATTRIBUTE_GIVENNAME,
                            LDAP_ATTRIBUTE_SURNAME,
                            LDAP_ATTRIBUTE_MAIL,
                            LDAP_ATTRIBUTE_DISPLAYNAME)
                    .filter(new AndFilter().and(classFilter).and(queryFilter));


            return ldapTemplate.search(ldapQuery, USER_CONTEXT_MAPPER);
        } catch(LimitExceededException lee) {
            LOGGER.info("Too much results while searching for [" + query +"]. Returns an empty list.");
            return Collections.emptyList();
        } finally {
            Thread.currentThread().setContextClassLoader(classLoader);
        }
    }

    @Override
    public boolean canHandle(IdentityReference identityReference) {
        return LdapIdentityProvider.PROVIDER_TYPE.equalsIgnoreCase(identityReference.getSource());
    }

    @Override
    public User retrieve(IdentityReference identityReference) {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        try {
            Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
            return ldapTemplate.lookup(
                    identityReference.getReference(),
                    new String [] {
                            identifierAttribute, LDAP_ATTRIBUTE_GIVENNAME, LDAP_ATTRIBUTE_SURNAME,
                            LDAP_ATTRIBUTE_MAIL, LDAP_ATTRIBUTE_DISPLAYNAME
                    },
                    USER_CONTEXT_MAPPER);
        } catch (final NameNotFoundException nnfe) {
            return null;
        } finally {
            Thread.currentThread().setContextClassLoader(classLoader);
        }
    }

    private final ContextMapper USER_CONTEXT_MAPPER = new AbstractContextMapper() {

        @Override
        protected User doMapFromContext(DirContextOperations ctx) {
            LdapUser user = new LdapUser(ctx.getDn().toString());
            user.setFirstname(ctx.getStringAttribute(LDAP_ATTRIBUTE_GIVENNAME));
            user.setLastname(ctx.getStringAttribute(LDAP_ATTRIBUTE_SURNAME));
            user.setEmail(ctx.getStringAttribute(LDAP_ATTRIBUTE_MAIL));
            user.setDisplayName(ctx.getStringAttribute(LDAP_ATTRIBUTE_DISPLAYNAME));
            user.setUsername(ctx.getStringAttribute(LdapIdentityLookup.this.identifierAttribute));

            if (user.getDisplayName() == null) {
                user.setDisplayName(user.getFirstname() + ' ' + user.getLastname());
            }

            return user;
        }
    };
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy