Spring security ldap connection management - spring-security

I am using spring security to authenticate users logging into a webapp. Authentication is currently done with ldap.
Between my webapp and my ldap server lies a firewall. After 50 minutes of inactivity, the firewall flushes idle ldap connections.
Spring security sometimes reuses existing connections, but not always. If it picks a connection closed by my firewall, the login will fail.
The exception I find in my Tomcat log is the following.
org.springframework.ldap.ServiceUnavailableException: ldap:389; socket closed; nested exception is javax.naming.ServiceUnavailableException
More specifically, connections causing issues are the ones used for search requests. They're not systematically closed by the framework. Bind requests are always made on a new connection that's closed at the end of the request.
In my app a search request is issued after a bind because of a custom LdapAuthoritiesPopulator granting access only to users with particular roles. I have verified the default LdapAuthoritiesPopulator issues search requests in the same manner.
Is it normal for search request connections to stay open almost indefinitely?
If it is, is there a way I can change the way spring security manages its connections?
I'm also interested to know if there is a better way than using a custom LdapAuthoritiesPopulator to enforce a role constraint during authentication.
My problem persists after trying easy upgrades:
spring-security 3.1.7 (up from 3.1.2)
spring-ldap-core 2.0.2 (up from 1.3.0)
spring-ldap 1.3.1 (up from 1.3.0)
Thanks.

The solution is to use ldap-spring pooling and validation.
http://docs.spring.io/spring-ldap/docs/1.3.x/reference/html/pooling.html
A first good step is to define <beans:property name="pooled" value="false"/>. With that, all requests - bind or search - are made on an independent connection.
If you have a lot of ldap connections to handle and wish to minimize connection overhead, then you have to setup additional objects to define your connection pool behavior. It is all well explained in the doc.
As of spring-ldap 1.3, you need to add commons-pool 1.6 to your project.

Related

Grails spring-security-ldap caching caching with Redis

Newbie question so bear with me...
Currently I have a Grails 2.4.4 app that used spring-security-ldap 2.0.1 to authenticate + authorised users with an OpenLdap server.
The LDAP people are concerned that without caching this app when move to Production might impact the LDAP server's performance. They had recommend looking into using Redis as a app level caching for users, b4 hitting the LDAP server.
I would like to get some directions before I dive into the POC, make sure I start on the right path:
i) I briefly looked into the 'Grails 1 & 2 Plugins' from Grail org, there are a couple of plugins appeared when I searched for Redis... Which one(s) actually are relevant to what I am trying to achieve?
ii) Assume I had integrated Redis caching to my Grails, how/where do I tell spring-security-ldap to look into the Redis cache first, b4 hitting up the Ldap server?
Thanks in advance any info/guide..
Here are some advices, as you're not looking for ready-to-use solutions:
caching any type of authentication is big security failure as hackers will be able to take advantage of this to bypass some rules implemented into your LDAP solution, such as brute force protections (e.g. block account after N bad password)
in order to handle the load on LDAP server side, you could adjust the session token expiration (JSESSIONID or JWT, depending on how Spring security has been configured). For example, if token expiration is 1 hour, you will receive only 1 request per hour per user.
you could had refresh token mechanism to renew session token without querying LDAP. In this case you will have only 1 LDAP request per device per user, which might be acceptable. Here is how to do it using Grails JWT
In this doc you will see that REDDIS can be used to store token, which is quite related to what your initial solution

Is sameOriginDisabled and setAllowedOrigin("*") are for same purpose in spring websocket security?

In Spring websocket security, I found options, which looks like similar, can anyone explain?
https://docs.spring.io/autorepo/docs/spring-security/4.0.x/reference/html/websocket.html#websocket-sameorigin-disable
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/socket/config/annotation/StompWebSocketEndpointRegistration.html#setAllowedOrigins-java.lang.String...-
sameOriginDisabled() vs setAllowedOrigins("*")
In my application, even though, I have setAllowedOrigin(*), if access websocket from a different domain (localhost:4200 -> app server), app is asking me to authenticate again. If I connect from the same domain (deployed in the same server), it is going through.
Due to version conflicts, I couldn't try sameOriginDisabled(). We are using 3.2.10 spring security version.
So even if we upgrade, not sure whether sameOriginDisabled() will help me.

Problems while implementing SSO with Spring Security CAS extension

