Spring Security Remember Me Redirect after RequireFully Authorized - spring

All,
I am trying to implement Remember Me functionality
I have two protected urls.
/operation/fully (user must be fully authenticated no remember me allowed)
and
/operation/authenticated (remember me ok)
If I have no remember me cookie and I visit either URL I am prompted for my credentials and redirected to the original URL life is good.
If I am in remember me mode, I can navigate to /operation/authenticated no problem. If I navigate to /operation/fully I am redirected to the login page. I then authenticate and am taken back to "/" I want to go back to my original target /operation/fully.
<http auto-config="true" use-expressions="true" access-denied-page="/login">
<form-login login-page="/login"
login-processing-url="/static/j_spring_security_check"
authentication-failure-url="/login" />
<logout logout-url="/j_spring_security_logout" logout-success-url="/logout"/>
<intercept-url pattern="/favicon.ico" access="permitAll" />
<intercept-url pattern="/operations/fully" access="hasRole('ROLE_USER') and isFullyAuthenticated()"/>
<intercept-url pattern="/operations/authenticated" access="hasRole('ROLE_USER')"/>
<intercept-url pattern="/login" />
<remember-me key="myKey"
token-validity-seconds="2419200" />
</http>
Somehow I need to get the user back to the original requested URL when they aren't fully authenticated. Any ideas on the best approach to do this?
I have come up with one solution, however it makes me cringe as it seems like it is more work than should be necessary.
In my scenario the ExceptionTranslationFilter is not invoking the login process and thus is not storing off the original URL.
The following line isn't called
requestCache.saveRequest(request, response);
instead a 403 is generated which I was catching via configuration and sending the user to the login page. In my case the user should be treated as if it they were anonymous and a 403 not be generated and the login process should begin.
The easiest way I found to change this behavior was to change the AuthenticationTrustResolverImpl
public boolean isAnonymous(Authentication authentication) {
if ((anonymousClass == null) || (authentication == null)) {
return false;
}
//if this is a RememberMe me situation, the user should be treated as
//if they were anonymous
if (this.isRememberMe(authentication)){
return true;
}
return anonymousClass.isAssignableFrom(authentication.getClass());
}
This seems to do exactly what I want, however since you can't get access to the ExceptionTranslationFilter when using the http namespace I had to do a lot of messy manual configuration.
Is there a more elegant way to do this?

There's a PR scheduled for Spring Security 4.2.0 M1 to address this need. Its associated commit probably gives hints to implement the same thing in previous versions of Spring Security.

Related

redirect to requested page after login using spring

This is my spring-security.xml
<http auto-config="true" path-type="ant">
<intercept-url pattern="/myaccount.html*" access="ROLE_CUSTOMER"/>
<intercept-url pattern="/viewpage.html*" access="ROLE_CUSTOMER"/>
<form-login login-page="/login.html"
authentication-success-handler-ref="ssoAuthenticationSuccessHandler"
login-processing-url="/j_security_check" default-target-url="/login.html"
authentication-failure-handler-ref="authenticationFailureHandler"/>
<logout invalidate-session="true" success-handler-ref="ssoLogoutHandler" delete-cookies="JSESSIONID,loggedIn,_bt,slc_f,slc_t,_px_i,attempt_auto_login"/>
<session-management session-fixation-protection="none"/>
</http>
If user access some URL I want to intercept him to login. After it needs to be redirected to the original requested page by user.
Above xml helps me to intercept when user access viewpage.html but after login success it is not taking me to viewpage.html. Instead it takes me to myaccount.html always.
SavedRequestAwareAuthenticationSuccessHandler is used as a default implementation class for AuthenticationSuccessHandler.
This should work as you expect.
I'm not sure what authentication-success-handler-ref="ssoAuthenticationSuccessHandler" is suppose to do, but try looking in to SavedRequestAwareAuthenticationSuccessHandler and see if you can get any clue.

AngularJS and Spring Security. How to handle AngularJS Urls with Spring Security

