Stop Authenticated Users From Accessing Login Processing URL - Spring Security - spring

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>

Related

Spring security session management and Spring MVC view resolver error

I am working on a Spring MVC web application. Last week I started adding Sping Secuirty to my project. The problem I am facing concerns session management.
Here is http part of my spring-security.xml
<http auto-config="true">
<intercept-url pattern="/css" filters="none"/>
<intercept-url pattern="/js" filters="none"/>
<intercept-url pattern="/logout" filters="none"/>
<intercept-url pattern="/loginfailed" filters="none"/>
<intercept-url pattern="/login" filters="none"/>
<intercept-url pattern="/**" access="ROLE_USER" />
<form-login login-page="/login" default-target-url="/hello"
authentication-failure-url="/loginfailed" />
<session-management invalid-session-url="/login.jsp?error=sessionExpired" session-authentication-error-url="/login.jsp?error=alreadyLogin">
<concurrency-control max-sessions="1" expired-url="/login.jsp?error=sessionExpiredDuplicateLogin" error-if-maximum-exceeded="false"/>
</session-management>
</http>
Login/logout works fine, but when I try to invalidate user session by trying to login from different browser invalid-session-url="/login.jsp?error=sessionExpired" fails. Browser get redirected, because I see that GET request to login.jsp?error=sessionExpired is being sent. However, web page shows error saying that resource is not available. I suspect that it has something to do with
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass">
<value>org.springframework.web.servlet.view.JstlView</value>
</property>
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
in my dispatcher-servlet.xml. However, I don't know exactly how to fix this issue. login.jsp is located in WEB-INF/pages/
It seems to me Spring MVC DispatcherServlet couldn't find a mapping for /login.jsp because it's not set as a view that accessible without controller. I'm also assuming you had /login mapped to login.jsp (you did not provide enough info to confirm this), but if this is the case, just use expired-url="/login?error=sessionExpiredDuplicateLogin
You are redirecting to the jsp not the mapped url.
session management tag should be :
<session-management invalid-session-url="/login?error=sessionExpired" session-authentication-error-url="/login?error=alreadyLogin">
<concurrency-control max-sessions="1" expired-url="/login?error=sessionExpiredDuplicateLogin" error-if-maximum-exceeded="false"/>
</session-management>

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 Webflow: logout

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>

CAS Authentication failing when user navigating from one web app to another web app

We have two web applications. Both are enabled with CAS authentication. We can navigate from web application(Application A) to another one(Application B). Some times sessionManagementFilter is redirecting to session expired page ,when user navigating from Application A to B.We are getting session invalid page for Application B. Here is our spring configuration settings in applicationContext-security.xml file.
Any idea what is the causing the issue. Prompt response is appreciable.
<http entry-point-ref="casProcessingFilterEntryPoint" >
<custom-filter position="CAS_FILTER" ref="casProcessingFilter" />
<custom-filter ref="sessionManagementFilter" before="SESSION_MANAGEMENT_FILTER" />
<logout logout-url="/j_spring_security_logout.xhtml" logout-success-url="calltoolSecurity{CAS_URL}/logout" invalidate-session="true" />
</http>
<beans:bean id="sessionManagementFilter" class="org.springframework.security.web.session.SessionManagementFilter">
<beans:constructor-arg name="securityContextRepository" ref="httpSessionSecurityContextRepository" />
<!-- this permits redirection to session timeout page from javascript/ajax or http -->
<beans:property name="invalidSessionStrategy" ref="actInvalidSessionStrategy" />
</beans:bean>
<beans:bean id="actInvalidSessionStrategy" class="com.avivausa.api.web.JsfRedirectStrategy">
<beans:constructor-arg name="invalidSessionUrl" value="/pages/system/errorSessionExpired.xhtml" />
</beans:bean>
Please make sure that both application using the same CAS server to login.

Blazeds and Spring security, can remember-me be used in this combination?

I'm using the latest release of Spring Blzeds integration which has some features making it easier to secure invocations on destination objects. However the basic setup I use which uses the ChannelSet login approach form the flex side looses the authentication information (sessions) on each page refresh. Here's the configuration I'm using:
<http entry-point-ref="preAuthenticatedEntryPoint" >
</http>
<beans:bean id="preAuthenticatedEntryPoint" class="org.springframework.security.ui.preauth.PreAuthenticatedProcessingFilterEntryPoint" />
<beans:bean id="userAccountManager" class="com.comp.service.managers.jpa.UserAccountJpaManager" />
<beans:bean id="userService" class="com.comp.auth.JpaUserDetailsService" />
<beans:bean id="defaultPasswordEncoder" class="com.comp.auth.DefaultPasswordEncoder" />
<authentication-provider user-service-ref="userService">
<password-encoder ref="defaultPasswordEncoder"/>
</authentication-provider>
<flex:message-broker>
<flex:secured />
</flex:message-broker>
<bean id="testService" class="com.comp.service.TestService">
<flex:remoting-destination channels="comp-amf" />
<security:intercept-methods>
<security:protect method="say*" access="ROLE_USER" />
</security:intercept-methods>
</bean>
Is there another way to configure/implement this so I could get persistent sessions (remember me). Is it possible to do the logins from flex over standard HTTP POST (like forms) and still get the same level of granularity for protecting remote object calls?
Try adding this to your config:
<http entry-point-ref="preAuthenticatedEntryPoint" create-session="always">

Resources