Spring Security cannot request URL with jessionid - spring

I am developing a web application using Spring 5.3.20, Spring Security 5.7.1 and Tomcat 9.0.62.
Here is my Spring Security settings:
<form-login login-page="/home" />
<logout logout-url="/logout"
logout-success-url="/login?logout"
delete-cookies="JSESSIONID"/>
<session-management invalid-session-url="/main?timeout" session-authentication-error-url="/main?error"
session-fixation-protection="newSession">
<concurrency-control max-sessions="1" expired-url="/mail"
error-if-maximum-exceeded="true" session-registry-alias="sessionRegistry" />
</session-management>
The problem is when user logged out, the JSESSIONID cookies is deleted and the URL Rewriting kicked in.
As as result, the CSS, JS URLs become something like this.
http://localhost:8080/bookstore/resources/css/bootstrap.min-7184d3edc008c1890deb0a71e4348267.css;jsessionid=5052769FD8FEB8D2901C8CCB2B6A0C66
http://localhost:8080/bookstore/resources/js/jquery-1.12.3.min-2b6294333db8eeb65bc7717144357d23.js;jsessionid=5052769FD8FEB8D2901C8CCB2B6A0C66
The JESSIONID and semicolon are appended to the URLs which is a problem because according to those links below, the Spring Security will reject URLs that contain semicolons.
Spring getting The request was rejected because the URL contained a potentially malicious String ";"
https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/firewall/StrictHttpFirewall.html
There are two ways to solve this problem.
Not deleting the JSESSIONID cookies when logged out by removing delete-cookies="JSESSIONID"
<logout logout-url="/logout"
logout-success-url="/login?logout"/>
Forcing Spring Security to allow semicolons in URL by using setAllowSemicolon(true)
But from best security practices perspectives I think both of those solution above are not really good.
Can you guys elaborate in real world web application how people handle such a situation?

Related

Session fixation in Spring Security

We are trying to prevent session fixation attack in our application. This means we are expected to generate new JSESSIONID every time a user logs into application.
Current scenario doesn't generate new JSESSIONID post authentication with ADFS (Active directory). Thus we would like to achieve the same. Can you let us know, how to achieve solution for this kind of attack?
We have Spring, Primefaces and Spring Security used in our application. We tried implementing below tags in our Spring security.xml file. However, it doesnt seem to generate new JSESSIONID post authentication is successful with ADFS. This spring-security.xml has been added in web.xml. Can you let us know what is wrong with below use? We are using Spring Security 3.2.10 in project.
<sec:http create-session="always" use-expressions="true">
<sec:intercept-url pattern="/*" />
<sec:http-basic />
<sec:session-management invalid-session-url="/"
session-fixation-protection="newSession">
<sec:concurrency-control max-sessions="150"
expired-url="/" />
</sec:session-management>
<sec:csrf/>
</sec:http>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider>
<sec:user-service>
<sec:user name="abc" password="abc" authorities="ROLE_USER" />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
If you are using the Basic authentication for API, you'd better not create new session
<sec:http create-session="stateless" ....
If you want to create new session post authentication, the default Basic Filter is not supported, but you can implement your own filter and just like AbstractAuthenticationProcessingFilter, there is SessionAuthenticationStrategy in it, and SessionFixationProtectionStrategy will create a new session with exist attributes in old session post authentication.
I suposse you are using form-login because talking about users login in. Spring includes out-of-the-box session fixation protection. In SessionManagementFilter, in doFilter method, you can see that if the user has been authenticated in the current request, the session authentication strategy is called. This strategy by default is SessionFixationProtectionStrategy.
Apparently your configuration is correct, debug that method and check what is happening. Besides, login forms are recommended to be light and sessionless if possible, so default create-session value "IfRequired" should be preferred instead of "always". Anyway newSession strategy should invalidate current session, ceate a new one and return a new JSESSIONID cookie.

Spring REST Basic Authentication Design Approach

Environment :
Spring 4
Spring Security 4
Spring MVC 4
Hibernate 4
MySQL
Issue :
Below is the requirement :
1)We are developing a Spring REST service for inventory management.
2)This web service will be consumed by .NET client. (or may be mobile device in future)
3)The users of REST service need to be authenticated. The user will use login form displayed by .NET client and if authentication is successfull , he will be
allowed to consume REST API.
4)If authentication fails , user won't be allowed entry into REST service.
Now we have decided to use Basic Authentication for this.
My question is : How do we achieve this using Spring MVC REST and Spring security ?
Below is my first attempt :
application-security.xml
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/usermanagement/authenticate" access="permitAll"/>
<intercept-url pattern="/abhishek/*" access="hasRole('ROLE_ADMIN')"/>
<http-basic/>
<csrf disabled="true"/>
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="Atul" password="12345" authorities="ROLE_ADMIN" />
</user-service>
</authentication-provider>
</authentication-manager>
Following is the flow happening right now :
1)The /authentication API looks up user in Db and returns Http Status code 201(success ) or 401 (failure) accordingly. (this url is unsecured)
2)If success , client puts username/password as Authorization header (which is used in login) and sends this header for future Http requests.
3)Now once next request comes (this is secured), spring security comes into picture and again authentication happens here.
But this time it will be Spring provided.
4)So there are two authentication mechanism are being used .
5)I know I am messing up here , but not able to decide on what is the correct approach to design this.
6)How can client be provided the authentication capability by hooking into Spring security ? He needs to know authentication success/failure
immediately after he logs in.
Please help since I am struggling a lot on this.

