What is difference between the following options:
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
and
http.sessionManagement().disable()
?
Seems like in the first case SessionManagementFilter will be added and do nothing. While in the second case it will not be added at all. So, seems like it is better to always use the second option if you don't need sessions. But I'm not sure.
Behaviour-wise I've noticed that, as you say, setting it as STATELESS adds a SessionManagementConfigurer to the SecurityBuilder and disabling it just adds null as the configurer.
This affects the SessionAuthenticationStrategyies added when configuring security. For example, enabling CSRF protection will add a CsrfAuthenticationStrategy even for statless case but will not for disabled session management.
To sum up: disabling it will not execute session authentication strategies at all but enabling it will execute it on each authenticated request for a stateless scenario.
Hope it helps, this is based on personal experience (configuring, trial-error, debugging).
Related
I am new to web security and implementation of same using spring-security. One important concept is prevention from CSRF using CSRF token. Spring security has provided two ways to manage CSRF token
CookieCsrfTokenRepository
HttpSessionCsrfTokenRepository
However I am not able to understand which one should be used as I can see cons in both the approach.
CookieCsrfTokenRepository is asking to set HTTP only property to false in cookie so that javascript can read it and add the same to in further request. However as per my understanding, setting http only as false is not recommended as malicious script can also read the cookie and share the same token in the forged request.
HttpSessionCsrfTokenRepository is storing the csrf token in session. In this case, we need to introduce session stickiness or session replication in case of distributed environment however recommendation is to go for stateless application.
So please some let me know if my above understanding is correct or not. If correct, which option do we need to select for csrf token implementation.
However as per my understanding, setting http only as false is not recommended as malicious script can also read the cookie and share the same token in the forged request.
I believe this would be true if a) you have an XSS vulnerability on your site or b) you did not set the Domain of the cookie. The rest of your question seems opinion-based to me.
however recommendation is to go for stateless application.
Note: The following is simply my opinion on the matter, as it's difficult to argue for/against statelessness in general.
This is an example where security requires state, so to protect the csrf token and avoid your concern with cookies, you need state on the server and should choose session.
I have several apps deployed in Tomcat 7, and use Keycloak to manage user login and logout of these apps. Logout does not work i.e., does not log the user out and redirect to Keycloak's login page. Then I found the JSESSIONID cookie is still present, once I deleted the JSESSIONID cookie, the logout link works as expected. So I tried to disable Tomcat's session by putting
<%# page session="false" %>
in the header of my apps' JSP pages. Unfortunately, this still does not seem to disable Tomcat's session, I still see JSESSIONID cookie present. I am wondering if anyone has a solution to this problem? I believe the presence of the Tomcat session interferes with the Keycloak's SSO session, and causes Keycloak logout to not work. This has to be a common problem Keycloak users encounter, Tomcat is so widely used for web apps.
Would appreciate any tips on how we should handle this!
I don't have specific experience with Keycloak, however, there's a principle that applies to most if not all Single-Sign-On (or external authentication) solutions:
SSO identifies a user and removes the burden of knowing passwords from typical applications. When a user signs in, an application server is often detached from the actual SSO system, thus it will need to cache the user once they're identified, just as if the user identified itself with a classic login.
On the logout side, you can either log out of the application itself (tomcat in this case) or you can log out of the SSO system (which seems to be what you're doing here). With the later approach, you're running into the problem of "Single Sign Out": Logging out of the SSO system should invalidate all sessions that once were initiated with the associated login. As I know it, the SSO system needs to keep track of all of the systems that have signed on through it and trigger an explicit logout there.
I can't tell you how to implement this in Keycloak, but hope that the general principle helps guiding you towards the solution:
The use or non-use of a session on Tomcat's side has nothing to do with the problem: You might have applications that legitimately store information in a session in addition to the signed in user - those applications should continue to work even if you're not comparing passwords in tomcat itself.
Edit, after your comment:
If this one page doesn't trigger the use of a session, any other code (e.g. the code that processes your login) still might trigger a session and then later delegate to the page that doesn't want to use a session.
I'd expect that you'll have to disable sessions in Tomcat's configuration e.g. through providing a custom "Manager" implementation. It looks like the default ones do not expect you to completely ignore sessions. As I've outlined above, I'd also expect sessions to be required even if you're not logging in through Tomcat itself.
Another way to avoid sessions (this is the indicator why I don't expect "no session" config to work) is to avoid calling any method on request/response that would trigger the automatic creation of a session. And it seems that you have such a method somewhere in your app.
(someone correct me if I'm wrong. This is mostly my educated expectation as I've never looked at this requirement)
I need to realise "logged in system" policy which means only one session per login. But problem is that I have sessionCreationPolicy.STATELESS and sessions actually doesn't exist. So how can I solve this task? What is the best approach?
I don't think you have a problem here. Since you're using STATELESS approach it means that Spring will not create any session: no security context, no cookies, every request must be authenticated on its own.
Some users of my application can use it for a fixed maximum amount of time. At the first request happening past the expiration time, after checking the user is part of the target group, I want to invalidate the session, update the user and return a 401.
In theory a servlet filter invoked post-session-validation could be used for this. I am looking for pointers on how to do this using spring security.
Thanks!
While you could most certainly just add a normal servlet filter that executes at the very end of the chain (or at least after the Spring Security filter stack) where you get the SecurityContext and inspect the user (potentially logging out the user like this or this), I would suggest you instead simply change the session duration on per-user basis. After a successful login (AuthenticationSuccessHandler is a good place) you could simply call setMaxInactiveInterval on the session and give it a different value depending on the user's role. This seems a lot cleaner to me as you don't have to separately handle otherwise semantically equal actual and forced session expiration/logout cases.
i have a Swing-client and a Server running on tomcat 7, which communicate with each other using Spring (3.1) HTTP invoker. The communication works fine so far (even with TSL), but now i am trying to add Spring Security.
side-note: In a typical webapplication i would use basic authentication to authenticate the user. After my CustomAuthenticationProvider returns an Authentication object for the user, everything "just works", meaning that on every further request the SecurityContext is automatically set. I guess the login returns a session-key to the client which is send on every request to identify the session.
That is pretty much what i am looking for with HTTP-Invoker. At the moment it seems like i get a new context on every request, which is bad, because my customAuthenticationManager.authenticate(Authentication auth) method is pretty costy and should really only be called once per user-session.
Any Idea?
edit i found some hints on this at http://forum.springsource.org/showthread.php?10764-Maintaing-State-while-using-HttpInvoker ,but as this link is more then 8 years old, i was hoping for an easier solution.
I found the solution now. First you need to know that the spring-security part is completely the same as it would be in a webapplication (which is great).
On client-side you need a more complex HTTP-client implementation. I used org.springframework.remoting.httpinvoker.HttpComponentsHttpInvokerRequestExecutor. On server-side you could use the create-session="always"-Attribute of the <http-element to ensure that a session is always created. However, i found it better to create the session myself (just call httpServletRequest.getSession() which creates a session if non exists), because that way you can specify when to do that. In my case i create the session in my authenticationProvider only if authentication was successful.