>
> Dave I have written my .own classes handler,configuration(please refer to 
> the attached files).What i observe is My handler is getting registered 
> properly but when i give the credentials the method "
> authenticateUsernamePasswordInternal" is not getting called. properties 
> are same as above .

-- 
- Website: https://apereo.github.io/cas
- Gitter Chatroom: https://gitter.im/apereo/cas
- List Guidelines: https://goo.gl/1VRrw7
- Contributions: https://goo.gl/mh7qDG
--- 
You received this message because you are subscribed to the Google Groups "CAS 
Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to cas-user+unsubscr...@apereo.org.
To view this discussion on the web visit 
https://groups.google.com/a/apereo.org/d/msgid/cas-user/8179af60-49fd-44fc-bcb4-6bd00adae092%40apereo.org.
package org.apereo.cas.config;

import com.google.common.collect.Multimap;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.authentication.AuthenticationEventExecutionPlanConfigurer;
import org.apereo.cas.authentication.AuthenticationHandler;
import org.apereo.cas.authentication.CoreAuthenticationUtils;
import org.apereo.cas.authentication.LdapAuthenticationHandler;
import org.apereo.cas.authentication.principal.DefaultPrincipalFactory;
import org.apereo.cas.authentication.principal.PrincipalFactory;
import org.apereo.cas.authentication.principal.PrincipalNameTransformerUtils;
import org.apereo.cas.authentication.principal.PrincipalResolver;
import org.apereo.cas.authentication.support.DefaultLdapLdapAccountStateHandler;
import org.apereo.cas.authentication.support.DefaultLdapPasswordPolicyHandlingStrategy;
import org.apereo.cas.authentication.support.GroovyLdapPasswordPolicyHandlingStrategy;
import org.apereo.cas.authentication.support.LdapPasswordPolicyConfiguration;
import org.apereo.cas.authentication.support.LdapPasswordPolicyHandlingStrategy;
import org.apereo.cas.authentication.support.OptionalWarningLdapLdapAccountStateHandler;
import org.apereo.cas.authentication.support.RejectResultCodeLdapPasswordPolicyHandlingStrategy;
import org.apereo.cas.authentication.support.password.PasswordEncoderUtils;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.configuration.model.core.authentication.PasswordPolicyProperties;
import org.apereo.cas.configuration.model.support.ldap.LdapAuthenticationProperties;
import org.apereo.cas.services.ServicesManager;
import org.apereo.cas.util.CollectionUtils;
import org.apereo.cas.util.LdapUtils;
import org.ldaptive.auth.AuthenticationResponseHandler;
import org.ldaptive.auth.Authenticator;
import org.ldaptive.auth.ext.ActiveDirectoryAuthenticationResponseHandler;
import org.ldaptive.auth.ext.EDirectoryAuthenticationResponseHandler;
import org.ldaptive.auth.ext.FreeIPAAuthenticationResponseHandler;
import org.ldaptive.auth.ext.PasswordExpirationAuthenticationResponseHandler;
import org.ldaptive.auth.ext.PasswordPolicyAuthenticationResponseHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.core.io.Resource;

import java.time.Period;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;

/**
 * This is {@link LdapAuthenticationConfiguration} that attempts to create
 * relevant authentication handlers for LDAP.
 *
 * @author Misagh Moayyed
 * @author Dmitriy Kopylenko
 * @since 5.0.0
 */
