Skip to content


Configuring different target URLs after login according to user roles (grails spring security)

I was working on some requirement regarding redirecting users to different URLs upon login according to their assigned roles, and was not quite sure how to achieve this in grails (well more specifically with spring security since I am using the spring security core plugin for grails).

Looking through the mailing list, I was able to find this, which had some good information, but did not quite answer the question. After a short chat with Alan (OP) I began my quest to figure out how to do this.

The Basics

One of the great things about the security plugin for grails, is that it gives you lots of functionality out of the box, that most of the time you don’t really need to do more than config changes. It also offers really good documentation on how to do more complex things; but once you hit that point of doing things that are not just configuration changes, it is a good idea to understand how spring security works; and that is what I set out to do.

After reading up some docs and guides on spring security, I got a basic idea of how things are wired, and the basic units that are at hand. For this specific issue, I found this section of the docs very helpful. So from what I gathered after reading the docs and looking at the source code (which was very helpful in putting things together); the idea here is that after an AuthenticationManager has processed the supplied login information, our authentication filter (which is the RequestHolderAuthenticationFilter that the plugin supplies) will delegate the processing to an AuthenticationSuccessHandler or AuthenticationFailureHandler depending on whether the login succeeds or fails.

So, given the above, I implemented my own AuthenticationSuccessHandler to handle redirecting users according to their roles.

 

The Implementation

The plugin already implements its own success handler (namely AjaxAwareAuthenticationSuccessHandler), but I did not really need any of the ajax support, so I went ahead and extended SavedRequestAwareAuthenticationSuccessHandler which is what the plugin extends for the ajax success handler as well. In my implementation below, I don’t really take advantage of what is implemented in that parent class (unless the user role is not in my checks), but just in case I need it, it will be there (the sort of things that the SavedRequestAwareAuthenticationSuccessHandler provides are things that you could configure like the default target url, and whether to always use the default url or make use of the saved request, etc…)

In any case, the code below shows a snapshot of the implementation. The trick is to override the determineTargetUrl method and return a String with the target url you want to send your users to. The rest will be taken care of by the SavedRequestAwareAuthenticationSuccessHandler.
I have put some logic to redirect an admin to a different page from a regular user; and for other roles, I just re-use whatever is defined in the parent class, but feel free to add whatever crazy logic you want here. (I will be passing the admin/user specific urls when defining the bean later on)

package com.omarello.authsuccess;

import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyAuthSuccessHandler 
       extends SavedRequestAwareAuthenticationSuccessHandler {
	
	@Override
	protected String determineTargetUrl(HttpServletRequest request,
                                            HttpServletResponse response) {
		
		boolean hasAdmin = SpringSecurityUtils.ifAllGranted("ROLE_ADMIN");
		boolean hasUser = SpringSecurityUtils.ifAllGranted("ROLE_USER");
		
		if(hasAdmin){
			return adminUrl;
		}else if (hasUser){
			return userUrl;
		}else{
			return super.determineTargetUrl(request, response);
		}
	}

	private String userUrl;
	private String adminUrl;
	
	public void setUserUrl(String userUrl){
		this.userUrl = userUrl;
	}
	
	public void setAdminUrl(String adminUrl){
		this.adminUrl = adminUrl;
	}
}

 

Wiring things

Now, for our shiny success handler to work, we need to wire it to be the one responsible for handling all successful logins instead of the default AjaxAwareAuthenticationSuccessHandler. To do this, we need to edit resources.groovy in our spring config, and assign the authenticationSuccessHandler bean to use our new success handler.

import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils

beans = {
	
	authenticationSuccessHandler(com.omarello.authsuccess.MyAuthSuccessHandler) {
		def conf = SpringSecurityUtils.securityConfig		
		requestCache = ref('requestCache')
		defaultTargetUrl = conf.successHandler.defaultTargetUrl
		alwaysUseDefaultTargetUrl = conf.successHandler.alwaysUseDefault
		targetUrlParameter = conf.successHandler.targetUrlParameter
		useReferer = conf.successHandler.useReferer
		redirectStrategy = ref('redirectStrategy')
		adminUrl = "/admin/index"
		userUrl = "/user/profile"
	}
}

Again, looking through the grails spring security plugin source code came in handy here. I used similar configurations adding the adminUrl and userUrl along with the other properties. (it is probably a good idea to move those URLs to the config as well, but you get the idea)

 
Once you have done this, then you should be good to go.
I am not sure if there is another way to do this, maybe implementing your own filter and bypassing all the authentication success and failure handlers is another option. But I think this way you will be able to support any filter you’ve got configured. If anyone has a better way to do this I’d love to hear it :)

Posted in Programming.

Tagged with , .


