Spring Webflow: logout - spring

I am using Webflow 2.3.0.RELEASE and Spring 3.1.2.RELEASE with Spring security and Freemarker.
It all works well except that when I logout the session is not destroyed.
e.g. when I click the logout link on the screen, I can see the logout screen successfully with url like this:
http://localhost/mart/adminflow.html;jsessionid=855454DFGDFG54501DSF548036?execution=e1s1
If I copy this url and paste into a new window, it just works with me still logged in.
I am not too sure what code to share, but I can share.
Any advice/
Thanks
UPDATE 1:
The logout link :
<a class="link_a" href="../j_spring_security_logout">
Security config:
<security:global-method-security secured-annotations="enabled" />
<bean id="preAuthenticatedProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
<security:http use-expressions="true" auto-config="false" entry-point-ref="preAuthenticatedProcessingFilterEntryPoint">
<security:custom-filter position="PRE_AUTH_FILTER" ref="preAuthFilter" />
<security:logout logout-success-url="logout.htm?_eventId=logout" />
<security:session-management invalid-session-url="logout.htm?_eventId=logout" />
</security:http>

Related

Stop Authenticated Users From Accessing Login Processing URL - Spring Security

I'm creating a web app that will be run on a single page. For this reason, I need to have my authentication paths accessible using only Ajax calls (no redirection).
I'm using Spring Security and I have the login and logout functionality working fine so far. The issue is that when the user is already authenticated and they POST to the login-processing-url they are actually logged in again. What I want to happen is my jsonAuthenticationHandler or some other handler to return a 500 or something telling me I can't log in again.
Here's what I've got for my security XML:
<sec:http use-expressions="true" entry-point-ref="jsonAuthenticationHandler">
<sec:intercept-url pattern="/data/**" access="isAuthenticated()"/>
<sec:intercept-url pattern="/data/login" access="!isAuthenticated()"/> <!--This is the line that is not behaving as expected-->
<sec:form-login login-page="/data/loginpage"
login-processing-url="/data/login"
username-parameter="username"
password-parameter="password"
authentication-failure-handler-ref="authenticationFailureHandler"
authentication-success-handler-ref="authenticationSuccessHandler"/>
<sec:logout logout-url="/data/logout"
delete-cookies="true"
invalidate-session="true"
logout-success-url="/"/>
</sec:http>
<bean id="jsonAuthenticationHandler" class="com.example.security.JsonAuthenticationHandler">
<constructor-arg name="loginUrl" value="/data/loginpage"/>
</bean>
<bean id="userDetailsService" class="com.example.security.UserDetailService"/>
<bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<bean id="authenticationSuccessHandler" class="com.example.security.AuthenticationSuccessHandler"/>
<bean id="authenticationFailureHandler" class="com.example.security.AuthenticationFailureHandler"/>
<sec:authentication-manager>
<sec:authentication-provider user-service-ref="userDetailsService">
<sec:password-encoder ref="encoder"/>
</sec:authentication-provider>
</sec:authentication-manager>
Thanks in advance for any help!
Assuming you have a form to login you can simple hide it after successful Ajax post or you can use security taglib
<sec:authorize access="isAnonymous()">
<!-- you form here -->
</sec:authorize>
It will render when there is no user logged in, but when you log you can make a call to render again the view, then the content of these tags will disappear because now the user is authenticated.
These tags render the content based on what role or status of authentication.
Maven dependency:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>

Redirect to view-state afte login success

I'm using for first time spring security (3.2.0.RELEASE) and spring webflow (2.4.0.RC1).
I have a webflow where there is a view-stat which needs a user authenticated:
<view-state id="finish" model="order">
<secured attributes="ROLE_USER" />
<on-render>
<render fragments="body" />
</on-render>
</view-state>
If user is not already authenticated is redirected to a login page. I'm wondering if would be possible: user insert his credentials into login page and if he has success, redirect him to "finish" view-state again with all information of flow.
It's posible?
Yes it is possible. In spring-security.xml specify the flow URL in "default-target-url" attribute.
If the URL to your flow is something like screen/finish, then the configuration would be like below
<http auto-config="true" >
<form-login login-page="/login.jsp"
login-processing-url="/j_spring_security_check"
authentication-failure-url="/login.jsp?error=t"
default-target-url="screen/finish"
always-use-default-target="true" />
<!--other configurations -->
</http>

spring security redirect by using excel hyperlink