@Configuration("lTldapAuthenticationConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
@Slf4j
public class LTLdapAuthenticationConfiguration {


    @Autowired
    private CasConfigurationProperties casProperties;

    @Autowired
    @Qualifier("personDirectoryPrincipalResolver")
    private PrincipalResolver personDirectoryPrincipalResolver;

    @Autowired
    @Qualifier("servicesManager")
    private ServicesManager servicesManager;

    @ConditionalOnMissingBean(name = "ldapPrincipalFactory")
    @Bean
    public PrincipalFactory ldapPrincipalFactory() {
        return new DefaultPrincipalFactory();
    }

    @ConditionalOnMissingBean(name = "ldapAuthenticationHandlers")
    @Bean
    @RefreshScope
    public Collection<AuthenticationHandler> ldapAuthenticationHandlers() {
        final Collection<AuthenticationHandler> handlers = new HashSet<>();
        System.out.println("================================");
        System.out.println("In Collection Handlers");
        System.out.println("================================");
        casProperties.getAuthn().getLdap()
                .stream()
                .filter(ldapInstanceConfigurationPredicate())
                .forEach(l -> {
                    final Multimap<String, String> multiMapAttributes = 
                            CoreAuthenticationUtils.transformPrincipalAttributesListIntoMultiMap(l.getPrincipalAttributeList());
                    
                    
                    final Authenticator authenticator = LdapUtils.newLdaptiveAuthenticator(l);
                    System.out.println("=====================Multimap=================================");
                    System.out.println(multiMapAttributes.keySet());

                    
                    final LdapPasswordPolicyHandlingStrategy strategy = createLdapPasswordPolicyHandlingStrategy(l);

                    
                    final LTLdapAuthenticationHandler handler = new LTLdapAuthenticationHandler(l.getName(),
                            servicesManager, ldapPrincipalFactory(), l.getOrder(), authenticator, strategy);
                    handler.setCollectDnAttribute(l.isCollectDnAttribute());

                    final List<String> additionalAttributes = l.getAdditionalAttributes();
                    if (StringUtils.isNotBlank(l.getPrincipalAttributeId())) {
                        additionalAttributes.add(l.getPrincipalAttributeId());
                    }
                    if (StringUtils.isNotBlank(l.getPrincipalDnAttributeName())) {
                        handler.setPrincipalDnAttributeName(l.getPrincipalDnAttributeName());
                    }
                    handler.setAllowMultiplePrincipalAttributeValues(l.isAllowMultiplePrincipalAttributeValues());
                    handler.setAllowMissingPrincipalAttributeValue(l.isAllowMissingPrincipalAttributeValue());
                    handler.setPasswordEncoder(PasswordEncoderUtils.newPasswordEncoder(l.getPasswordEncoder()));
                    handler.setPrincipalNameTransformer(PrincipalNameTransformerUtils.newPrincipalNameTransformer(l.getPrincipalTransformation()));

                    if (StringUtils.isNotBlank(l.getCredentialCriteria())) {
                        
                        handler.setCredentialSelectionPredicate(CoreAuthenticationUtils.newCredentialSelectionPredicate(l.getCredentialCriteria()));
                    }

                    if (StringUtils.isBlank(l.getPrincipalAttributeId())) {
                        
                    } else {
                        handler.setPrincipalIdAttribute(l.getPrincipalAttributeId());
                        
                    }

                    if (l.getPasswordPolicy().isEnabled()) {
                       
                        final LdapPasswordPolicyConfiguration cfg = createLdapPasswordPolicyConfiguration(l, authenticator, multiMapAttributes);
                        handler.setPasswordPolicyConfiguration(cfg);
                    }

                    // final Map<String, Collection<String>> attributes = CollectionUtils.wrap(multiMapAttributes);
                    // handler.setPrincipalAttributeMap(attributes);
                    System.out.println("===========Collection Utils================");
                    System.out.println(CollectionUtils.wrap(multiMapAttributes));

                   
                    handler.initialize();
                    handlers.add(handler);
                });
        return handlers;
    }


    private static Predicate<LdapAuthenticationProperties> ldapInstanceConfigurationPredicate() {
        return l -> {
            if (l.getType() == null) {
               
                return false;
            }
            if (StringUtils.isBlank(l.getLdapUrl())) {
               
                return false;
            }
            return true;
        };
    }

    private LdapPasswordPolicyHandlingStrategy createLdapPasswordPolicyHandlingStrategy(final LdapAuthenticationProperties l) {
        // if (l.getPasswordPolicy().getStrategy() == PasswordPolicyProperties.PasswordPolicyHandlingOptions.REJECT_RESULT_CODE) {
        //     LOGGER.debug("Created LDAP password policy handling strategy based on blacklisted authentication result codes");
        //     return new RejectResultCodeLdapPasswordPolicyHandlingStrategy();
        // }
        
        // final Resource location = l.getPasswordPolicy().getGroovy().getLocation();
        // if (l.getPasswordPolicy().getStrategy() == PasswordPolicyProperties.PasswordPolicyHandlingOptions.GROOVY && location != null) {
        //     LOGGER.debug("Created LDAP password policy handling strategy based on Groovy script [{}]", location);
        //     return new GroovyLdapPasswordPolicyHandlingStrategy(location);
        // }

        // LOGGER.debug("Created default LDAP password policy handling strategy");
        return new DefaultLdapPasswordPolicyHandlingStrategy();
    }

    private LdapPasswordPolicyConfiguration createLdapPasswordPolicyConfiguration(final LdapAuthenticationProperties l,
                                                                                  final Authenticator authenticator,
                                                                                  final Multimap<String, String> attributes) {
        final LdapPasswordPolicyConfiguration cfg =
            new LdapPasswordPolicyConfiguration(l.getPasswordPolicy());
        final Set<AuthenticationResponseHandler> handlers = new HashSet<>();

        final String customPolicyClass = l.getPasswordPolicy().getCustomPolicyClass();
        if (StringUtils.isNotBlank(customPolicyClass)) {
            try {
                
                final Class<AuthenticationResponseHandler> clazz = (Class<AuthenticationResponseHandler>)
                        Class.forName(customPolicyClass);
                handlers.add(clazz.getDeclaredConstructor().newInstance());
            } catch (final Exception e) {
               
            }
        }
        // LOGGER.debug("Password policy authentication response handler is set to accommodate directory type: [{}]", l.getPasswordPolicy().getType());
        switch (l.getPasswordPolicy().getType()) {
            case AD:
                handlers.add(new ActiveDirectoryAuthenticationResponseHandler(Period.ofDays(cfg.getPasswordWarningNumberOfDays())));
                Arrays.stream(ActiveDirectoryAuthenticationResponseHandler.ATTRIBUTES).forEach(a -> {
                    
                    attributes.put(a, a);
                });
                break;
            case EDirectory:
                Arrays.stream(EDirectoryAuthenticationResponseHandler.ATTRIBUTES).forEach(a -> {
                   
                    attributes.put(a, a);
                });
                handlers.add(new EDirectoryAuthenticationResponseHandler(Period.ofDays(cfg.getPasswordWarningNumberOfDays())));
                break;
            default:
                handlers.add(new PasswordPolicyAuthenticationResponseHandler());
                handlers.add(new PasswordExpirationAuthenticationResponseHandler());
                break;
        }
        authenticator.setAuthenticationResponseHandlers((AuthenticationResponseHandler[]) handlers.toArray(new AuthenticationResponseHandler[handlers.size()]));

        

        if (StringUtils.isNotBlank(l.getPasswordPolicy().getWarningAttributeName())
                && StringUtils.isNotBlank(l.getPasswordPolicy().getWarningAttributeValue())) {

            final OptionalWarningLdapLdapAccountStateHandler accountHandler = new OptionalWarningLdapLdapAccountStateHandler();
            accountHandler.setDisplayWarningOnMatch(l.getPasswordPolicy().isDisplayWarningOnMatch());
            accountHandler.setWarnAttributeName(l.getPasswordPolicy().getWarningAttributeName());
            accountHandler.setWarningAttributeValue(l.getPasswordPolicy().getWarningAttributeValue());
            accountHandler.setAttributesToErrorMap(l.getPasswordPolicy().getPolicyAttributes());
            cfg.setAccountStateHandler(accountHandler);
            
        } else {
            final DefaultLdapLdapAccountStateHandler accountHandler = new DefaultLdapLdapAccountStateHandler();
            accountHandler.setAttributesToErrorMap(l.getPasswordPolicy().getPolicyAttributes());
            cfg.setAccountStateHandler(accountHandler);
           
        }
        return cfg;
    }

    @ConditionalOnMissingBean(name = "lTldapAuthenticationEventExecutionPlanConfigurer")
    @Bean
    public AuthenticationEventExecutionPlanConfigurer lTldapAuthenticationEventExecutionPlanConfigurer() {
        System.out.println("================================");
        System.out.println("In Planregister");
        System.out.println("====================================");
        return plan -> ldapAuthenticationHandlers().forEach(handler -> {
           
            plan.registerAuthenticationHandlerWithPrincipalResolver(handler, personDirectoryPrincipalResolver);
        });
    }
}
package org.apereo.cas.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apereo.cas.authentication.MessageDescriptor;
import org.apereo.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
import org.apereo.cas.authentication.principal.Principal;
import org.apereo.cas.authentication.principal.PrincipalFactory;
import org.apereo.cas.authentication.support.LdapPasswordPolicyConfiguration;
import org.apereo.cas.authentication.support.LdapPasswordPolicyHandlingStrategy;
import org.apereo.cas.authentication.AuthenticationHandlerExecutionResult;
import org.apereo.cas.authentication.PreventedException;
import org.apereo.cas.authentication.UsernamePasswordCredential;
import org.apereo.cas.services.ServicesManager;
import org.apereo.cas.util.CollectionUtils;
import org.ldaptive.LdapAttribute;
import org.ldaptive.LdapEntry;
import org.ldaptive.LdapException;
import org.ldaptive.ReturnAttributes;
import org.ldaptive.auth.AuthenticationRequest;
import org.ldaptive.auth.AuthenticationResponse;
import org.ldaptive.auth.AuthenticationResultCode;
import org.ldaptive.auth.Authenticator;

import javax.annotation.PostConstruct;
import javax.security.auth.login.AccountNotFoundException;
import javax.security.auth.login.FailedLoginException;
import javax.security.auth.login.LoginException;
import java.security.GeneralSecurityException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;


@Slf4j
public class LTLdapAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler {

    
    /**
     * Mapping of LDAP attribute name to principal attribute name.
     */
    protected Map<String, Collection<String>> principalAttributeMap = new HashMap<>();

    /**
     * Decide how to execute password policy handling, if at all.
     */
    protected LdapPasswordPolicyHandlingStrategy passwordPolicyHandlingStrategy;
    
    /**
     * Performs LDAP authentication given username/password.
     **/
    private final Authenticator authenticator;

    /**
     * Name of attribute to be used for resolved principal.
     */
    private String principalIdAttribute;

    /**
     * Flag indicating whether multiple values are allowed fo principalIdAttribute.
     */
    private boolean allowMultiplePrincipalAttributeValues;

    /**
     * Flag to indicate whether CAS should block authentication
     * if a specific/configured principal id attribute is not found.
     */
    private boolean allowMissingPrincipalAttributeValue = true;

    /**
     * Set of LDAP attributes fetch from an entry as part of the authentication process.
     */
    private String[] authenticatedEntryAttributes = ReturnAttributes.NONE.value();

    private boolean collectDnAttribute;
    /**
     * Name of attribute to be used for principal's DN.
     */
    private String principalDnAttributeName = "principalLdapDn";

    /**
     * Creates a new authentication handler that delegates to the given authenticator.
     *
     * @param name             the name
     * @param servicesManager  the services manager
     * @param principalFactory the principal factory
     * @param order            the order
     * @param authenticator    Ldaptive authenticator component.
     * @param strategy         the strategy
     */
    public LTLdapAuthenticationHandler(final String name, final ServicesManager servicesManager, final PrincipalFactory principalFactory,
                                     final Integer order, final Authenticator authenticator, final LdapPasswordPolicyHandlingStrategy strategy) {
        super(name, servicesManager, principalFactory, order);
        this.authenticator = authenticator;
        this.passwordPolicyHandlingStrategy = strategy;
        System.out.println("==================================");
        System.out.println("In Handler");
        System.out.println("====================================");
    }

    /**
     * Sets the name of the LDAP principal attribute whose value should be used for the
     * principal ID.
     *
     * @param attributeName LDAP attribute name.
     */
    public void setPrincipalIdAttribute(final String attributeName) {
        this.principalIdAttribute = attributeName;
    }

    /**
     * Sets the name of the principal's dn attribute.
     *
     * @param principalDnAttributeName principal's DN attribute name.
     */
    public void setPrincipalDnAttributeName(final String principalDnAttributeName) {
        this.principalDnAttributeName = principalDnAttributeName;
    }

    /**
     * Sets a flag that determines whether multiple values are allowed for the {@link #principalIdAttribute}.
     * This flag only has an effect if {@link #principalIdAttribute} is configured. If multiple values are detected
     * when the flag is false, the first value is used and a warning is logged. If multiple values are detected
     * when the flag is true, an exception is raised.
     *
     * @param allowed True to allow multiple principal ID attribute values, false otherwise.
     */
    public void setAllowMultiplePrincipalAttributeValues(final boolean allowed) {
        this.allowMultiplePrincipalAttributeValues = allowed;
    }

    /**
     * Sets the mapping of additional principal attributes where the key is the LDAP attribute
     * name and the value is the principal attribute name. The key set defines the set of
     * attributes read from the LDAP entry at authentication time. Note that the principal ID attribute
     * should not be listed among these attributes.
     *
     * @param attributeNameMap Map of LDAP attribute name to principal attribute name.
     */
    public void setPrincipalAttributeMap(final Map<String, Collection<String>> attributeNameMap) {
        this.principalAttributeMap = attributeNameMap;
    }

    @Override
    protected AuthenticationHandlerExecutionResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential upc,
                                                                                        final String originalPassword)
        throws GeneralSecurityException, PreventedException {
        final AuthenticationResponse response;
        System.out.println("==================================");
        System.out.println("In Main Method");
        System.out.println(upc.getUsername());
        System.out.println(upc.getPassword());
        System.out.println("====================================");
        try {
            final AuthenticationRequest request = new AuthenticationRequest(upc.getUsername(),
                    new org.ldaptive.Credential(upc.getPassword()), authenticatedEntryAttributes);
            response = authenticator.authenticate(request);
            System.out.println(response);
        } catch (final LdapException e) {
           
            throw new PreventedException("Unexpected LDAP error", e);
        }
        

        if (!passwordPolicyHandlingStrategy.supports(response)) {
           
            throw new FailedLoginException("Invalid credentials");
        }

        
        final List<MessageDescriptor> messageList = passwordPolicyHandlingStrategy.handle(response,
                (LdapPasswordPolicyConfiguration) getPasswordPolicyConfiguration());
        
        if (response.getResult()) {
            
            final Principal principal = createPrincipal(upc.getUsername(), response.getLdapEntry());
            return createHandlerResult(upc, principal, messageList);
        }

        if (AuthenticationResultCode.DN_RESOLUTION_FAILURE == response.getAuthenticationResultCode()) {
            
            throw new AccountNotFoundException(upc.getUsername() + " not found.");
        }
        throw new FailedLoginException("Invalid credentials");
    }

    /**
     * Creates a CAS principal with attributes if the LDAP entry contains principal attributes.
     *
     * @param username  Username that was successfully authenticated which is used for principal ID when
     *                  {@link #setPrincipalIdAttribute(String)} is not specified.
     * @param ldapEntry LDAP entry that may contain principal attributes.
     * @return Principal if the LDAP entry contains at least a principal ID attribute value, null otherwise.
     * @throws LoginException On security policy errors related to principal creation.
     */
    protected Principal createPrincipal(final String username, final LdapEntry ldapEntry) throws LoginException {
       
        final String id = getLdapPrincipalIdentifier(username, ldapEntry);
        

        final Map<String, Object> attributeMap = collectAttributesForLdapEntry(ldapEntry, id);

       
        return this.principalFactory.createPrincipal(id, attributeMap);
    }

    /**
     * Collect attributes for ldap entry.
     *
     * @param ldapEntry the ldap entry
     * @param username  the username
     * @return the map
     */
    protected Map<String, Object> collectAttributesForLdapEntry(final LdapEntry ldapEntry, final String username) {
        final Map<String, Object> attributeMap = new LinkedHashMap<>(this.principalAttributeMap.size());
        
        this.principalAttributeMap.forEach((key, attributeNames) -> {
            final LdapAttribute attr = ldapEntry.getAttribute(key);
            if (attr != null) {
                

                if (attributeNames.isEmpty()) {
                    
                    attributeMap.put(key, CollectionUtils.wrap(attr.getStringValues()));
                } else {
                    attributeNames.forEach(s -> {
                       
                        attributeMap.put(s, CollectionUtils.wrap(attr.getStringValues()));
                    });
                }
            } else {
                
            }
        });

        if (this.collectDnAttribute) {
           
            attributeMap.put(this.principalDnAttributeName, ldapEntry.getDn());
        }
        
        return attributeMap;
    }

    /**
     * Gets ldap principal identifier. If the principal id attribute is defined, it's retrieved.
     * If no attribute value is found, a warning is generated and the provided username is used instead.
     * If no attribute is defined, username is used instead.
     *
     * @param username  the username
     * @param ldapEntry the ldap entry
     * @return the ldap principal identifier
     * @throws LoginException in case the principal id cannot be determined.
     */
    protected String getLdapPrincipalIdentifier(final String username, final LdapEntry ldapEntry) throws LoginException {
        if (StringUtils.isNotBlank(this.principalIdAttribute)) {
            final LdapAttribute principalAttr = ldapEntry.getAttribute(this.principalIdAttribute);
            if (principalAttr == null || principalAttr.size() == 0) {

                if (this.allowMissingPrincipalAttributeValue) {
                    
                    return username;
                }
                
                throw new LoginException("Principal id attribute is not found for " + principalAttr);
            }

            if (principalAttr.size() > 1) {
                if (!this.allowMultiplePrincipalAttributeValues) {
                    throw new LoginException("Multiple principal values are not allowed: " + principalAttr);
                }
                
            }
            
            return principalAttr.getStringValue();
        }

       
        return username;
    }

    public void setAllowMissingPrincipalAttributeValue(final boolean allowMissingPrincipalAttributeValue) {
        this.allowMissingPrincipalAttributeValue = allowMissingPrincipalAttributeValue;
    }

    /**
     * Initialize the handler, setup the authentication entry attributes.
     */
    @PostConstruct
    public void initialize() {
        /*
         * Use a set to ensure we ignore duplicates.
         */
        final Set<String> attributes = new HashSet<>();

       
        if (StringUtils.isNotBlank(this.principalIdAttribute)) {
           
            attributes.add(this.principalIdAttribute);
        }
        if (this.principalAttributeMap != null && !this.principalAttributeMap.isEmpty()) {
            final Set<String> attrs = this.principalAttributeMap.keySet();
            attributes.addAll(attrs);
            
        }

        if (authenticator.getReturnAttributes() != null) {
            final List<String> authenticatorAttributes = CollectionUtils.wrapList(authenticator.getReturnAttributes());
            if (!authenticatorAttributes.isEmpty()) {
                
                attributes.removeIf(authenticatorAttributes::contains);
            }
        }
        this.authenticatedEntryAttributes = attributes.toArray(new String[attributes.size()]);
        
    }

    public void setCollectDnAttribute(final boolean collectDnAttribute) {
        this.collectDnAttribute = collectDnAttribute;
    }
}

Reply via email to