Let me explain my problem.
I have implemented a site in AngularJS that is accessed like this:
http://localhost:8080/example/resources/#/
Here we can call different pages, for example a Login page:
http://localhost:8080/example/resources/#/login
admin page:
http://localhost:8080/example/resources/#/admin
user page:
http://localhost:8080/example/resources/#/user
Now, I have implemented spring security in the example in order to catch every call and check if it has ROLE_USER privileges. So far so good, I have done it like this configuration in Spring security context file:
<security:http create-session="stateless" entry-point-ref="restAuthenticationEntryPoint"
authentication-manager-ref="authenticationManager">
<security:custom-filter ref="customRestFilter" position="BASIC_AUTH_FILTER" />
<security:intercept-url pattern="/**" access="ROLE_USER" />
</security:http>
This configuration checks for every url called, if the user has the proper ROLES, and it works fine, throws 401 Unauthorized page.
The problem I`m having is that when I put the login page to be accessed by everybody I'll do it this way:
<security:http create-session="stateless" entry-point-ref="restAuthenticationEntryPoint"
authentication-manager-ref="authenticationManager">
<security:custom-filter ref="customRestFilter" position="BASIC_AUTH_FILTER" />
<security:intercept-url pattern="/login**" access="ROLE_ANONYMOUS" />
<security:intercept-url pattern="/**" access="ROLE_USER" />
</security:http>
But I dont know why spring security is not catching this URL. Maybe Angular manages the URL differently.
Finally i have tried deleting the <security:intercept-url pattern="/**" access="ROLE_USER" /> and giving /login** access to ROLE_USER only, but this page was not found. Does anybody know what could be happening here?
Thanks in advance!!!
I wrote a little sample application that illustrates how to integrate AngularJS with Spring Security by exposing the session id as an HTTP header (x-auth-token). The sample also provides some (simple) authorization (returning the roles from the server) so that the client AngularJS application can react to that. This is of course primarily for user-experience (UX) purposes. Always make sure your REST endpoints have property security.
My blog post on this is here.

Why is my Spring PreAuthFilter always called?

I have my Spring 3.1 app configured like this
<http use-expressions="true" entry-point-ref="http401UnauthorizedEntryPoint">
<intercept-url pattern="/app/demo" access="hasRole('Demo')" />
<intercept-url pattern="/app/**" access="isAuthenticated()" />
<intercept-url pattern="/admin/**" access="hasRole('Admin')" />
<custom-filter position="PRE_AUTH_FILTER"
ref="currentWindowsIdentityAuthenticationFilter" />
<logout invalidate-session="true" delete-cookies="JSESSIONID"
logout-url="/logout" logout-success-url="/logout-success" />
</http>
I have written a custom preauth filter. When I call my app at the root URL / the filter chain hooks in and runs the preauth filter although this resouce is not protected. This means that the logout does not work as designed. After a logout a login is performed again.
My implementation is based on the org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter class.
Is this normal behavior or can this be fixed some how? I'd like the auth be performed on the protected URLs only.
As I side note, I do not intend to configure security='none' because I want to maintain the security context on all pages.
I have posted the appropriate log out on pastebin. It is too verbose to include in here.
Seems that what you want is creating special <http> without any filters for logout URL:
<http pattern="/logout/**" security="none" />
<http use-expressions="true" entry-point-ref="http401UnauthorizedEntryPoint">
<intercept-url pattern="/app/demo" access="hasRole('Demo')" />
<intercept-url pattern="/app/**" access="isAuthenticated()" />
<intercept-url pattern="/admin/**" access="hasRole('Admin')" />
<custom-filter position="PRE_AUTH_FILTER"
ref="currentWindowsIdentityAuthenticationFilter" />
<logout invalidate-session="true" delete-cookies="JSESSIONID"
logout-url="/logout" logout-success-url="/logout-success" />
</http>
Read more about request matching mechanism here.
EDIT:
#LukeTaylor mentioned that if you want to create another filter chain then the pattern should go in the element (is this documented somewhere explicitely?), so my idea with separate chain without PRE_AUTH_FILTER obviously won't work. Added <http> for /logout without any filters, which should prevent authorizing at logout requestes.
Still, I don't know how prevent requests like /other from applying PRE_AUTH_FILTER. One way could probably be abandon <http> namespace configuration to manual filterChainProxy configuration with two <sec:filter-chain> patterns, but I don't know if it's worth it.
#Michael-O: About exception IllegalArgumentException: A universal match pattern ('/**') is defined before other patterns - it's strange, is it your whole XML config for Security? Or maybe it's just a consequence of what Luke said (that another <http> element should have pattern)...
I was able to indentify the issue but it cannot be solved the way it is now because of the way the entire chain works.
Here's the deal:
When you define a <http> element on /** you ask Spring Security to fire the entire filter chain on all paths under your defined pattern. It does not matter whether one of them needs protection or not. Rob Winch published a very helpful video. If you take a closer look at the default filter stack you'll what filters are applied. Amidst these is my filter located.
The first ten lines of my log file reveal that the entire chain is fired since / matches the <http> configuration. At the end, the FilterSecurityInterceptor sees that this resource does not need protection. More over, you see that the CurrentWindowsIdentityAuthenticationFilter is fired too and performs unwanted authentication.
Why? Compared to header-based filters or URL processing filters you have no trigger/entry point to commence the authentication deliberately you simply do without challenging the client regardless the URL needs protection or not. Defining something like this <http pattern="/unprotected-url" security="none" /> saves you absolutely nothing because you lose the security context on unprotected paths. You want to keep your client logged in regardless of the URL protection.
How can this be solved now? You have two options:
Define a <http> element on /app/**, /admin/** so on but this is really cumbersome and contains repitions all over. I would not recommend such a solution. Additionally, you probably won't have the sec context on other URLs in /**. This is not desired.
Split the preauth filter in two filters:
CurrentWindowsIdentityPreAuthenticationFilter
CurrentWindowsIdentityUrlAuthenticationFilter
The second option solves the problem.
CurrentWindowsIdentityPreAuthenticationFilter: Remains as-is and peforms the auth always. Very helpful for M2M communication like script access or REST requests.
CurrentWindowsIdentityUrlAuthenticationFilter: Suits human interaction very well. It works basically like a form-based filter. If define a URL, say /login, you will get redirected to when you request a protected resource and after successful auto-auth you be redirected back to your actual resource. Auth is done. Public resources remain unauthenticated because the preauth filter is trigged on /login only just like form-based. If you log out you stay logged out.
I'd be happy if any of the Spring folks can confirm my analysis.

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.

Spring Security: Redirect to invalid-session-url instead of logout-success-url on successful logout

I have implemented a login-logout system with Spring Security 3.0.2, everything is fine but for this one thing: after I added a session-management tag with invalid-session-url attribute, on logout Spring would always redirect me on the invalid-session-url instead of the logout-success-url (which it correctly did before).
Is there a way to avoid this behaviour?
This is my configuration:
<http use-expressions="true" auto-config="true">
[...some intercept-url's...]
<form-login login-page="/login" authentication-failure-url="/login?error=true"
login-processing-url="/login-submit" default-target-url="/home"
always-use-default-target="true" />
<logout logout-success-url="/home?logout=true" logout-url="/login-logout" />
<session-management invalid-session-url="/home?invalid=true" />
</http>
Thanks a lot.
By default, the logout process will first invalidate the session, hence triggering the session management to redirect to the invalid session page. By specifying invalidate-session="false" will fix this behavior.
<sec:logout logout-success-url="/logout" invalidate-session="false"
delete-cookies="JSESSIONID" />
Do not confuse the logout-url attribute in the logout tag with the invalid-session-url attribute from session-management.
The latter is the URL to execute the action of logging out while the former is the URL being forwarded to upon a logout action.
To put it in other words, when creating a logout button, the URL for that button would be the logout-url value.
Now when the logout is done, spring security, be default, will render the main application's root app path, i.e.: http://yourserver:yourport/yourwebapp/. This path is overridden by invalid-session-url. So upon logout, you will be forwarded there.
To sum up, if you don't want the behavior you're asking for, then do not use invalid-session-url attribute.
Hope that helps.

Resources