Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3
Warning
titleWork in progress

This document is a work-in-progress and may not accurately reflect the full set of changes that implemented in the CAS 4 release. Tread lightly! Upon the CAS 4 release, this page should be updated to reflect the correct LPPE settings

 

Table of Contents

The purpose of the LPPE module is to detect a number scenarios that would otherwise prevent user authentication, specifically using an Ldap instance as the primary source of user accounts. To understand the general overview and intent of the LPPE functionality, please review this page

This document serves to highlight and explain the architectural changes that are proposed for upcoming CAS 4 release. In additional to various bug and security fixes, the following goals and improvements are planned: 

Change in Package Structure

All LPPE functionally is proposed to be contained inside the new package: org/jasig/cas/adaptors/ldap/lppe as much as possible. There may be overlap in some areas, but the effort is concentrated on keeping the changeset in one subpack of the ldap integration module.

Support for Non-Expiring ActiveDirectory Accounts

Current version of LPPE in CAS 3.5.x contains a bug in calculating the expiration date for AD accounts that are flagged to never expire. The correct approach would be to look up the bitwise value in the userAccountControl attribute of the AD container to detect account state. This fix can be accommodated through support for retrieval of custom attributes as descrfibed above.

...

Info
titleLdaptive & CAS 4

Coming up in CAS 4, the ldap integration in CAS that is provided by Spring is being reworked and replaced by that of ldaptive. Some of the design ideas and efforts throughout this document will be provided by the new framework and as such, may not be need explicit implementation and support directly in CAS.

 

This document serves to highlight and explain the architectural changes that are proposed for upcoming CAS 4 release. In additional to various bug and security fixes, the following goals and improvements are planned: 

Change in Package Structure

All LPPE functionally is proposed to be contained inside the new package: org/jasig/cas/adaptors/ldap/lppe as much as possible. There may be overlap in some areas, but the effort is concentrated on keeping the changeset in one subpack of the ldap integration module.

Support for Non-Expiring ActiveDirectory Accounts

Current version of LPPE in CAS 3.5.x contains a bug in calculating the expiration date for AD accounts that are flagged to never expire. The correct approach would be to look up the bit-wise value in the userAccountControl attribute of the AD container to detect account state. This fix can be accommodated through support for retrieval of custom attributes as described above.

The bitwise flags are defined as such:

Code Block
private enum ActiveDirectoryUserAccountControlFlags {
        UAC_FLAG_ACCOUNT_DISABLED(2),
        UAC_FLAG_LOCKOUT(16),
        UAC_FLAG_PASSWD_NOTREQD(32),
        UAC_FLAG_DONT_EXPIRE_PASSWD(65536),
        UAC_FLAG_PASSWORD_EXPIRED(8388608);
        
        private int value;
        
        ActiveDirectoryUserAccountControlFlags(final int id) { 
            this.value = id; 
        }
        
        public final int getValue() { 
            return this.value; 
        }
}

...

Code Block
<property name="ldapErrorDefinitions">
    <list>
       <bean class="org.jasig.cas.adaptors.ldap.lppe.AccountDisabledLdapErrorDefinitionActiveDirectoryAccountDisabledLdapErrorDefinition" />
       <bean class="org.jasig.cas.adaptors.ldap.lppe.AccountLockedLdapErrorDefinitionActiveDirectoryAccountLockedLdapErrorDefinition" />
       <bean class="org.jasig.cas.adaptors.ldap.lppe.InvalidLoginHoursLdapErrorDefinitionActiveDirectoryInvalidLoginHoursLdapErrorDefinition" />
       <bean class="org.jasig.cas.adaptors.ldap.lppe.InvalidLoginWorkstationLdapErrorDefinitionActiveDirectoryInvalidLoginWorkstationLdapErrorDefinition" />
       <bean class="org.jasig.cas.adaptors.ldap.lppe.AccountMustChangePasswordLdapErrorDefinitionActiveDirectoryAccountMustChangePasswordLdapErrorDefinition" />
       <bean class="org.jasig.cas.adaptors.ldap.lppe.AccountPasswordExpiredLdapErrorDefinitionActiveDirectoryAccountPasswordExpiredLdapErrorDefinition" />
    </list>
</property>

