Issue with Spring security's logout - spring-security

I've got a problem logging out in Spring framework.
First when I want j_spring_security_logout to handle it for me i get 404 j_spring_security_logout not found:
sample-security.xml:
<http>
<intercept-url pattern="/messageList.htm*" access="ROLE_USER,ROLE_GUEST" />
<intercept-url pattern="/messagePost.htm*" access="ROLE_USER" />
<intercept-url pattern="/messageDelete.htm*" access="ROLE_ADMIN" />
<form-login login-page="/login.jsp" default-target-url="/messageList.htm"
authentication-failure-url="/login.jsp?error=true" />
<logout/>
</http>
Sample url link to logout in JSP page:
Logout
When i try to use a custom JSP page i.e. I use login form for this purpose then I get better result at least it gets to login page, but another problem is that you dont't get logged off as you can diretcly type url that should be guarded buy you get past it anyway.
Slightly modified from previous listings:
<http>
<intercept-url pattern="/messageList.htm*" access="ROLE_USER,ROLE_GUEST" />
<intercept-url pattern="/messagePost.htm*" access="ROLE_USER" />
<intercept-url pattern="/messageDelete.htm*" access="ROLE_ADMIN" />
<form-login login-page="/login.jsp" default-target-url="/messageList.htm"
authentication-failure-url="/login.jsp?error=true" />
<logout logout-success-url="/login.jsp" />
</http>
Logout
Thank you for help

I've just had this problem.
You need to make sure in web.xml your security filter matches on the url /j_spring_security_logout
e.g.
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/j_spring_security_logout</url-pattern>
</filter-mapping>

You should do POST request. Something like that:
<form action="${logoutUrl}" method="post" id="logoutForm">
<input type="hidden"
name="${_csrf.parameterName}"
value="${_csrf.token}" />
</form>
<script>
function formSubmit() {
document.getElementById("logoutForm").submit();
}
</script>
<c:if test="${pageContext.request.userPrincipal.name != null}">
<h2>
Welcome : ${pageContext.request.userPrincipal.name} |
Logout
</h2>
</c:if>

I ran into the same problem and after loosing hope, finally I found out the answer by accident.
Of course we learn a lot by reading and using someone else's codes and, by doing this we inherit settings we don't know much about.
And this is what happened to me when programming using Spring Security.
In the Spring Security XML, within the http tag, there is this line:
<logout invalidate-session="true" logout-success-url="/login" logout-url="/logout" />
I got this line during my research from some tutorial or example. And after 2 days struggling with the j_spring_security_logout keyword and getting nothing but error 404, I figured out this.
In the logout tag I am using, there's this logout-url parameter set to "/logout". Then I realized that according to my settings, my spring is expecting to receive /logout instead of /j_spring_security_logout.
Once I updated my code accordingly, it worked like a charm.

Is logout link aware of the context path?
For example, if your context path is "myapp", where does the above mentioned link point?
"http://localhost:8080/myapp/j_spring_security_logout" or "http://localhost:8080/j_spring_security_logout" ?
In fact, the j_spring_security_logout is only valid within the context of the webapp so only the first link would lead to the correct url

I had the same issue.
Seems to be a bug on 3.0.6!
I just downgrade to 3.0.5 and everything works nicely.

Try this link in your page whow content a logout link:
<h:outputLink value="#{request.contextPath}/logout.jsp">Logout</h:outputLink>
and creeate a logout.jsp file in your "webcontent" folder with the following code:
<% response.sendRedirect("/#{request.contextPath}/j_spring_security_logout"); %>
if an eror occured try to change "#{request.contextPath}" to the name of your project
ex: my project name is "security" so i am using in my logout.jsp file:
<% response.sendRedirect("/security/j_spring_security_logout"); %>

Related

Spring Security: Getting error "The server understood the request but refuses to authorize it"

