Spring ActiveDirectoryLdapAuthenticationProvider setSearchFilter method - java

I have a working setup for SpringFramework Security 4.0.0 with my AD server. This was working fine with the default search filter until I discovered that the users in the AD database are much more twisted than expected originally.
My setup was as follow for the ActiveDirectoryLdapAuthenticationProvider bean in the namespace:
<b:bean id="monFournisseurAD" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<b:constructor-arg value="subdom1.dom1.com" />
<b:constructor-arg value="ldap://fsapps.company.uni:389/" />
<b:constructor-arg value="dc=fsapps,dc=company,dc=uni" />
<b:property name="searchFilter" value="(&(userPrincipalName={0})(objectClass=user))" />
<b:property name="userDetailsContextMapper">
<b:bean class="org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper" />
</b:property>
<b:property name="authoritiesMapper" ref="grantedAuthoritiesMapper" />
<b:property name="convertSubErrorCodesToExceptions" value="true" />
</b:bean>
I then moved to the following setup instead to remove the dependency on the domain:
<b:bean id="monFournisseurAD" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<b:constructor-arg value="" />
<b:constructor-arg value="ldap://fsapps.company.uni:389/" />
<b:constructor-arg value="dc=fsapps,dc=company,dc=uni" />
<b:property name="searchFilter" value="(&(sAMAccountName={0})(objectClass=user))" />
<b:property name="userDetailsContextMapper">
<b:bean class="org.springframework.security.ldap.userdetails.InetOrgPersonContextMapper" />
</b:property>
<b:property name="authoritiesMapper" ref="grantedAuthoritiesMapper" />
<b:property name="convertSubErrorCodesToExceptions" value="true" />
</b:bean>
The problem now is the {0} substitution in the searchFilter accordingly to the SpringFramework Security 4.0.0 documentation is substituting username#domain where domain seems to be the default domain of the AD server itself, which in this case is fsapps.company.uni since my first constructor argument is empty. SpringFramework Security 4.0.0 Class ActiveDirectoryLdapAuthenticationProvider's documentation
Question: Is there a way to substitute only username rather than username#domain? Any other suggestions how I can circumvent this problem?
NOTE: After looking at the source code. It seems the expected behavior should be as follow: if the domain argument for the constructor of the class ActiveDirectoryLdapAuthenticationProvider is an empty string or an all white spaces string, it is set to null. When the domain is set to null, the substitution of the {0} pattern should be the username only without the domain appended to it and this should do exactly what I want it to do: search for the sAMAccountName attribute equals to the username alone and a record of objectClass user. So, why does it fail to find users which are not in the rootDN as a domain (third constructor's argument fsapps.company.com in my example)? I have no problem to match users which would have a userPrincipalName of the form: username#fsapps.company.com while I cannot match users with a userPrincipalName of the form: username#whatever.domain ?
NOTE 2: I found the problem, not yet the solution. Actually, my search filter is perfectly fine and Spring Security is using it correctly. The problem is the authentication is performed by a bind to the AD server and to bind to the server I must use username#fsapps.company.com (if authorized) or either username#domain.in.constructor.arg.1. The sAMAccountName attribute is checked against a username with a domain rather than a username without a domain. If the domain is added, there is no sAMAccountName matching the value passed as an argument.

An alternative is using (sAMAccountName={1}) based on this fix.

A working solution is to rely on the first shown configuration using the userPrincipalName and emptying the first constructor's argument to pass an empty string to the constructor. This way, nothing will be appended to the username and instead of typing a simple username, the users have to type their complete usernames with the domain specified. So, instead of logging in with username, the use username#domain.
Another solution would be to investigate if it is possible to bind to the AD database with a generic and authorized user to perform all the queries on its behalf. I haven't investigate if it is feasible (it is done with plain LDAP) and how much effort it requires. If anyone experiment this solution, it would be nice to post the results here to share this solution.

Related

limit Concurrent logins in wicket application

I am developing a web application with Apache wicket(v 1.4) and spring(v 3.2) and i need to prevent users from logging in from two different
places at same time.
I tried to do it with spring security concurrency control,i added the following in my xml
<security:http create-session="never" auto-config="true">
<security:remember-me />
<security:intercept-url pattern="/**" />
<security:session-management>
<security:concurrency-control
max-sessions="1" error-if-maximum-exceeded="true"/>
</security:session-management>
</security:http>
but it doesn't seems to work.
Is there any wicket way to do it?Can anyone please help me?
You can track the sessions/users "manually".
For example: use a Set in YourApplication.java to keep the currently logged in users' names. In your signIn(String username, String password) method check whether this username is already in the set. Override Session#onInvalidate() to remove the username from the Set.
Since this Set is a global state the access to it should be synchronized.

Is there a way to configure Roles in a property file for Spring security MVC app

I have a spring security MVC application. In few JSP files I have code that looks like this:
<sec:authorize access="hasAnyRole('ROLE_FOO', 'ROLE_BAR')">
<!--do something here-->
</sec:authorize>
I have to make code changes (changing ROLE_FOO to something else) when deploying the app to production because it has different role names. So I was wondering whether there is a way to configure these role names in a property file and then pick those inside the <sec:authorize> tag.
So the code would look something like this:
Property File:
Admin_Roles = ROLE_FOO ROLE_BAR
and JSP
<sec:authorize access="hasAnyRole(<get roles from Admin_Roles in prop file>)">
<!--do something here-->
</sec:authorize>
btw, I am using Active Directory for authentication so these roles are pre-configured in the active directory for test and production.
Not sure it is the easiest way. But you can write your own expression.
This link should be very useful. link
Since there are some differences between each version. You had better take a look at the source code of DefaultWebSecurityExpressionHandler to make sure you do not miss anything when override createSecurityExpressionRoot
Not sure how you would do this for a variable number of roles, but for a fixed number have you tried something like this?
JSP:
<sec:authorize access="hasAnyRole('${adminRole1}', '${adminRole2}')">
<!--do something here-->
</sec:authorize>
Controller:
#Value("#{myprops.admin_role_1}"}
private String adminRole1;
#Value("#{myprops.admin_role_2}"}
private String adminRole2;
...
#RequestMapping("/hello")
public String hello(final Model model) {
model.addAttribute("adminRole1", adminRole1);
model.addAttribute("adminRole2", adminRole2);
...
}
and config XML:
<bean id="myprops"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<!-- External property files -->
<value>file:${somepathvar}/adminroles.properties</value>
</list>
</property>
</bean>

Configuring URL patterns for servlet filters

We are trying to use spring security in our application.
IN the below code, How do we configure the URL pattern to say
"intercept all the URLs except the URLs of pattern '/xyz/' " ?
Basically I want the filter to intercept all the URLs,but if an URL contains /xyz/ , it should not intercept it.
<sec:filter-chain pattern="/**" filters="httpSessionContextFilter,
filter_A,
filter_B,
exceptionTranslationFilter,
authorizationFilter" />
</sec:filter-chain-map>
Try:
<intercept-url pattern="*/xyz/*" filters="none" />
filters="none" disables the filter chain for the given URL pattern.
Also I'd recommend enabling the spring debug log if you haven't already. So you can see exactly what's going on.

Cumulative filters in Spring Security 3

I need to secure my website using 2 layers. First is an LDAP check, next is a username/password entry. I have written both custom authentication filters for both checks.
If the LDAP filter fails the user should be redirected to an 'access denied' page, and if the username/password failed the user should be redirected back to the login page.
How can I set up these filters in my config.xml file? Here is what I have currently
<sec:http entry-point-ref="loginAuthenticationEntryPoint"
auto-config="false" use-expressions="true">
<sec:intercept-url pattern="/login.htm" access="isAnonymous()" />
<sec:intercept-url pattern="/*"
access="hasRole('ROLE_LDAP') and hasRole('ROLE_CRESTA')" />
<sec:custom-filter ref="ldapAuthenticationFilter"
before="FORM_LOGIN_FILTER" />
<sec:custom-filter ref="usernameAuthenticationFilter"
position="FORM_LOGIN_FILTER" />
</sec:http>
with
public class LdapAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter
and
public class CrestaUsernameAuthenticationFilter extends AbstractAuthenticationProcessingFilter
My current thinking is for each filter to add one of the required roles, but when the LDAP filter doesn't add both roles I am immediately denied access.
Much appreciated
I think that approach will not work because as soon as your LDAP filter returns successfully, Spring Security considers the user has been completely authenticated and skips the username/password filter.
In your situation I would use the standard form login security, customizing just my UserDetailsService so that instead of going just to Cresta to create the UserDetails instance, it would query your LDAP server too for user roles.

how to leverage on Spring MVC to implement front controller but not using controllers

the title of this post might be confusing.I'll try be best to clarify it.
I Started a project using Spring MVC it works fine no problem.After that i've realized
that i was a bit overkill and found that i needed a front controller dispatcher because
all a wanted was nice urls without extensions.
So instead of implementing a whole new font controller i will like to take advantage of the existing Spring MVC setup. here is an example of a controller
#RequestMapping("/accounts")
public String home() {
return "accounts";
}
#RequestMapping(value="/")
public String Home(){
return "home";
}
as you can see, the return string is the one indicating the view based on the resourceviewresolver
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/views/" />
<property name="suffix" value=".jsp" />
</bean>
now i don't want to use the controller, but need a mechanism to map the request to a physical page.i'm wondering if that could be possible.
How can i do that? i should simply create another dispatcher?
thanks for reading this and helping out.
Spring 3 supports <mvc:view-controller> element for such cases:
<mvc:view-controller path="/" view-name="home" />
<mvc:view-controller path="/accounts" view-name="accounts" />
See also:
MVC Simplifications in Spring 3.0

Categories