I'm trying to use Spring Security CAS extension to authenticate users on my applications. Earlier there was only one application, so SSO was not needed. Now there is one more application and I want the user to log in once and use all the applications without having to go through authentication again (SSO, basically). I've a bunch of questions like these -
All the applications I have are part of a single tomcat container and will be served via same domain. I checked Tomcat SSO Valve, but it seems to need container based authentication, I'm not really sure if I would want to use that for authentication / authorization. I'm using spring security form-based login. Do I really need something like Jasig CAS or will it be an overkill?
Spring Security and CAS deployerContext Configuration - http://pastie.org/8408976 and http://pastie.org/8408967
I set up Spring Security CAS with Jasig server and SSO seems to work as logging in to any of the applications suffices to access the other application. I've modified the deployerConfigContext.xml to replace the inMemoryServiceRegistryDaoImpl with JPA / Hibernate one. But I always see the below line in my logs. Though the tables have been created (SERVICETICKET and so on) in my db. These tables are always empty when I try logging in and out.
2013-10-17 16:41:18,882 INFO [org.jasig.cas.services.DefaultServicesManagerImpl] - <Loaded 0 services.>
When I try to access URL https://localhost/cas/services, it returns an error "This website has a redirect loop". and I see the below piece repeating n number of times in the logs (with different ticket numbers)-
http://pastie.org/8408940
I don't have any REST or stateless services accessing authenticated resources, do I need proxy tickets at all?
Note: I'm using Spring Security 3.1.4.RELEASE and CAS server 3.5.2 version.
Any pointers will be helpful.
I set up Spring Security CAS with Jasig server and SSO seems to work
as logging in to any of the applications suffices to access the other
application. I've modified the deployerConfigContext.xml to replace
the inMemoryServiceRegistryDaoImpl with JPA / Hibernate one. But I
always see the below line in my logs. Though the tables have been
created (SERVICETICKET and so on) in my db. These tables are always
empty when I try logging in and out.
When I try to access URL `https://localhost/cas/services`, it returns an error "This website has a redirect loop". and I see the
below piece repeating n number of times in the logs (with different
ticket numbers)
I figured out the solution to this. This was happening as filterProcessesUrl in CAS server configuration had the string "acegi" (old name for Spring Security), which didn't match to "spring", hence the problem. Modifying that helped. Not sure why old name was hardcoded there. Also, it didn't pick up this string from cas.properties, so figuring it out was a little more difficult.
I hope to get answers for other questions.

Are there issues with using Spring Security's HttpSessionSecurityContextRepository on CloudFoundry?

I understand that Spring Security's HttpSessionSecurityContextRepository makes use of HttpSession.
Furthermore, I have read that PaaS such as CloudFoundry try to avoid session replication for the purpose of scalability.
I intend to deploy an application to the CloudFoundry PaaS.
Are there issues with using HttpSessionSecurityContextRepository on CF?
CloudFoundry documentation simply says that HTTP Sessions are not replicated across instances by default. All this means is that applications deployed on multiple instances will be unable to use any sort of HTTP session clustering by default. HTTP sessions become sticky, that is, all HTTP requests in the same session will be routed to the instance on which the session for the request resides. In case an instance fails, users who had active session on that instance will be migrated to other instances but they will lose their session information, which will mean they will have to login again.
This does not mean it is unsafe to use Spring Security in such an environment. The semantics with Spring Security will be the same as those without it. Once a user has logged in, they will continue to access the CloudFoundry instance on which their session was created. If that instance crashed, they will be automatically ported to another instance but will have to login again.
If the default set up (without session replication) is a concern, it is certainly possible to share sessions across instances. CloudFoundry forums list two ways of achieving this - via Redis and using JDBC. It is also possible to implement your own solution using one of the CloudFoundry services.

how to get current user in spring security integrated with cas?

I have integrated CAS to Spring Security using Spring security tutorial on cas wiki. Now I want to get the current user and don't know how!
Should I get it from Spring security or CAS?
SecurityContextHolder.getContext().getAuthentication() returns null :|
If SecurityContextHolder.getContext().getAuthentication() is null means that the user is not authenticated yet.
Some pointers on CAS
Make sure that you use SSL for the communication to CAS thus CAS
must be hosted on SSL ports (443 or 8443)
Make sure that you Spring
Apps is hosted on SSL ports so that CAS can call to your Spring via
SSL server.
Common error is that both CAS and Spring Apps are not on SSL ports.
If this is the case, get a free SSL cert from www.startssl.com
Found the problem! I was going to use my own Access Control system, so I commented filters who where responsible for checking user's roles to access URLs. Apparently if I don't intercept URLs, spring security's context won't be accessible through that request (or at least it seems like that! I am not a big fan of Documents, so I try out codes and when I get an exception, I try to guess the reason! I really should stop doing that :| but anyway now that I intercept URLs, SecurityContextHolder.getContext().getAuthentication() doesn't return null anymore :) )

Resources