>
> 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 [email protected].
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;
}
}