Redirect to Login for isFullyAuthenticated() URL and then, back again - spring

I am using Spring Security 3.1.x and trying to achieve the following scenario:
a page is secured with isFullyAuthenticated()
the current user is only authenticated with Remember Me, so not fully authenticated
the user navigates to this fully authenticated page - this should not be permitted (and it's not)
however, the user should not get the 403 page - instead, the user should be prompted to login via the Login form
after logging in, the user should be allowed to proceed to the page he previously requested, since now he's a fully authenticated user
My Spring Security config is:
<http use-expressions="true">
<intercept-url pattern="/admin/full_auth_only.html" access="isFullyAuthenticated()" />
<form-login login-page="/login.html" default-target-url="/authenticated.html" />
<logout />
<remember-me key="someAppKey" />
</http>
And I tried to add:
<access-denied-handler error-page="/login.html" />
However, the problem is now that, when visiting the page, I am indeed prompted by the Login form, only the URL doesn't correspond to login; instead it's the URL of the fully authenticated page:
http://localhost:8080/spring-security/admin/full_auth_only.html
Which then breaks the authentication process, which fails when trying to access the (invalid) URL:
http://localhost:8080/spring-security/admin/j_spring_security_check
This should have been:
http://localhost:8080/spring-security/j_spring_security_check
Any help on this is appreciated - I think the usecase is very common and so I would prefer using the namespace support instead of going in a custom direction.
Thanks.
Eugen.

I couldn't reproduce your issue with version 3.1.3.RELEASE of Spring Security. Which version do you use?
Authentication requests are intercepted by the AbstractAuthenticationProcessingFilter that checks if the URL of the request ends with a pre-configured value (that defaults to /j_spring_security_check). Any URL with that ending will trigger an authentication attempt. You can see the related code here.
This means that the URL you said is invalid should in fact be processed without problems.
The code linked above hasn't been changed since very early versions (2.x), so there should be some other issues in your case.
If you could share your configuration and some debug level logs, that would help to reveal what's the real problem.

1.Remove any welcome-file-list if you have in web.xml.
2.Make sure always-use-default-target is not set to false in form-login tag or remove it all together.
3.And make sure you have permitted every one to access your login page. something like this <intercept-url pattern="/login.htm" access="permitAll()"/>
That should work.

it sounds like the cookie was not set, and the following requests sent were all treated as the first requests without a session ID, so spring security asked for login every time even though you had logged in.
If you were using google chrome, and tested the application in your local machine using the localhost address, the cookie might not be set. And it is a known issue with Google chrome.
You can try 127.0.0.1 instead to test. Or try another web browser like Internet Explorer.

Related

Is it possible to redirect at home page if session is live using Spring-Security?

I am using Spring Security for Web application development. I do not want to allow users to do registration while they are already loggedIn in the System.
So suppose, there is url for registration is /registration and for home page is /home.
Now I want to redirect at /home if user tries to hit /registration while session is live. Is it possible using spring-security ? I can check session in controller method and redirect manually...that I know. but is there any config with spring-security? Thanks.
Yes, you can do it with Spring Security only. Add a new security:http element before your existing one as follows:
<security:http pattern="/registration" access-denied-page="/home" entry-point-ref="forbiddenEntryPoint">
<security:intercept-url pattern="/registration" access="ROLE_ANONYMOUS"/>
</security:http>
<bean id="forbiddenEntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
The entry point implementation doesn't really matter, because it won't be invoked. It's just mandatory to define it.
System will now monitor URL /registration and when it's hit by a user without ROLE_ANONYMOUS (= an authenticated user) it will serve content from /home instead.

Delete access_token after logout

i have a little question.
At the moment my Spring configuration uses the DefaultTokenServices (provided by the spring-security-oauth2-2.0.0.M3.jar).
It generates correctly the access_token.
Now what i will do is to cancel/delete/remove/revoke this token when i do a logout.
In the security.xml i configured the logout in the http tag:
<sec:logout logout-url="/logout" logout-success-url="/auth" invalidate-session="true" delete-cookies="true" />
and the redirection is successfully. But if i write a test doing a login, logout and after i try to access a restricted path with this access_token i can get a successful request, but i expect a Not authorized Error.
Why?
How can i configure the logout that the access_token are automatically deleted to force an new login?
The lifetime of the access_token is independent of the login session of a user who grants access to a client. OAuth2 has no concept of a user login or logout, or a session, so the fact that you expect a logout to revoke a token, would seem to indicate that you're misunderstanding how OAuth2 works. You should probably clarify in your question why you want things to work this way and why you need OAuth.
If you really want this behaviour, then you would have to code it yourself (in a custom Spring Security LogoutHandler, for example), but the lifetime of a token is normally governed by its expiry time. Token revocation would usually be a separate interface provided to the user, allowing them to prematurely revoke access to their resources for one or more clients - something like Twitter's third-party applications access.
At the end I followed this
link
And in the LogoutHandlerFilter i call the TokenService.revokeToken() method.

Spring Security: session.invalidate() vs invalidate-session="true"

What's the difference between the two? I'm not so sure but I believe the HttpServletReqest.getSession.invalidate() invalidates the user's session only while the invalidate-session="true" invalidates the session and redirects the user to the defined session-expired page. Please correct me if I'm wrong, I would want to understand this more. Thanks.
invalidate-session is an attribute on the <logout> element and causes the session to be invalidated upon logout (which is the default behavior), but doesn't cauese any redirection itself.
The session-expired page comes into picture if a request contains an invalid/expired session id, in which case the SessionManagementFilter redirects it to a pre-configured URL, which you can set through the <session-management invalid-session-url="..."> configuration. In case nothing is set, no redirection happens.
HttpServletReqest.getSession.invalidate() simply invalidates the session, as you said.

How to add a message to session when login is required in Spring security?

I have a decent login system working with Spring 3 security.
If a user tries to access a secure page prior to login, he is bounced to the login page, and then upon successful login, he is redirected back to the page that he tried to access previously. This is almost exactly what I want.
What I ALSO want is a special error message to appear on the login page explaining to the user that he has been redirected there because he has tried to access a secure area. How can I do this (without showing that error message on the login page for people who haven't previously tried to access a secure page)?
Thanks!
P.S. I have read http://static.springsource.org/spring-security/site/docs/3.0.x/reference/springsecurity-single.html#getting-started and many posts on this site and others but have not found the solution.
Are you using jsp? Then something like this might be useful.
Would you like to customize your error message from Spring Security? Take a look here.
On your login jsp page you can retrieve HTTP header referer (e.g. with jstl - ${header['referer']}) which would tell you what page user tried to access before being redirected to this login page.
Displaying a error message in the login page it is something done authomaticaly by Spring. You can see how it is discussed here. I think that this is more about displaying login error as "Bad credentials" but take it in mind anyway.
For your case, displaying a error message related with access denied can be done just defining the access denied page in the spring security configuration.
Usually, you can see something like this:
<http auto-config="true" access-denied-page="/403.jsp">
....
</http>
but also you can do this and control in the login jsp if myError variable comes in the request:
<http auto-config="true" access-denied-page="/login.jsp?myError=access-denied">
....
</http>
I don't think any of the answers here provide a clean generic solution to the original problem. I do not understand OP's solution and it may be specific to his situation.
When a user clicks on a secure URL, spring redirects the user to the login page. The original request is stored in the session. And spring doesn't pass any of the parameters in the original request to the login page.
You can add something like the following to the login.jsp:
<%
if((SavedRequest)session.getAttribute("SPRING_SECURITY_SAVED_REQUEST") != null && ((SavedRequest)session.getAttribute("SPRING_SECURITY_SAVED_REQUEST")).getParameterMap().get("LOGINMSG") != null){
out.println('<%= ((SavedRequest)session.getAttribute("SPRING_SECURITY_SAVED_REQUEST")).getParameterMap().get("LOGINMSG")[0]%>');
}
%>
Where LOGINMSG is the custom end user login message that you appended to the original secure URL.
I hope the spring security team would chime in and validate ( or invalidate ) this approach.

Remember-Me with Spring Security, various questions

I'm using Spring Framework 3.0.5 and Spring Security 3.0.5 for developing a webapplication where users can log in and log out, using Remember-Me-Service, if they want to.
As I don't have pretty much experience, I wonder if it's working correctly. I use PersistentTokenApproach (with my own implementation, because I use Hibernate.) I can see the cookie is created on login and deleted on logout.
If I have an valid Remember-Me-Cookie and close the Browser, Im successfully logged in again when I open the browser again. So far, so good.
Now, I'd just like to know if those things I noticed are working as they are expected to or if I maybe did make a mistake.
1) When a user logs in without remember-me and the browser-tab is closed (not the browser itself), on reopening a new browser-tab he is still authenticated (he's using the same JSESSIONID). When closing the browser and reopening again, he isn't authenticated anymore. Regarding the security of a webapplication, is this a recommended ("normal") behaviour?
2) When remember-me used and the user is successfully authenticated (by login or later by cookie), there are no more checks on the cookie. that means, if meanwhile the user is online I'd delete the cookie from the database, the user would still be logged in, allowed to watch even the secured pages. I guess this happens because he was authenticated before and keeps using the same SESSIONID. When I close the browser and reopen it again, he isn't authenticated anymore.
3) When I dont own a cookie and open the main page, for every request I send (every picture, every file on the page) the server is checking for the rememberme-cookie. Is that correct?
Sorry for the newbie-questions, but I just want to make sure everything is working as it should. :-) Thanks in advance!
1) As far as tabs within a browser go, I am pretty sure they all share the same browser session. If you try using gmail or other web-based services you'll see the same behaviour when you close / open tabs. With older versions of IE (maybe version 6) separate instances had their own sessions, unless they were spawned from existing IE instances.
2) This sounds correct. Its not really ideal to hit the database on every request after they have been authenticated.
3) That is correct, as by default the spring security filters will be filtering on /* - and trying to look for authentication info. You can add excludes to your security config for resources you dont need to protect- ie
<http> <intercept-url pattern="/images/**" filters="none"/>

Resources