I use Spring Security for my web application
By default, the authentication mechanism redirect the user on the "home", but it's possible to access directly to one screen of the application by its URL.
Everything is working well if you fill the URL in your web-browser.
BUT, if I have an hyperlink in Excel sheet, with the same URL, I get the login page, and then I'm forward to the "home" whereas I wanted to access my specific screen.
If I open the Excel sheet with OpenOffice, everything is working well ; as if I were filling the URL in the web browser.
Here is my configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<security:http auto-config="true" access-denied-page="/accessDenied.jsp" use-expressions="true" access-decision-manager-ref="accessDecisionManager" entry-point-ref="entryPoint">
<security:intercept-url pattern="/css/*.css" access="permitAll" />
<security:intercept-url pattern="/images/**" access="permitAll" />
<security:intercept-url pattern="/javascript/*.js" access="permitAll" />
<security:intercept-url pattern="/j_spring_security_check" access="permitAll"/>
<security:intercept-url pattern="/register.*" access="permitAll" />
<security:intercept-url pattern="/registerUser.*" access="permitAll" />
<security:intercept-url pattern="/login.*" access="permitAll" />
<security:intercept-url pattern="/restore/*" access="permitAll" />
<security:intercept-url pattern="/customer/**" access="permitAll" />
<security:intercept-url pattern="/logout.*" access="isAuthenticated()" />
<security:intercept-url pattern="/j_spring_security_logout" access="isAuthenticated()"/>
<security:intercept-url pattern="/index.*" access="isAuthenticated()" />
<security:intercept-url pattern="/admin/**" access="hasRole('ADMIN')" />
<security:intercept-url pattern="/template/*" access="isAuthenticated()" />
<security:intercept-url pattern="/editor/*" access="hasRole('EDITOR')" />
<security:intercept-url pattern="/creator/*" access="hasRole('CREATOR')" />
<security:intercept-url pattern="/task/*" access="hasAnyRole('CREATOR','EDITOR')"/>
<security:intercept-url pattern="/ajax/*" access="hasAnyRole('CREATOR','EDITOR')"/>
<security:intercept-url pattern="/**" access="isAuthenticated()" />
<security:form-login default-target-url="/index.jsp" authentication-failure-url="/login.jsp?login_error=true"/>
<security:logout invalidate-session="true" logout-url="/logout.jsp" logout-success-url="/login.jsp"/>
</security:http>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="userEnvironmenttStatisticService" />
</security:authentication-manager>
<security:global-method-security secured-annotations="enabled" pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler" />
</security:global-method-security>
<bean id="userEnvironmenttStatisticService" class="com.epam.crs.security.UserEnvironmenttStatisticService">
<property name="userDetailsService" ref="userDetailsService" />
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<constructor-arg>
<list>
<ref bean="notDeletedVoter" />
</list>
</constructor-arg>
</bean>
<bean id="notDeletedVoter" class="com.epam.crs.security.NotDeletedVoter" />
<bean id="entryPoint" class="com.epam.crs.security.ParameterizedLoginUrlAuthenticationEntryPoint">
<constructor-arg value="/login.jsp"/>
</bean>
<bean id="customPermissionEvaluator" class="com.epam.crs.security.CustomPermissionEvaluator" />
<bean id="expressionHandler"
class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator" ref="customPermissionEvaluator" />
</bean>
</beans>
Anybody can help me?
Maybe you have any idea how to fix it?
I got the same issue on a similar system. Here is how I fixed it and a bit more details behind my investigation.
How I fixed it for my similar app
I updated the entrypoint so it uses forwarding. Your updated code would be:
<bean id="entryPoint" class="com.epam.crs.security.ParameterizedLoginUrlAuthenticationEntryPoint">
<constructor-arg value="/login.jsp"/>
<property name="useForward" value="true" />
</bean>
Note: this requires that your entrypoint derives from LoginUrlAuthenticationEntryPoint
More details..
Typical flow of execution:
This is the typical flow of execution of a Spring Security setup like yours:
Anonymous user hits a secured page.
An AccessDeniedException is thrown and is captured by the ExceptionTranslationFilter. That filter adds the request coming from the anonymous user in the session.
The security entrypoint (that's your ParameterizedLoginUrlAuthenticationEntryPoint bean) then redirects the user to the login page. This redirection is done as a HTTP 302 redirect.
The user enters valid credentials.
The default SavedRequestAwareAuthenticationSuccessHandler is called. This handler loads the saved request (stored in the session in step 2) & redirects the user to that page (again with a HTTP 302 redirect.)
How Excel messes with that
Excel, for reasons that are out of scope, uses a simple http client before passing the url to your default browser.
That http client will pass the first url that returns a HTTP 200 code.
The http client will trigger the 3 first steps in the flow, landing on the login page.
Since the login page emits a HTTP 200, that is the url that Excel's http client will send to your browser.
The browser opens the login page, but it receives a new session id: it does not share the session cookie of Excel's http client.
When the user enters valid credentials, the SuccessHandler is called, just like in step 5, except that there is no saved request in the user's session (that saved request was saved in Excel's http client's session, not in the user's one). The handler defaults to sending the user to the default page: your home page.
Why does forwarding fixes this?
Forwarding simply handles the redirection on the server-side, excluding the browser/client from the process. So in the typical flow example, all of the redirections are done as forwards on the server-side.
Concretely, this means that the URL will not change. This allows Excel's http client to pass the right url to the browser, allowing your user to complete the 5 steps process without any hickups.
I had the same problem and for me this helped me:
http://support.microsoft.com/kb/218153
Install the Microsoft Fix it 50655:
http://go.microsoft.com/?linkid=9769998
Everything is working well if you fill the URL in your webbrowser.
BUT, if I have an hyperlink in Excel sheet, with the same URL, I get
the login page, and then I'm forward to the "home" whereas I wanted to
access my specific screen.
This is simply not determined by spring. Your URL's must be different, or you session expired.