Ldap error definitions are optional. If none is found, authentication is prevented and the appropriate exception is thrown back. As such, deployers may choose to only pick definitions that are relevant to their environment and configuration. 

...

The above approach is completely extensible and exposes hooks for other implementations of the LdapErrorDefinition, should a use case arise. The changeset is provided and facilitated by having support for retrieval of custom attributes. 

Support for Post-Authentication Account Examiners

To detect and calculate the account expiration warning, the account state needs to be examined after a successful authentication. Based on LPPE configuration, the account state through retrieval of custom attributes is examined and appropriate prompts and alterations in the flow may occur. 

This changeset proposes an extensiable API an extensible API for examining account state post authentication. By default the implementation exposes an instance of LdapPasswordExpirationPolicyExaminer that calculates password expiration warning.  Other implementation that need to evaluate the account from other aspects may also be provided.

...

To calculate the password expiration warning based on a given LDAP attribute date (specified in the lppe LPPE configuration), this changeset proposes various implementations of the LdapDateConverter the LdapDateConverter interface. This interface provides for not only configuring the given timezone used in date calculation, but defines the general contract between LPPE and the following implementations: 

...

  • Let the inner ldap authN handler to do its job which is to execute the authentication query. This will execute one query only as part of which the LPPE authN handler should be able to instruct the inner ldap handler to retrieve additional (custom) attributes necessary for LPPE processing.
  • Allows Allow for a semi-comprehensive construction of a given PasswordPolicyConfiguration which is constructed based on account state and retrieved attributes. 
  • Take advantage of the machinery provided by the AbstractLdapUsernamePasswordAuthenticationHandler class, such as principal transformers as opposed to duplicating the same elements over. 
  • Exposes better control for detecting ldap error definitions before/during authentication as well as examining the account state post authentication, using the constructed PasswordPolicyConfiguration.
Code Block
<bean id="lppeEnabledLdapAuthenticationHandler" class="org.jasig.cas.adaptors.ldap.lppe.LdapPasswordPolicyAwareAuthenticationHandler"> 
		<property name="ldapAuthenticationHandler" ref="bindLdapAuthenticationHandler" />
		
		...
</bean>

The LdapPasswordPolicyAwareAuthenticationHandler is able to work with other authentication handlers as well, should they grant user authentication. For instance, along side with LdapPasswordPolicyAwareAuthenticationHandler, there might be a JDBC authentication handler defined apriori that allows the user to login. In this use case, LPPE will still issue an ldap query after authentication to retrieve account state and to construct the password policy configuratio. 

Support for Retrieval of Custom Ldap Authentication Attributes

The LPPE authentication handler relies on the inner ldap authN handler for retrieval of attributes that are needed for LPPE. Support and hooks must be exposes exposed so that LPPE instructs the inner handler, which attributes to retrieve. Such attributes may be:

...

Retrieval of custom attributes allows LPPE to detect certain ldap error codes and condition conditions that do not prevent ldap authentication. For instance, in working with OpenLdap a given account may be able to successfully log in even through a flag is set to indicate the account is locked. Defining custom attributes and their evaluation prior to authentication can support this use case. 

Support for retrieval of ldap authentication attributes is not available in CAS 3.5.x, which is partially the reason LPPE in CAS 3.5.x has to execute a second ldap query to retrieve the needed elements from ldap. 

...

The Current LPPE implementation exposes a custom webflow action that execute LPPE functions after the authentication has taken place. Its job is to examine the account state for password expiration warnings and redirect the flow as is appropriate. The authentication process, for ldap error definitions, also relied relies on the error "type" of a given error definition to redirect the flow, which was/is initiated by AuthenticationViaFormAction. This method involves two webflow actions and unnecessarily augments the AuthentivationViaFormAction logic and purposes  intent even if LPPE is not implemented. 

To separate the concerns, an extension of AuthentivationViaFormAction is developed. This new component,  LdapPasswordPolicyAwareAuthenticationViaFormAction LdapPasswordPolicyAwareAuthenticationViaFormAction, is responsible for invoking account examiners and to handle the redirects in the webflow that are specific to LPPE. Each examine, such as LdapPasswordExpirationPolicyExaminer, upon a successful authentication is invoked to evaluate the account state. 