While running the application using Spring Security, I am getting below error on all browsers:
"The server understood the request but refuses to authorize it"
I tried by changing Roles from "ROLE_ADMIN" to "ROLE_USER" in "spring-security.xml" file.
Below is "spring-security.xml"
<http auto-config="true">
<intercept-url pattern ="/admin" access = "hasRole('ROLE-USER')"/>
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name = "abc" password = "xyz" authorities="hasRole('ROLE-USER')" />
</user-service>
</authentication-provider>
</authentication-manager>
Below is SpringController Class:
#Controller
public class SpringController {
#RequestMapping(value = "/")
public String homePage() {
return "HomePage";
}
#RequestMapping(value="/admin", method=RequestMethod.GET)
public String loginPage() {
return "login";
}
HomePage.jsp and login.jsp pages are loaded property but after passing credentials on login.jsp getting error:
HTTP Status 403 – Forbidden
Type: Status Report
Message: Access is denied
Description: The server understood the request but refuses to
authorize it.
Apache Tomcat/7.0.90
403 is a very generic error code. I was facing the same issue but after making some changes I am able to make it work. Still not sure if the problem was with password encryption or configuration of form-login tag.
<security:http auto-config="true" >
<security:intercept-url pattern="/login*" access="isAnonymous()" />
<security:intercept-url pattern="/**" access="isAuthenticated()"/>
<security:form-login login-page="/login" login-processing-url="/login-user" authentication-failure-url="/login?error=true" />
<security:csrf disabled="true" />
<security:logout logout-success-url="/" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="admin" password="{noop}admin" authorities="ROLE_USER" />
</security:user-service>
</security:authentication-provider >
</security:authentication-manager>
Ignore the security: prefix in the tags.
{noop} in front of the password ensures that I am not using any encryption for the password.
Controller to show login JSP
#Controller
#RequestMapping("/login")
public class LoginController {
#RequestMapping(value = { "/", "" }, method = { RequestMethod.GET})
public String login(HttpServletRequest request) {
System.out.println("LoginController.login() "+request.getRequestURI());
return "login";
}
}
Form action
<form name='loginForm' action="login-user" method='POST'>
I got this issue but not while using spring. We were hosting two instances of our own in house application on the same server but using two different ports. Login to one instance was okay, however login to the other one from the same browser (another tab) caused the error above to be thrown from tomcat, preceded with this message "CSRF nonce validation failed".
The workaround I did is to login to the other instance from different browser. I know that this is not a fix but it may help if you have a situation similar to mine
This happens because you use normal <form> tags with spring security, while it checks for CSRF attacks.
The solution is:
Add CSRF hidden field with each <form> tag
<form action="..." method="POST">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
Or use spring MVC <form:form> tags which include this hidden field automtically (Recommended)
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<form:form action="..." method="POST">
</form:form>
This also happened with me when I accidentally launched two instances of my application on different tomcat servers. I resolved it by removing the working directories of the application in my webapps and work folders, and restarting the server.
use <form:form> tags when you're dealing with spring security, instead of manually adding the CSRF token for each forms as below
<form:form action="", method="">
</form:form>

Exclude IP adress from spring security cas filter

I have a site that uses CAS as a SSO solution and require all that access the site to be authenticated. To fulfill the regulations that our company has we need to create fully rendered snapshot copies of the site. I was thinking of using something like Httrack to accomplish this, but I need to get around the login. My plan was to exclude the IP address of the server running httrack, but I cannot seem to figure out how to configure this.
<sec:http name="contentSecurityFilterChain" use-expressions="true" access-decision-manager-ref="contentAccessDecisionManager" entry-point-ref="casAuthenticationEntryPoint">
<sec:custom-filter position="CAS_FILTER" ref="casAuthenticationFilter" />
<sec:logout logout-success-url="/logout.jsp" logout-url="/j_security_logout" invalidate-session="true" delete-cookies="sessionKey,userId,lastClient" />
<sec:access-denied-handler ref="accessDeniedHandler" />
<sec:custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER" />
<sec:custom-filter ref="singleLogoutFilter" before="CAS_FILTER" />
<sec:csrf disabled="true" />
<sec:headers>
<!-- Enable hsts if possible. See http://tools.ietf.org/html/rfc6797 -->
<sec:hsts disabled="true" />
<sec:cache-control disabled="true" />
<sec:frame-options disabled="true" />
</sec:headers>
<sec:intercept-url pattern="/monitoring/**" access="hasRole('ROLE_MONITORING')" requires-channel="${security.channel.dispatcher}" />
channel="${security.channel.dispatcher}" />
<sec:intercept-url pattern="/api/login" access="hasRole('ROLE_AUTHENTICATED')" />
<sec:intercept-url pattern="/**" access="hasRole('ROLE_AUTHENTICATED') or hasIpAddress('192.168.123.123')" requires-channel="${security.channel.dispatcher}" />
</sec:http>
I tried the above as a first attempt (where 192.168.123.123 represents my excluded server), but the request still gets redirected to the SSO site before returning to the filter chain.
The closest I got in my various naive fiddlings was by adding a filter to the entry point that did not trigger the commence method; While it did not redirect the request, it only returned an empty page. I assume that is because by not calling the commence method the request was seen as not matching the filter group.
Is there a way to exclude an IP address from the security filters OR is there a better way of doing this?
Suggestions most welcomed!

How to handle 404 with Spring Security?

I found only related topic for c# please don't blame me if I missed the resource.
It looks something like
/project/blablaentered and content with 404.
Effectively I just want to specify my own page when 404 page is thrown.
My security xml:
<security:http auto-config="true" use-expressions="true" >
<security:form-login login-processing-url="/static/j_spring_security_check" login-page="/login" authentication-failure-url="/login?login_error=t" default-target-url="/home"/>
<security:intercept-url pattern="/home" access="isAuthenticated()" />
<security:intercept-url pattern="/home/try" access="hasRole('ROLE_EDITOR')"/>
<security:access-denied-handler error-page="/accessDenied"/>
</security:http>
UPDATE: Please follow for solution: Custom 404 using Spring DispatcherServlet
The simplest way is probably enable an error-page element inside web.xml as long as you don't mind it being a plain JSP (ie, no controller). This way, URLs outside your DispatcherServlet which will generate a 404 from your servlet container will follow the same path as any URL that Spring is unable to map to a controller based on your configuration.
If this isn't good enough, you can define a #Exception method for a particular controller, or use a HandlerExceptionResolver.
You need add class:
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {
// Do nothing
}

Where are the pictures of my JSF page?

I have a navigation-rule like this in my JSF 2 application:
<navigation-rule>
<from-view-id>*</from-view-id>
<navigation-case>
<from-action>#{myBean.goToMyHome1}</from-action>
<from-outcome>myHome1.xhtml</from-outcome>
<to-view-id>/myhome1/myHome1.xhtml</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
When I put an h:commandLink in myHome2.xhtml within directory myhome2 that satisfy this rule, the page myHome1.xhtml will display but there are no images on the page. Where they go?
Behind the application is Springsecurity 3 with this config:
<sec:intercept-url pattern="/myhome1/**" access="hasAnyRole('ROLE1','ROLE2')" />
<sec:intercept-url pattern="/myhome2/**" access="hasRole('ROLE2')" />
This look like as if your picture URLs are relative to the current URL path. E.g.
<img src="images/picture.png" />
When you open the page by
http://example.com/contextname/myHome1.xhtml
then the image URL will effectively point to
http://example.com/contextname/images/picture.png
But when you open the page by
http://example.com/contextname/myhome/myHome1.xhtml
then the image URL will effectively point to
http://example.com/contextname/myhome/images/picture.png
You need to fix it accordingly. There are several ways. Use a domain-relative path
<img src="/contextname/images/picture.png" />
Or prepend the context name dynamically
<img src="#{request.contextPath}/images/picture.png" />
Or just use <h:graphicImage> which will do that automatically
<h:graphicImage value="/images/picture.png" />

Spring Security session-management setting and IllegalStateException

I'm trying to add <session-management> in my Spring Security namespace configuration so that I can provide a different message than the login page when the session times out. As soon as I add it to my configuration it starts throwing "IllegalStateException: Cannot create a session after the response has been committed" when I access the app.
I'm using Spring Security 3 and Tomcat 6. Here's my configuration:
<http>
<intercept-url pattern="/go.htm" access="ROLE_RESPONDENT" />
<intercept-url pattern="/complete.htm" access="ROLE_RESPONDENT" />
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<form-login login-processing-url="/j_spring_security_check"
login-page="/login.htm"
authentication-failure-url="/login.htm?error=true"
default-target-url="/go.htm"
/>
<anonymous/>
<logout logout-success-url="/logout_message.htm"/>
<session-management invalid-session-url="/login.htm" />
</http>
Everything works great until I add in the <session-management> line. What am I missing?
You are probably hitting this bug:
https://jira.springsource.org/browse/SEC-1346
Try using the up-to-date version (3.0.2.RELEASE).
This works for me
<session-management invalid-session-url="/taac/login">
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>
Maybe including the auto-config="true" attribute in the <http> tag helps, you might be missing some required filters or settings.

Resources