Spring Security Remember Me service without HttpSession

My question is similar to this one, but I can simplify it some. Basically I want to authenticate users through the remember me cookie, but I want everything on the server side to be completely stateless, i.e. never create a HttpSession. I have the following setup:
<security:http use-expressions="true" create-session="stateless" >
<security:intercept-url pattern="/index.jsp" access="hasRole('ROLE_ANONYMOUS')" />
<security:intercept-url pattern="/**" access="hasRole('ROLE_TEST')" />
<security:form-login login-page="/index.jsp" default-target-url="/home" always-use-default-target="true" authentication-failure-url="/index.jsp?login_error=1" />
<security:logout logout-success-url="/index.jsp"/>
<security:remember-me key="MY_KEY" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="testUser" password="testPassword" authorities="ROLE_TEST" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
I authenticate just fine with the username and password above and see the remember me cookie in my browser. That part of it is working great. However, I'm finding it is creating a session during this process. I thought the create-session="stateless" was supposed to prevent this. Am I missing something here?
After working with this more, I found out that it wasn't Spring Security that was creating the session. The index.jsp was creating a new session every time I hit it. I simply added <%# page session="false"> to the top of index.jsp, and now there are no sessions being created.

Immediate signing in after logout causes redirection to home page

I have a common login and logout screen. When i logout after signing in... I come to signin page. Default behavior of spring security invalidates the session on logout so if i try to sign-in using the same screen, i get redirected to home page as there is no session available at that point. The desired behavior should be able to sign-in immediately after sign-out, which is not happening due to session invalidation
<http use-expressions="true" access-denied-page="/access-denied">
<intercept-url pattern="/secured/user/sign-up" access="hasAnyRole('ROLE_USER','ROLE_ANONYMOUS')" />
<intercept-url pattern="/secured/user/sign-in" access="hasRole('ROLE_ANONYMOUS')" />
<intercept-url pattern="/secured/**" requires-channel="https" />
<intercept-url pattern="/user/dashboard/**" access="hasAnyRole('ROLE_IC')" />
<intercept-url pattern="/**" access="permitAll"
requires-channel="http" />
<form-login login-page="/secured/user/sign-in"
authentication-success-handler-ref="authenticationSuccessHandler"
authentication-failure-url="/secured/user/sign-in" />
<logout logout-success-url="/secured/user/sign-in?loggedout=true"
logout-url="/secured/logout"/>
<security:session-management
session-fixation-protection="none">
</security:session-management>
</http>
If you refer to the xml, you will see /secured/user/sign-in is used for both sign-in and sign-out
How can I handle this issue ?
I think that as a "for now" solution.
You can:
Declare your own HttpSessionEventPublisher in your web.xml:
<listener>
<listener-class>org.yourcompany.MyHttpSessionEventPublisher</listener-class>
</listener>
In the HttpSessionEventPublisher grab the HttpSessionDestroyedEvent and don't allow spring to invalidate the seesion.
I'm not sure if this s a 'correct' solution, but it should work.
I managed to get a work around for this issue by using invalidate-session="false"

Resources