33 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. Jerome says

    Excellent, just what I was looking for.

  2. aldrin says

    Thanks for this. :D

  3. Alan says

    great article, simplifies something which is tricky to discover.

  4. Ryan says

    This is exactly what I needed! Unfortunately when I implemented your code it didn’t seem to have any effect. I threw some breakpoints and print statements into your code and it looks like it isn’t ever being executed. I’m not very familiar with spring and wiring up beans. Is there anything else that needs to be done to make this work? Maybe in the config.groovy file?

    I stuck the MyAuthSuccessHandler class in my src/java directory. I assume this is ok? I’m using Grails 2.0 and spring-security-core 1.2.6

    • Carl says

      Ryan, did you ever get an answer to this? I’m having the exact same problem, the code never seems to get executed.

  5. oswaldl says

    why i can not do some save action here, it seems no session has been found in MyAuthSuccessHandler

  6. Sagar says

    This is great! I was doing crytpic logic post login to achieve this but this is so much more elegant and maintainable :)

  7. mlip says

    In my configuration determineTargetUrl() is never called. I don’t know exacly why. But one can ovveride onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) and there set url with setDefaultTargetUrl(adminUrl) before calling super.

    • Carl says

      Hi mlip, can you clarify exactly what you implemented in your MyAuthSuccesHandler? If you could share the code that would really help.

  8. Amit says

    In my application determineTargetUrl() is never called. Can any body let me know what I am doing wrong ?.

  9. Florent says

    Thanks a lot, exactly what I was looking for. It works perfect in my app.

  10. Pietro says

    Excellent, clean and well done

  11. unixssh says

    Thanks for this. Very well done.

  12. Damien says

    I really understand why post. I’ve been looking everywhere for this reason!
    Thank heavens I uncovered it on Bing. You’ve got made my day! Thanks again

  13. skin disorder with pictures says

    Paragraph writing is also a fun, if you be acquainted with then
    you can write or else it is difficult to write.

  14. parental control software internet timer says

    Hi, after reading this remarkable piece of writing i am
    as well cheerful to share my experience here with mates.

  15. Vada says

    There’s certainly a great deal to find out about this topic. I love all the points you made.

  16. ear ringing news august 2012 says

    I got this web page from my friend who informed me regarding this website and now this time I am visiting this web page and reading very informative
    content at this place.

  17. energy supplements for thyroid says

    Good post however , I was wanting to know if you could write a litte
    more on this topic? I’d be very thankful if you could elaborate a little bit further. Kudos!

  18. Roosevelt says

    The write-up has proven useful to us. It’s extremely
    educational and you’re simply clearly very experienced of this type. You possess opened up my personal sight in order to varying thoughts about this specific matter with intriguing and sound content.

  19. second mri online opinion says

    Admiring the persistence you put into your blog and in depth information you present.
    It’s nice to come across a blog every once in a while that isn’t the same old rehashed material.
    Wonderful read! I’ve saved your site and I’m including your RSS feeds to my Google account.

  20. business in home says

    Hi, I do believe this is an excellent website. I stumbledupon it ;) I may return
    once again since I book marked it. Money and freedom is the greatest way to change, may you be rich and continue to guide other people.

  21. interior designer says

    Excellent solutions from you, man. We’ve realize your stuff before and you happen to be just too excellent.

  22. wallpaper designs for bathrooms says

    Great post. I was checking continuously
    this weblog and We are impressed! Very helpful information particularly the remaining part :
    ) I maintain such info much. I had been trying to
    find this certain info to the number of years. Thanks a lot and all
    the best.

  23. abdominal pannus lymphedema says

    I really like looking through an article that
    can make men and women think. Also, many thanks for allowing for me to
    comment!

  24. Anthony says

    I’m keen this blog a whole lot quite a lot good info.

  25. Connected.zz.Mu says

    For one thing thank you for writing this. Additionally
    there is an issue with your new stylesheet or maybe it’s just my netbook but it doesn’t display right.

  26. mif.or.jp says

    I’d constantly have to be update on new websites in this particular site, saved to favorites! .

  27. ministerstwo finansów pit says

    That is really attention-grabbing, You are an excessively skilled blogger.
    I have joined your rss feed and sit up for seeking extra of
    your fantastic post. Also, I have shared your web site in
    my social networks.

  28. male extender says

    Hmm it appears like your website ate my first comment
    (it was extremely long) so I guess I’ll just sum it up what I submitted and say, I’m thoroughly enjoying your blog.

    I as well am an aspiring blog blogger but I’m still new to everything. Do you have any recommendations for novice blog writers? I’d genuinely appreciate it.

Continuing the Discussion

  1. » Blog Archive linked to this post on September 26, 2011

    [...] Configuring different target URLs after login according to user roles (grails spring security) [...]

  2. An Army of Solipsists » Blog Archive » This Week in Grails (2011-38) linked to this post on September 26, 2011

    [...] Configuring different target URLs after login according to user roles (grails spring security) [...]

  3. Leverage Spring Security to Handle Mobile Access to Your Grails App | Object Partners Inc linked to this post on March 28, 2012

    [...] the UserDetails piece, but the problem was which step.  After a bit of work with Google, I found this site.  His approach was almost dead on to what I wanted to do with handling the landing page [...]



Some HTML is OK

or, reply to this post via trackback.