how to delete remember me cookie in spring security

I was wondering how to the remove the remember me cookie when using spring remember me services.
I am using the default remember me cookie name
I came across the following documentation in spring to delete the JSESSION.
<http>
<logout delete-cookies="JSESSIONID" />
</http>
But is it possible to do something like below to delete the remember me cookie as well
I don't have a logout controller and i have the following configuration in the spring xml.
<http use-expressions="true">
<!-- Authentication policy -->
<form-login login-page="/signin" login-processing-url="/signin/authenticate" authentication-failure-url="/signin?param.error=bad_credentials" />
<logout logout-url="/signout" delete-cookies="JSESSIONID" />
....................
I don't think you have to manually delete the remember-me cookie. The AbstractRememberMeServices implements the LogoutHandler interface, so it will receive a call-back from the LogoutFilter, and makes sure the remember-me cookie is cancelled on logout.

Why do I get an invalid-session redirect after a Spring Security logout?

I have a Spring MVC project which uses Spring Security. I am wondering how j_spring_security_logout works. I have a logout link defined in a view like this:
Logout
In my spring-security.xml I have defined this:
<form-login login-page="/login" default-target-url="/wellcome" authentication-failure-url="/loginfailed" />
<logout logout-success-url="/logout" logout-url="/j_spring_security_logout" />
<session-management invalid-session-url="/invalidsession" />
I expected that clicking logout should redirect me to /logout, but instead I get redirected to the invalid-session-url, namely /invalidsession. The logout-success-url is ignored.
However when I delete session-management, logging out does indeed redirect me to /logout.
This is explained in the Spring Security reference manual.
You can't really use the session-expiry facility unless the session cookie is deleted when you log out.
Use just this one and it should work (without logout-url):
<logout logout-success-url="/logout" />
I think you may experience problems by using both logout and session management invalid session url because once you've logged out your session is no longer valid.
Update per your additional question, how about this :
<security:logout logout-success-url="/logout?displayLogout=1" />
<security:session-management invalid-session-url="/logout?displayLogout=0" />
And then in your view :
<c:if test="${param.displayLogout == 0}">
<h2>Your session has timed out.</h2>
</c:if>
Update #2, just tried it locally, when you logout your session is invalid and you get redirected to invalid-session-url location you specified in the session-management configuration.
Really interested in the solution now.

Spring Security in a Stateless webapp? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
create-session stateless usage
Im just beginning experimenting on Spring Security, on version 3.1, and im wondering how to achieve authentication with a stateless webapp.
http-basic and digest come to mind, and i've tried them, but i dislike the inability to logout like the form authentication without closing the browser.
I currently have a working stateless webapp with form-based authentication using spring security (which makes it stateful by storing auth stuffs in session perhaps ?), and i wonder what are the strategies that i could research on to make spring security work without making use of http sessions ?
I realize that there's a <http create-session="stateless" ..>, but there must be something that needs more doing because the app stops working correctly after i tried that, by keep authenticating me when accessing protected resources.
Here's my config :
<http use-expressions="true" create-session="stateless">
<form-login login-page="/login"
login-processing-url="/static/j_spring_security_check"
authentication-failure-url="/login?login_error=t" />
<logout logout-url="/static/j_spring_security_logout"/>
<intercept-url pattern="/person/test/**"
access="isAuthenticated() and principal.username=='albertkam'"
/>
<intercept-url pattern="/person/**" access="hasRole('ROLE_NORMAL')"/>
<remember-me
key="spitterKey"
token-validity-seconds="2419200"/>
</http>
With create-session="stateless" :
accessing http://myhost:8080/mycontext/person/blah
goes to login page
returns to homepage url http://myhost:8080/mycontext after logging in (i expect it returns to the protected resource)
Without create-session="stateless", which defaults to ifRequired (stateful) :
accessing http://myhost:8080/mycontext/person/blah
goes to login page
returns to the protected url http://myhost:8080/mycontext/person/ blah after logging in (this is correct behaviour , but stateful)
You can use always-use-default-target="false" on <form-login>to prevent going to default page after successful login.

Resources