I have an issue with the Session Timeout. In my grails application an user logs in after a session timeout, but then gets to the last edited page. I want to prevent that and send them to a specific URL. How can I achieve this, I cant find something in the spring security documentation.
Greetings.
Per the docs, it looks like you might be able to use a combination of:
successHandler.defaultTargetUrl="/whatever/url/you/want"
successHandler.alwaysUseDefault=true
By default spring security will forward the original request after successful login. You can prevent that by adding the following to Config.groovy:
grails.plugins.springsecurity.successHandler.alwaysUseDefault = true
grails.plugins.springsecurity.successHandler.alwaysUseDefaultTargetUrl = true
grails.plugins.springsecurity.successHandler.defaultTargetUrl = '/my/default/url'
The two properties sound like they should do the same, but in my case it only works when I have them both. Perhaps you can remove one of them and get it to work...
This will alter the behavior any time you log in, not just after a timeout. If you need a more dynamic solution, I guess you have to dig into the spring security source code...
Related
I am using GGTS and Grails 2.2.0 and have implemented spring security along with Basic Auth with the following options
Config.groovy
grails.plugins.springsecurity.useBasicAuth = true
grails.plugins.springsecurity.digest.realmName = 'someval'
LogoutController {
def index = {
redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl
}
When I click on logout – it does not log the user out, it takes me back to the home page. I have looked at the forums, but have not found anything that works.
I want to make sure that whatever solution is implemented, logs off the use completely and the user is not able to return back to the original page without logging back in.
Any pointers/suggestions are appreciated.
The problem is HTTP Basic Authentication. It doesn't specify a way to log out. I believe there are some "unofficial" methods that work (see How to log out user from web site using BASIC authentication?), but Spring Security doesn't appear to use them.
The best solution is to avoid Basic Auth altogether. If that's not an option, you'll have to write a custom LogoutController that e.g. sends back a 401 error code.
I'm working on a Grails application and want to integrate with a custom single-sign-on service (not CAS, but similar). I'm struggling to find all the pieces that I need to customize to make this happen. Can someone explain to me a general outline as to what I need to use to accomplish this? I've read the documentation on the plugin, but it assumes I know which beans to override and where to put all the needed files.
I've block-quoted what I think needs to be done based on my research below each point.
Order of Operations
1- The user requests secure content (everything is secure in the application for now)
I believe this setting is in the Config.groovy file:
grails.plugins.springsecurity.rejectIfNoRule = true
grails.plugins.springsecurity.securityConfigType = "InterceptUrlMap"
grails.plugins.springsecurity.interceptUrlMap = [
'/**':['ROLE_ADMIN']
]
2- Spring Security checks to see if the user has a specific value set in a cookie provided by the authentication service
I'm guessing I need to create an authentication filter, but I don't know where to put it or what it should look like.
If they don't, the user is redirected to this custom SSO service, they login, once authenticated, the user is redirected back to my application (with a new cookie set)
3- Spring security checks for the cookie value and validates it against the custom service (via HTTP POST)
From some research, I think that I need to use PreAuthenticatedProcessingFilter, but I haven't been able to find any examples of how to do this.
4- The custom service returns a series of name/value pairs, a user then needs to be created in the local application database (or the timestamp of "lastLoggedIn" is updated if they user's data is already in the database)
I believe this is done in the same PreAuthenticatedProcessingFilter as number 3 or in a GrailsUserDetailsService
5- The user's authentication is cached in the session for a period of time (6-8 hours) so that re-validation against the SSO service doesn't need to occur every time the user requests a new resource.
I'm not sure if this is something that's done inherently or if I need to add code to do this (and also set the session timeout)
Here is my issue: I don't want to use any of spring security core filter when a user is using the API (basically, all /myapi/** request), to avoid creating a useless session. The api is based on oauth token.
So, I'm using the plugin spring-security-core for the user authentication, and I added, in my Config.groovy file,
grails.plugins.springsecurity.filterChain.chainMap = [
'/myapi/**': 'JOINED_FILTERS,-securityContextPersistenceFilter,-logoutFilter,-authenticationProcessingFilter,-securityContextHolderAwareRequestFilter,-rememberMeAuthenticationFilter,-anonymousAuthenticationFilter,-exceptionTranslationFilter',
'/**':'JOINED_FILTERS'
]
Basically, from what I understood, it shouldn't go throught any spring security filter for all /myapi/something, but, actually, it goes throught all the filters as it creates a session (i don't have anything for session in /myapi/something.
But, according to http://grails-plugins.github.com/grails-spring-security-core/docs/manual/guide/16%20Filters.html
So you need a /** catch-all rule at the end for URLs that do not match one of the earlier rules.
And that's why I don't understand why the request are still going throught all the filters for any /myapi/something.
Some testing I did, which may help:
It is not creating a session if I only have, in my Config.groovy:
grails.plugins.springsecurity.filterChain.chainMap = [
'/myapi/**': 'JOINED_FILTERS,-securityContextPersistenceFilter,-logoutFilter,-authenticationProcessingFilter,-securityContextHolderAwareRequestFilter,-rememberMeAuthenticationFilter,-anonymousAuthenticationFilter,-exceptionTranslationFilter'
]
But it's also not creating a session for the other urls, not using any other filter, which causes the application not to work of course. This example was just to be sure that the session was not created by the /myapi/something request
If i just have:
grails.plugins.springsecurity.filterChain.chainMap = [
'/myapi/**': 'JOINED_FILTERS'
]
Then, it goes throught all the filters for all /myapi/something request and create a session. It doesn't use any filter for the other request. It is the excepted behavior.
Thanks a lot for your help, I have been fighting with that for some times now, and any ideas would be more than welcome!
Thanks a lot! Have a good day.
Yup, I'm suffering from the exact same problem! Although I don't use JOINED_FILTER, I set the filter explicitly like this:
grails.plugins.springsecurity.filterChain.chainMap = [
'/apitest/**': 'requestContextAttributesFilter,sessionPreventionFilter,objectRepositoryCreationFilter',
'/api/**': 'requestContextAttributesFilter,sessionPreventionFilter,objectRepositoryCreationFilter,apiAuthenticationFilter',
'/**': 'requestContextAttributesFilter,securityContextPersistenceFilter,aisAuthenticationProcessingFilter'
]
The last filter of the catch-all rule gets executed when I access the '/apitest/*' URL. I could not reproduce this issue when I created a simple Grails project with a few dummy filters, which only did a println, and a similar chain map. For the simple test project, the filters acted as expected. Since there doesn't seem to be a proper logging when which filter gets executed and why, it is quite difficult to pinpoint the problem. Very strange...
UPDATE:
I was able to reproduce this error using the Spring Security Core plugin version 1.2.7.2. However, this bug seems to be fixed with version 1.2.7.3!
See: http://jira.grails.org/secure/ReleaseNote.jspa?projectId=10229&version=13100
Using version 1.2.7.3 seems to solve this issue.
I'm using Spring Security 3.0.0 and persistent RememberMe. When the server restarts and a browser window is still open, we need to be able to continue using the application without having to login - if remember me is selected.
I'm getting a org.springframework.security.web.authentication.rememberme.CookieTheftException: Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack, when I try to continue to use the application after a server restart.
What I notice is that the processAutoLoginCookie method gets called twice. I'm not sure why. The behavior of the method itself seems to be correct, ie , update the token in the database and update the cookie in the client.
Any help on this would be appreciated.
Thank you.
I was getting the exact same issue! The processAutoLoginCookie was getting called twice in succession so that the first call was successful, but the second call fails because the cookie is updated by the first call.
My only solution was to subclass PersistentTokenBasedRememberMeServices and override the processAutoLoginCookie method. I had to copy the existing code for processAutoLoginCookie and comment out the throwing of the CookieTheftException.
Note: My solution will open up a security hole!
If you are happy to allow for Cookie Thefts to occur (my system is used internally and does not contain sensitive data) then this solution will work.
Alternatively, you could also subclass PersistentTokenBasedRememberMeServices and add a more robust solution that still checks for Cookie Theft Exceptions but allows the two successive calls to processAutoLoginCookie to be made.
How do I implement a "Remember Me" function in Grails so that the user can check it and he won't have to log in again for 2 weeks?
I'm using the jSecurity plugin and want to change the cookie's lifetime beyond the browser session.
JSecurity already supports RememberMe functionality. Take a look at the AuthorizationController, you'll find that it supports parameter "rememberMe."
To implement a two-week time-out, I'd add another cookie and modify AuthorizationController to behave accordingly. There may be that functionality in JSecurity, not sure about that - doesn't seem the controller respects it.
Spring security (formerly acegi security) has this built-in, if you can use that plugin.
otherwise, the other posted solutions work nicely.