LdapPasswordPolicyAwareAuthenticationViaFormAction will also refactor and extract out the detection of ldap error codes and their appropriate custom webflow state from the previous webflow action.Of course, this method relies on the fact that AuthenticationViaFormAction becomes extensible and allows subclasses to pass on a given state id to which it should redirect on success/error/etc. 

...

Code Block
languagehtml/xml
	<bean id="lppeEnabledLdapAuthenticationHandler" class="org.jasig.cas.adaptors.ldap.lppe.LdapPasswordPolicyAwareAuthenticationHandler"> 
		<property name="ldapAuthenticationHandler" ref="bindLdapAuthenticationHandler" />
		
		<property name="ldapErrorDefinitions">
		    		<list>
		     	  	  	<bean class="org.jasig.cas.adaptors.ldap.lppe.AccountDisabledLdapErrorDefinitionActiveDirectoryAccountDisabledLdapErrorDefinition" />
	 	       	<bean class="org.jasig.cas.adaptors.ldap.lppe.AccountLockedLdapErrorDefinitionActiveDirectoryAccountLockedLdapErrorDefinition" />
		    		   	<bean class="org.jasig.cas.adaptors.ldap.lppe.InvalidLoginHoursLdapErrorDefinitionActiveDirectoryInvalidLoginHoursLdapErrorDefinition" />
		     	  		<bean class="org.jasig.cas.adaptors.ldap.lppe.InvalidLoginWorkstationLdapErrorDefinitionActiveDirectoryInvalidLoginWorkstationLdapErrorDefinition" />
		       			<bean class="org.jasig.cas.adaptors.ldap.lppe.AccountMustChangePasswordLdapErrorDefinitionActiveDirectoryAccountMustChangePasswordLdapErrorDefinition" />
		      	 		<bean class="org.jasig.cas.adaptors.ldap.lppe.AccountPasswordExpiredLdapErrorDefinitionActiveDirectoryAccountPasswordExpiredLdapErrorDefinition" />
		  	  </list>
		</property>
		
		<property name="ldapPasswordPolicyExaminers">
			<list>
				<bean class="org.jasig.cas.adaptors.ldap.lppe.LdapPasswordExpirationPolicyExaminer">
					<property name="ignorePasswordExpirationWarningFlags" value="${ldap.authentication.lppe.noWarnValues}" />
					<property name="alwaysDisplayPasswordExpirationWarning" value="${ldap.authentication.lppe.warnAll}" />
					<property name="ldapDateConverter">
						<bean class="org.jasig.cas.adaptors.ldap.lppe.ActiveDirectoryLdapDateConverter" />
					</property> 
				</bean>
			</list>
		</property>
    	<property name="accountDisabledAttributeName" value="${ldap.authentication.lppe.accountDisabledAttribute}" />
    	<property name="accountLockedAttributeName" value="${ldap.authentication.lppe.accountLockedAttribute}" />
    	<property name="accountPasswordMustChangeAttributeName" value="${ldap.authentication.lppe.accountPasswordMustChangeAttribute}" />
    	
		<property name="passwordExpirationDateAttributeName" value="${ldap.authentication.lppe.dateAttribute}" />
		<property name="passwordWarningNumberOfDaysAttributeName" value="${ldap.authentication.lppe.warningDaysAttribute}" />
		<property name="validPasswordNumberOfDaysAttributeName" value="${ldap.authentication.lppe.validDaysAttribute}" />
		
		<property name="defaultValidPasswordNumberOfDays" value="${ldap.authentication.lppe.validDays}" />
		<property name="defaultPasswordWarningNumberOfDays" value="${ldap.authentication.lppe.warningDays}" />
		<property name="ignorePasswordExpirationWarningAttributeName" value="${ldap.authentication.lppe.noWarnAttribute}" />
		<property name="passwordPolicyUrl" value="${ldap.authentication.lppe.password.url}" />   
</bean>
 
<bean id="authenticationViaFormAction" class="org.jasig.cas.adaptors.ldap.lppe.web.flow.LdapPasswordPolicyAwareAuthenticationViaFormAction"
        p:centralAuthenticationService-ref="centralAuthenticationService"
        p:warnCookieGenerator-ref="warnCookieGenerator"
        p:ldapPasswordPolicyAuthenticationHandler-ref="lppeEnabledLdapAuthenticationHandler" />

    

...