Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

First up we'll look at how to provide the user with access to the system without having to enter a username/password via Windows integrated authentication. Then we'll look at extending this to also obtain the access levels for the users from the domain.

Integrated Authentication

To implement Windows integrated authentication and allow internal users to login to Weave automatically using their Windows userid involves editing the security.xml file to replace the default login form with handling from the NTLM processor.

Looking at the default security.xml file it contains the following near the top:

...

Debugging

You may want to turn on the logging of the security processing during the setting up of the authentication, since it'd disabled by default.

To do this ensure that the following two lines appear in logging.properties and any others referencing security are removed (in case they reduce the logging)

Code Block
none
none
titleEnable security process logging
linenumberstrue
	<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
		<property name="filterInvocationDefinitionSource">
			<value>
				CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
				PATTERN_TYPE_APACHE_ANT
				/server/**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,jsonExceptionTranslationFilter,filterInvocationInterceptor
				/**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
			</value>log4j.logger.org.acegisecurity=DEBUG
log4j.logger.com.cohga.server.security=DEBUG

Then when someone is logging in the log file will show the progress and what roles they were granted, which should help you to understand what role names must be used in the access control lists

Integrated Authentication

To implement Windows integrated authentication and allow internal users to login to Weave automatically using their Windows userid involves editing the security.xml file to replace the default login form with handling from the NTLM processor.

Looking at the default security.xml file it contains the following near the top:

Code Block
xml
xml
titleDefault request filter chain
linenumberstrue

	<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
		<property name="filterInvocationDefinitionSource">
			<value>
				CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
				PATTERN_TYPE_APACHE_ANT
				/server/**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,jsonExceptionTranslationFilter,filterInvocationInterceptor
				/**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
			</value>
		</property>
	</bean>

What this section does is to determine which filters are applied to any incoming requests, passing everything that matched /server/** through the first list, and everything else through the second.

What we want to do to enable Windows authentication is add an additional filter to perform the NTLM authentication steps when required.

That should be the final new section we need to add, since the sections that it references should already exist. So all that remains is to add the first section we added to the list of filters:

Code Block
xml
xml
titleAdding NTLM filter to request filter chain
linenumberstrue

	<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
		<property name="filterInvocationDefinitionSource">
			<value>
				CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
				PATTERN_TYPE_APACHE_ANT
				/server/**=httpSessionContextIntegrationFilter,ntlmProcessingFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,jsonExceptionTranslationFilter,filterInvocationInterceptor
				/**=httpSessionContextIntegrationFilter,ntlmProcessingFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
			</value>
		</property>
	</bean>

Here we've added the ntlmProcessingFilter to the list of filters that will be applied to the incoming requests.

Now we need to create the ntlmProcessingFilter filter and configure it to use the local domain.

To do this we add a new section to the security.xml file to define a new NtlmProcessingFilter

Code Block
xml
xml
titleThe root NTLM filter definition
linenumberstrue

	<bean id="ntlmProcessingFilter" class="org.acegisecurity.ui.ntlm.NtlmProcessingFilter">
		<property name="defaultDomain"><value>DOMAINNAME</value></property>
		<property name="domainController"><value>172.16.0.30</value></property>
		<property name="authenticationEntryPoint" ref="ntlmEntryPoint"/>
		<property name="authenticationManager" ref="ntlmAuthenticationManager"/>
	</bean>

The two values in there DOMAINNAME and 172.16.0.30 need to be replaced with values that are appropriate for your environment.

This is the filter that we added to the filter list, now we need to create two more sections that this filter references, the ntlmEntryPoint and the ntlmAuthenticationManager.

The ntlmEntryPoint takes care of the communication for the server to obtain the Windows userid from the browser.
The ntlmAuthenticationManager then sends that information through a list of AuthenticationProviders to validate that it's correct.

Code Block
xml
xml
titleNTLM entry point for obtaining the user information from browser
linenumberstrue

	<bean id="ntlmEntryPoint" class="org.acegisecurity.ui.ntlm.NtlmProcessingFilterEntryPoint"/>
Code Block
xml
xml
titleNTLM authentication manager for verifying the user information from browser
linenumberstrue

	<bean id="ntlmAuthenticationManager" class="org.acegisecurity.providers.ProviderManager">
		<property name="providers">
			<list>
				<ref local="smbAuthenticationProvider"/>
				<bean class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
					<property name="key" value="changeThis"/>
				</bean>
				<bean class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
					<property name="key" value="changeThis"/>
				</bean>
			</list>
		</property>
	</bean>

The ntlmEntryPoint does not require any configuration, but we can see that the ntlmAuthenticationManager references yet another item that we need to add, the smbAuthenticationManager.
The smbAuthenticationManager provides authentication via the SMB protocol of the authentication information extracted by the NtlmProcessingFilter.

Note

The AnonymousAuthenticationProvider and RememberMeAuthenticationProvider ensure that anonymous users can connect and users that have indicated that they want to be remembered (if the login form is used) can be logged in from the cookie that was previously set. If neither of these things are applicable then it's possible to remove these 2 authentication providers and rely on the smbAuthenticationProvider.

Setting up the smbAuthenticationProvider is just a matter of configuring the SmbNtlmAuthenticationProvider with the authorizationProvider provider to be used.

Code Block
xml
xml
2A SMB NTLM aware authentication provider
linenumberstrue

	<bean id="smbAuthenticationProvider" class="org.acegisecurity.providers.smb.SmbNtlmAuthenticationProvider">
		<property name="authorizationProvider">
			<ref local="nullDaoAuthenticationProvider"/>
		</property>
	</bean>

What this section does is to determine which filters are applied to any incoming requests, passing everything that matched /server/** through the first list, and everything else through the second.

What we want to do to enable Windows authentication is add an additional filter to perform the NTLM authentication steps when required.

That should be the final new section we need to add, since the sections that it references should already exist. So all that remains is to add the first section we added to the list of filters:In this case we're referencing yet another item, the nullDaoAuthenticationProvider authentication provider.
The nullDaoAuthenticationProvider is a simple authentication provider that uses a separate UserDetailsService to retrieve the information about what roles a user has, and if you're using the default security.xml file for this that will be the users.properties file.
Alternatively the UserDetailsService could be accessing a database to retrieve the users roles, and later we'll be looking at changing this to use Active Directory (via LDAP) to determine the users roles.

Code Block
Adding NTLM filter to request filter chain
xml
xmltitle
2A SMB simple password authenticator
linenumberstrue
	<bean id="filterChainProxynullDaoAuthenticationProvider" class="org.acegisecurity.utilproviders.smb.FilterChainProxy">
		<property name="filterInvocationDefinitionSource">
			<value>
				CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
				PATTERN_TYPE_APACHE_ANT
				/server/**=httpSessionContextIntegrationFilter,ntlmProcessingFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,jsonExceptionTranslationFilter,filterInvocationInterceptor
				/**=httpSessionContextIntegrationFilter,ntlmProcessingFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
			</value>
		</property>
	</bean>

Here we've added the ntlmProcessingFilter to the list of filters that will be applied to the incoming requests.

Now we need to create the ntlmProcessingFilter filter and configure it to use the local domain.

To do this we add a new section to the security.xml file to define a new NtlmProcessingFilter

Code Block
xmlxml
titleThe root NTLM filter definition
linenumberstrue

	<bean id="ntlmProcessingFilter"NullPasswordDaoAuthenticationProvider">
		<property name="userDetailsService" ref="userDetailsService"/>
		<property name="userCache">
			<bean class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
				<property name="cache">
					<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
						<property name="cacheManager">
							<bean class="org.acegisecurityspringframework.uicache.ntlmehcache.NtlmProcessingFilterEhCacheManagerFactoryBean"/>
		<property name="defaultDomain"><value>DOMAINNAME</value><				</property>
						<property name="cacheName" value="domainController"><value>172.16.0.30</value><userCache"/>
					</bean>
				</property>
			<property name="authenticationEntryPoint" ref="ntlmEntryPoint"/>
		<property name="authenticationManager" ref="ntlmAuthenticationManager"/></bean>
		</property>
	</bean>

The two values in there DOMAINNAME and 172.16.0.30 need to be replaced with values that are appropriate for your environment.

This is the filter that we added to the filter list, now we need to create two more sections that this filter references, the ntlmEntryPoint and the ntlmAuthenticationManager.

The ntlmEntryPoint takes care of the communication for the server to obtain the Windows userid from the browser.
The ntlmAuthenticationManager then sends that information through a list of AuthenticationProviders to validate that it's correct.

...

If you're starting with the default security.xml file that should be the final new section we need to add, since the userDetailsService that it references should already exist. And you could restart the server and assuming that the users.properties file has an entry for each user they should be able to log in without having to enter a username/password.

Customising the the SMB authentication process

Depending upon the version of active directory you're running you may need to specify a username/password for the ntlmProcessingFilter, so if you find authentication errors in the weave.log file after enabling integrated authentication then change the ntlmProcessingFilter to the following and set the appropriate username/password.

Code Block
xml
xml
titleNTLM authentication manager for verifying the user information from browserSetting username/password for domain access
linenumberstrue
	<bean id="ntlmAuthenticationManagerntlmProcessingFilter" class="org.acegisecurity.providersui.ntlm.ProviderManagerNtlmProcessingFilter">
		<property name="providers">
			<list>
				<ref local="smbAuthenticationProvider"/>defaultDomain"><value>DOMAINNAME</value></property>
		<property name="domainController"><value>172.16.0.30</value></property>
		<property name="authenticationEntryPoint" ref="ntlmEntryPoint"/>
		<property name="authenticationManager" ref="ntlmAuthenticationManager"/>
		<property name = "JCifsProperties">
			<map>
				<bean<entry classkey="orgjcifs.acegisecuritysmb.providersclient.anonymous.AnonymousAuthenticationProviderusername">
					<property name="key" value="changeThis"/><value>username</value>
				</bean>entry>
				<bean<entry classkey="orgjcifs.acegisecuritysmb.providersclient.rememberme.RememberMeAuthenticationProviderpassword">
					<property name="key" value="changeThis"/><value>password</value>
				</bean>entry>
			</list>map>
		</property>
	</bean>

The ntlmEntryPoint does not require any configuration, but we can see that the ntlmAuthenticationManager references yet another item that we need to add, the smbAuthenticationManager.
The smbAuthenticationManager provides authentication via the SMB protocol of the authentication information extracted by the NtlmProcessingFilter.

Note

The AnonymousAuthenticationProvider and RememberMeAuthenticationProvider ensure that anonymous users can connect and users that have indicated that they want to be remembered (if the login form is used) can be logged in from the cookie that was previously set. If neither of these things are applicable then it's possible to remove these 2 authentication providers and rely on the smbAuthenticationProvider.

Setting up the smbAuthenticationProvider is just a matter of configuring the SmbNtlmAuthenticationProvider with the authorizationProvider provider to be used.

...


	<bean id="smbAuthenticationProvider" class="org.acegisecurity.providers.smb.SmbNtlmAuthenticationProvider">
		<property name="authorizationProvider">
			<ref local="nullDaoAuthenticationProvider"/>
		</property>
	</bean>

In this case we're referencing yet another item, the nullDaoAuthenticationProvider authentication provider.
The nullDaoAuthenticationProvider is a simple authentication provider that uses a separate UserDetailsService to retrieve the information about what roles a user has, and if you're using the default security.xml file for this that will be the users.properties file.
Alternatively the UserDetailsService could be accessing a database to retrieve the users roles, and later we'll be looking at changing this to use Active Directory (via LDAP) to determine the users rolesAdditional properties that can effect the SMB authentication process can be found here.

Selectively applying NTLM authentication

You can specify what IP addresses you want NTLM authentication to apply to, or not apply to, allowing you to support NTLM authentication for internal users and bypass it for external ones, for example (this prevents external users from being presented with a username/password dialogue box that they will probably not have valid values for).

To do this you need to replace the ntlmProcessingFilter, rather than using the org.acegisecurity.ui.ntlm.NtlmProcessingFilter class you should use the org.acegisecurity.ui.ntlm.IPFilteredNtlmProcessingFilter, this implementation of the NtlmProcessingFilter can then be provided with additional configuration items specifying which IP addresses should/shouldn't be provided with the option to authenticate using NTLM.

Note

All the previous configuration items still apply, and should still be set, for the IPFilteredNtlmProcessingFilter. This new version just provides additional configuration options.

The new configuration items that the IPFilteredNtlmProcessingFilter provides are excludedIpAddresses and includedIpAddresses, and are set as a list of IP addresses or address ranges.

Code Block
A SMB simple password authenticator
xml
xml2
titleSelectively applying NTLM authentication
linenumberstrue
	<bean id="nullDaoAuthenticationProviderntlmProcessingFilter" class="org.acegisecurity.providersui.smb.NullPasswordDaoAuthenticationProvider">ntlm.NtlmProcessingFilter">
		<property name="defaultDomain"><value>DOMAINNAME</value></property>
		<property name="userDetailsService" ref="userDetailsService"/>domainController"><value>172.16.0.30</value></property>
		<property name="userCacheauthenticationEntryPoint">
			<bean class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache" ref="ntlmEntryPoint"/>
				<property name="cacheauthenticationManager">
					<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
						 ref="ntlmAuthenticationManager"/>
		<property name="cacheManagerexcludedIpAddresses">
			<list>
				<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/><value>192.168.2.0/24</value>
				<value>138.19.19.50</value>
			</property>list>
			</property>
			<property name="cacheName" value="userCache"/includedIpAddresses">
					</bean><list>
				</property><value>172.16.0.0/16</value>
			</bean>list>
		</property>
	</bean>

If you're starting with the default security.xml file that should be the final new section we need to add, since the userDetailsService that it references should already exist. And you could restart the server and assuming that the users.properties file has an entry for each user they should be able to log in without having to enter a username/password.

Customising the the SMB authentication process

Depending upon the version of active directory you're running you may need to specify a username/password for the ntlmProcessingFilter, so if you find authentication errors in the weave.log file after enabling integrated authentication then change the ntlmProcessingFilter to the following and set the appropriate username/password.

...


	<bean id="ntlmProcessingFilter" class="org.acegisecurity.ui.ntlm.NtlmProcessingFilter">
		<property name="defaultDomain"><value>DOMAINNAME</value></property>
		<property name="domainController"><value>172.16.0.30</value></property>
		<property name="authenticationEntryPoint" ref="ntlmEntryPoint"/>
		<property name="authenticationManager" ref="ntlmAuthenticationManager"/>
		<property name = "JCifsProperties">
			<map>
				<entry key="jcifs.smb.client.username">
					<value>username</value>
				</entry>
				<entry key="jcifs.smb.client.password">
					<value>password</value>
				</entry>
			</map>
		</property>
	</bean>

Additional properties that can effect the SMB authentication process can be found here.

Selectively applying NTLM authentication

You can specify what IP addresses you want NTLM authentication to apply to, or not apply to, allowing you to support NTLM authentication for internal users and bypass it for external ones, for example (this prevents external users from being presented with a username/password dialogue box that they will probably not have valid values for).

To do this you need to replace the ntlmProcessingFilter, rather than using the org.acegisecurity.ui.ntlm.NtlmProcessingFilter class you should use the You don't need to provide both excludedIpAddresses and includedIpAddresses, in fact it's more than likely that you'll only want to provide one, either listing those addresses that should be NTLM authenticated, and everyone else isn't, or listing those addresses that should not be NTLM authenticated and everyone else should. But, if you do provide both then the exclude list is checked first. Also, if the include list is set then the IP address must appear in the list for NTLM authentication to be attempted.

Info

The IPFilteredNtlmProcessingFilter class is provided in version 1.0.7 or later of the org.acegisecurity.ntlm bundle

As of version 1.3.4 of the org.acegisecurity.ntlm bundle there's an additional property that can be set for the IPFilteredNtlmProcessingFilter, and that's defaultRole, which when set will add the role (exactly as it appears in the security.xml file) to the list of roles the user has. This allows you to utilise multiple Active Directory domain to authenticate user and provide access control based on what domain the user was authenticated against.
Note: If you're using LDAP to provide the users roles then it's also possible to set a defaultRole in the LDAP populator.

Code Block
xml
xml
titleUsing multiple domain for authentication
linenumberstrue

	<bean id="ntlmProcessingFilterInternal" class="org.acegisecurity.ui.ntlm.NtlmProcessingFilter">
		<property name="defaultDomain"><value>INTERNAL</value></property>
		<property name="domainController"><value>172.16.0.30</value></property>
		<property name="authenticationEntryPoint" ref="ntlmEntryPoint"/>
		<property name="authenticationManager" ref="ntlmAuthenticationManager"/>
		<property name="includedIpAddresses">
			<list>
				<value>172.16.0.0/16</value>
			</list>
		</property>
		<property name="defaultRole"><value>ROLE_INTERNAL</value></property>
	</bean>

	<bean id="ntlmProcessingFilterExternal" class="org.acegisecurity.ui.ntlm.

...

Note

All the previous configuration items still apply, and should still be set, for the IPFilteredNtlmProcessingFilter. This new version just provides additional configuration options.

The new configuration items that the IPFilteredNtlmProcessingFilter provides are excludedIpAddresses and includedIpAddresses, and are set as a list of IP addresses or address ranges.

Code Block
xmlxml
titleSelectively applying NTLM authentication
linenumberstrue

	<bean id="ntlmProcessingFilter" class="org.acegisecurity.ui.ntlm.NtlmProcessingFilter"NtlmProcessingFilter">
		<property name="defaultDomain"><value>EXTERNAL</value></property>
		<property name="domainController"><value>201.20.109.76</value></property>
		<property name="authenticationEntryPoint" ref="ntlmEntryPoint"/>
		<property name="authenticationManager" ref="ntlmAuthenticationManager"/>
		<property name="defaultDomain"><value>DOMAINNAME</value></includedIpAddresses">
			<list>
				<value>201.20.0.0/16</value>
			</list>
		</property>
		<property name="domainController"><value>172.16.0.30<defaultRole"><value>ROLE_EXTERNAL</value></property>
		<property name="authenticationEntryPoint" ref="ntlmEntryPoint"/>
		<property name="authenticationManager" ref="ntlmAuthenticationManager"/>
		<property name="excludedIpAddresses">
			<list>
				<value>192.168.2.0/24</value>
				<value>138.19.19.50</value>
			</list>
		</property></bean>

Not that to enable this both filters need to be added to the filter chain:

Code Block
xml
xml
titleAdding NTLM filter to request filter chain
linenumberstrue

	<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
		<property name="includedIpAddressesfilterInvocationDefinitionSource">
			<value>
			<list>	CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
				<value>172.16.0.0/16</value>
PATTERN_TYPE_APACHE_ANT
				</list>
		</property>
	</bean>

You don't need to provide both excludedIpAddresses and includedIpAddresses, in fact it's more than likely that you'll only want to provide one, either listing those addresses that should be NTLM authenticated, and everyone else isn't, or listing those addresses that should not be NTLM authenticated and everyone else should. But, if you do provide both then the exclude list is checked first. Also, if the include list is set then the IP address must appear in the list for NTLM authentication to be attempted.

Info

The IPFilteredNtlmProcessingFilter class is provided in version 1.0.7 or later of the org.acegisecurity.ntlm bundle

As of version 1.3.4 of the org.acegisecurity.ntlm bundle there's an additional property that can be set for the IPFilteredNtlmProcessingFilter, and that's defaultRole, which when set will add the role (exactly as it appears in the security.xml file) to the list of roles the user has. This allows you to utilise multiple Active Directory domain to authenticate user and provide access control based on what domain the user was authenticated against.
Note: If you're using LDAP to provide the users roles then it's also possible to set a defaultRole in the LDAP populator.

Code Block
xmlxml
titleUsing multiple domain for authentication
linenumberstrue

	<bean id="ntlmProcessingFilterInternal" class="org.acegisecurity.ui.ntlm.NtlmProcessingFilter">
		<property name="defaultDomain"><value>INTERNAL</value></property>
		<property name="domainController"><value>172.16.0.30</value></property>
		<property name="authenticationEntryPoint" ref="ntlmEntryPoint"/>
		<property name="authenticationManager" ref="ntlmAuthenticationManager"//server/**=httpSessionContextIntegrationFilter,ntlmProcessingFilter1,ntlmProcessingFilter2,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,jsonExceptionTranslationFilter,filterInvocationInterceptor
				/**=httpSessionContextIntegrationFilter,ntlmProcessingFilter1,ntlmProcessingFilter2,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
			</value>
		</property>
	</bean>

Active Directory Groups

Information about what active directory groups a user belongs to can be used to provide role information to Weave for the users that are authenticated using Windows integrated authentication, removing the need to utilise the users.properties file.

This information is obtained from an AD domain controller using the LDAP protocol.

When setting up the LDAP integration it's recommended that the JXplorer tool be used to test the settings, because the JXplorer uses the LDAP server in the same way as Weave but provides an interactive method for verifying the settings.

To enable LDAP as a source of authentication information the ntlmAuthenticationManager we created earlier needs to be altered to use an LdapAuthenticationProvider rather than the SmbAuthenticationProvider.

So we fist need to change the ntlmAuthenticationManager to

Code Block
xml
xml
titleEnabling LDAP support for authenticating users
linenumberstrue

	<bean id="ntlmAuthenticationManager" class="org.acegisecurity.providers.ProviderManager">
		<property name="includedIpAddressesproviders">
			<list>
				<value>172.16.0.0/16</value><ref local="ldapAuthenticationProvider"/>
			</list>	<bean class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
		</property>
			<property name="key"defaultRole"><value>ROLE_INTERNAL</value></property>
	 value="changeThis"/>
				</bean>

				<bean id="ntlmProcessingFilterExternal" class="org.acegisecurity.uiproviders.ntlmrememberme.NtlmProcessingFilterRememberMeAuthenticationProvider">
					<property name="defaultDomainkey"><value>EXTERNAL</value></property>
		<property name value="domainController"><value>201.20.109.76</value></property>
		<property name="authenticationEntryPoint" ref="ntlmEntryPoint"/>
		<property name="authenticationManager" ref="ntlmAuthenticationManager"/>
		<property name="includedIpAddresses">
			<list>
				<value>201.20.0.0/16</value>
			</list>
		</property>
		<property name="defaultRole"><value>ROLE_EXTERNAL</value></property>changeThis"/>
				</bean>
			</list>
		</property>
	</bean>

And then setup the new ldapAuthenticationProvider as follows

Code Block
xml
xml
linenumberstrue

	<bean id="ldapAuthenticationProvider" class="org.acegisecurity.ui.ntlm.ldap.authenticator.NtlmAwareLdapAuthenticationProvider">
		<constructor-arg>
			<ref local="authenticatorLdap"/>
		</constructor-arg>
		<constructor-arg>
			<ref local="populatorLdap"/>
		</constructor-arg>
	</bean>

Not that to enable this both filters need to be added to the filter chain:This provider uses two other item to provide information, the authenticationLdap bean and the populatorLdap bean.

The authentication would be configured as follows

Code Block
xml
xmltitleAdding NTLM filter to request filter chain
linenumberstrue
	<bean id="filterChainProxyauthenticatorLdap" class="org.acegisecurity.util.FilterChainProxy">
		<property name="filterInvocationDefinitionSource">
			<value>
				CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
				PATTERN_TYPE_APACHE_ANT
				/server/**=httpSessionContextIntegrationFilter,ntlmProcessingFilter1,ntlmProcessingFilter2,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,jsonExceptionTranslationFilter,filterInvocationInterceptor
				/**=httpSessionContextIntegrationFilter,ntlmProcessingFilter1,ntlmProcessingFilter2,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
			</value>ui.ntlm.ldap.authenticator.NtlmAwareLdapAuthenticatorImpl">
		<constructor-arg>
			<ref local="initialDirContextFactory"/>
		</constructor-arg>
		<property name="userSearch">
			<ref local="userSearchLdap"/>
		</property>
	</bean>

Active Directory Groups

Information about what active directory groups a user belongs to can be used to provide role information to Weave for the users that are authenticated using Windows integrated authentication, removing the need to utilise the users.properties file.

This information is obtained from an AD domain controller using the LDAP protocol.

When setting up the LDAP integration it's recommended that the JXplorer tool be used to test the settings, because the JXplorer uses the LDAP server in the same way as Weave but provides an interactive method for verifying the settings.

To enable LDAP as a source of authentication information the ntlmAuthenticationManager we created earlier needs to be altered to use an LdapAuthenticationProvider rather than the SmbAuthenticationProvider.

...

/bean>

Which as we can see requires two other items, the initialDirContextFactory and the userSearchLdap.

The initialDirContextFactory is also used by the userSearchLdap and the populaterLdap beans so we'll look at that first

Code Block
xml
xml
titleSetting up a connection to the LDAP server
linenumberstrue

	<bean id="initialDirContextFactory" class="org.acegisecurity.ldap.DefaultInitialDirContextFactory">
		<constructor-arg value="ldap://192.168.0.16:389/"/>
		<property name="managerDn">
			<value>CN=Administrator,OU=Users,DC=cohga,DC=local</value>
		</property>
		<property name="managerPassword">
			<value>password</value>
		</property>
	</bean>

Here the ip address, manager distinguished name and manager passwords must be set to appropriate values for a user that can read for the active directory server.

The two final beans, the userSearchLdap and populatorLdap also require information that is specific to the environment you're running within, the userSearchLdap beans would be as follows

Code Block
xml
xml
linenumberstrue
	<bean id="ntlmAuthenticationManager" class="org.acegisecurity.providers.ProviderManager">
		<property name="providers">
			<list>
				<ref local="ldapAuthenticationProvider"/>
				<bean="userSearchLdap" class="org.acegisecurity.providersldap.anonymoussearch.AnonymousAuthenticationProviderFilterBasedLdapUserSearch">
		<constructor-arg>
					<property name="key" value="changeThis"/>
				</bean>
				<bean class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
					<value>OU=Users,DC=cohga,DC=local</value>
		</constructor-arg>
		<constructor-arg>
			<value>(sAMAccountName={0})</value>
		</constructor-arg>
		<constructor-arg>
			<ref local="initialDirContextFactory" />
		</constructor-arg>
		<property name="keysearchSubtree" value="changeThis"/>>
			<value>true</value>
		</property>
		</bean>
			</list>
		</property>
	</bean>

...

This configuration assumes that there is a branch in the tree matching the first constructor arg and that the sAMAccountName value of any user found there will match the username they logged into Windows with.

Finally the populatorLdap is responsible for mapping the username to the roles and would be configured as follows

Code Block
xml
xml
titleSetting to populate users roles from LDAP
linenumberstrue
	<bean id="ldapAuthenticationProviderpopulatorLdap" class="org.acegisecurity.ui.ntlmproviders.ldap.authenticatorpopulator.NtlmAwareLdapAuthenticationProviderDefaultLdapAuthoritiesPopulator">
		<constructor-arg>
			<ref local="authenticatorLdapinitialDirContextFactory"/>
		</constructor-arg>
		<constructor-arg>
			<ref local="populatorLdap"/><value>OU=Users,DC=cohga,DC=local</value>
		</constructor-arg>
	</bean>

This provider uses two other item to provide information, the authenticationLdap bean and the populatorLdap bean.

The authentication would be configured as follows

Code Block
xmlxml
linenumberstrue

	<bean id="authenticatorLdap" class="org.acegisecurity.ui.ntlm.ldap.authenticator.NtlmAwareLdapAuthenticatorImpl	<property name="groupRoleAttribute">
		<constructor-arg>	<value>cn</value>
			<ref local</property>
		<property name="initialDirContextFactory"/>searchSubtree">
			<value>true</value>
		</constructor-arg>property>
		<property name="userSearchrolePrefix">
			<ref local="userSearchLdap"/<value>ROLE_</value>
		</property>
		<property name="convertToUpperCase">
		</property>
	</bean>

Which as we can see requires two other items, the initialDirContextFactory and the userSearchLdap.

The initialDirContextFactory is also used by the userSearchLdap and the populaterLdap beans so we'll look at that first

Code Block
xmlxml
titleSetting up a connection to the LDAP server
linenumberstrue

	<bean id="initialDirContextFactory" class="org.acegisecurity.ldap.DefaultInitialDirContextFactory">
		<constructor-arg value="ldap://192.168.0.16:389/"/><value>true</value>
		</property>
		<property name="groupSearchFilter">
			<value>(member={0})</value>
		</property>
		<property name="managerDndefaultRole">
			<value>CN=Administrator,OU=Users,DC=cohga,DC=local<<value>ROLE_USERS</value>
		</property>
		<property name="managerPassword">
			<value>password</value>
		</property>
	</bean>

Here the ip address, manager distinguished name and manager passwords must be set to appropriate values for a user that can read for the active directory server.

The two final beans, the userSearchLdap and populatorLdap also require information that is specific to the environment you're running within, the userSearchLdap beans would be as follows

...


	<bean id="userSearchLdap" class="org.acegisecurity.ldap.search.FilterBasedLdapUserSearch">
		<constructor-arg>
			<value>OU=Users,DC=cohga,DC=local</value>
		</constructor-arg>
		<constructor-arg>
			<value>(sAMAccountName={0})</value>
		</constructor-arg>
		<constructor-arg>
			<ref local="initialDirContextFactory" />
		</constructor-arg>
		<property name="searchSubtree">
			<value>true</value>
		</property>
	</bean>

This configuration assumes that there is a branch in the tree matching the first constructor arg and that the sAMAccountName value of any user found there will match the username they logged into Windows with.

...

</bean>

This "should" take the active directory groups that the user belongs to and convert them to a format that's usable in Weave, and also assigns a default ROLE_USERS role to all users (which you can remove if it's not appropriate).

You will then need to create Weave Access Control Lists utilising the roles that users will be assigned.

Supplementing LDAP Roles

As of version 1.4.4 of the org.acegisecurity.ntlm bundle it's possible to supplement the roles set via LDAP from a separate users details service (i.e. for example from a user.properties type file).

In this updated bundle there is a new SupplementedLdapAuthoritiesPopulator that can replace the DefaultLdapAuthoritiesPopulator in your security.xml and this authorities populator can be configured with an additional user details service, which if set will be used to look up the user being authenticated and if they're found the roles provided by the user details service will be added to the current user.

To implement the new authorities populator you should change:

Code Block
xml
xml
titleOld DefaultLdapAuthoritiesPopulator
linenumberstrue

<bean id="populator" class="org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator">
	...
</bean>

to

Code Block
xml
xml
titleSetting to populate users roles from LDAPNew SupplementedLdapAuthoritiesPopulator with reference to user details service
linenumberstrue
	<bean id="populatorLdappopulator" class="org.acegisecurity.providers.ldap.populator.DefaultLdapAuthoritiesPopulator">
		<constructor-arg>
			<ref local="initialDirContextFactory"/>
		</constructor-arg>
		<constructor-arg>
			<value>OU=Users,DC=cohga,DC=local</value>
		</constructor-arg>
	SupplementedLdapAuthoritiesPopulator">
	<property name="userDetailsService" ref="groupRoleAttributeldapDetailsService">
			<value>cn</value>
		</property>
		<property name="searchSubtree">
			<value>true</value>
		</property>
		<property name="rolePrefix">
			<value>ROLE_</value>
		</property>
		<property name="convertToUpperCase">
			<value>true</value>
		</property>
		<property name="groupSearchFilter">
			<value>(member={0})</value>
		</property>
		<property name="defaultRole">
			<value>ROLE_USERS</value>
		</property>
	</bean>

This "should" take the active directory groups that the user belongs to and convert them to a format that's usable in Weave, and also assigns a default ROLE_USERS role to all users (which you can remove if it's not appropriate).

You will then need to create Weave Access Control Lists utilising the roles that users will be assigned.

You may need to ensure that logging of the security related information is output by weave to be able to determine what roles a user is assigned to when they login. To do this ensure that the following two lines appear in logging.properties and any others referencing security are removed (in case they reduce the logging)

...


log4j.logger.org.acegisecurity=DEBUG
log4j.logger.com.cohga.server.security=DEBUG

...

/>
	...
</bean>

This will change it from DefaultLdapAuthoritiesPopulator to SupplementedLdapAuthoritiesPopulator and add a reference to the service that will provide the additional role information, which can be included by adding:

Code Block
xml
xml
titleNew user details service reading roles from a file
linenumberstrue

<bean id="ldapDetailsService" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
	<property name="userProperties">
		<bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
			<property name="location" value="ldap.properties"/>
		</bean>
	</property>
</bean>

Then you can create the ldap.properties, which has the same format as the existing users.properties file, in the workspace directory and any user listed there will have those roles added. e.g.

shaun=password,ROLE_TEST

Note the password is ignored, we're just mapping the userid to the roles and adding those roles to the current user.
There is currently no capability to remove roles or disable the users access using the SupplementedLdapAuthoritiesPopulator.

Alternatively you could also use the following if you just had a couple of users:

Code Block
xml
xml
titleNew user details service reading roles from its configuration
linenumberstrue

<bean id="ldapDetailsService" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
	<property name="userMap">
		<value>
			shaun=password,ROLE_TEST
		</value>
	</property>
</bean>

You could even use the JdbcDaoSupport class if you wanted to get this information from a database.