Announcement Announcement Module
Collapse
No announcement yet.
[Newbie] Post-authentication processing? Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • [Newbie] Post-authentication processing?

    Hi all,

    I just started to use Acegi recently and I am wondering what the best way to solve a problem would be.

    The context: A web app with Acegi setup similarly to what is described in the recent javalobby article.

    The problem: A populated Authentication object is put in the session by acegi if the authentication is sucessful. However, while Authentication contains some user-related information, I'd like to associate more model-related information to the session so that I can present more useful information. Since Acegi takes care of the redirect automatically after authentication, I am not given an opportunity to perform any such processing out of the box.

    My questions: Are there any hooks in Acegi that would allow me to, for example, add my own User object to the session after the authentication is performed but before the re-direction? It doesn't seem like using an AuthenticationEvent listener would work since it might not have access to the request.

    The problem that I describe seems to me a fairly common use case and I am wondering what the best practice is to solve that problem (short of implementing my own SecurityInterceptor).

    Hopefully this is clear enough...

    Thanks a lot in advance.
    Best,
    Chris

  • #2
    Re: [Newbie] Post-authentication processing?

    Originally posted by ubik
    for example, add my own User object to the session after the authentication is performed but before the re-direction?
    I think you'll find the Authentication already does that for you. If you use DaoAuthenticationProvider, your AuthenticationDao returns a UserDetails implementation. Typically people return the User concrete class or a subclass, which implements UserDetails. DaoAuthenticationProvider treats the UserDetails as the principal, popping it into the Authentication.principal property.

    This is how most people add extra user-related information, such as their real name, email address, phone number etc.

    DaoAuthenticationProvider itself also has a number of protected methods, designed for subclasses to override. So if the above doesn't answer your question, maybe take a look at those methods as well.

    Comment


    • #3
      Re: [Newbie] Post-authentication processing?

      Originally posted by Ben Alex
      I think you'll find the Authentication already does that for you. If you use DaoAuthenticationProvider, your AuthenticationDao returns a UserDetails implementation. Typically people return the User concrete class or a subclass, which implements UserDetails. DaoAuthenticationProvider treats the UserDetails as the principal, popping it into the Authentication.principal property.
      Thanks for the pointer. Stepping through the framework code pointed me to that direction as well after implementing a crappy solution involving a filter... A custom AuthenticationDao with a little Adapter magic later and I was done. Thank you very much for your help. It's really refreshing to see your level of involvement on the forum answering questions and helping newbies like myself.

      Comment


      • #4
        On further thought, while that solution works, it ties the code to the use of the Acegi framework since I then need to acess the application-specific information using code similar to below:
        Code:
        Authentication auth = (Authentication) request.getSession().getAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHORIZATION_KEY);
        MyUser user = (MyUser) auth.getPrincipal();

        Sure I could encapsulate that code into a method that gets called any time I need to access app-specific information to reduce the dependency but it still feels like jumping through hoops. Or am I missing something?

        Having a hook in AbstractProcessingFilter.doFilter would make things easier. Something like:

        Code:
        ...
        // Authentication success
        if (logger.isDebugEnabled()) {
          logger.debug("Authentication success: " + authResult.toString());
        }
        
        // ADDED CALLBACK
        postAuthenticationCallback.doPostAuthentication(httpRequest);
        
        httpRequest.getSession().setAttribute(HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY, authResult);
        ...
        This would be supported by a setter in AbstractProcessingFilter to be able to set the callback via Spring and PostAuthenticationCallback interface defining the doPostAuthentication method or something to the same effect.

        In my case, I would write a PostAuthenticationCallback that would retrieve the appropriate MyUser object and put it in the session with the appropriate key. I could then access that object in the rest of my code without having to make it depend on Acegi Security.

        Is it making any sense at all? Am I missing something really obvious?

        Comment


        • #5
          Originally posted by ubik
          In my case, I would write a PostAuthenticationCallback that would retrieve the appropriate MyUser object and put it in the session with the appropriate key. I could then access that object in the rest of my code without having to make it depend on Acegi Security.
          I think that would be more work than a simple utility class. Remember your UserDetails implementation can be any class you like, so it's really owned by your application itself (not Acegi Security). Then just have something like:

          Code:
          public class CurrentUser {
            public static MyUserObject getCurrentUser() {
               return (MyUserObject) ((SecureContext)ContextHolder.getContext()).getAuthentication().getPrincipal();
            }
          }
          You'd have to add some null detection in that line, but it's obviously less work than Acegi Security providing callback etc. It also avoids dependency on the HttpSession. What would happen if you decided you needed your user details from a services layer method, where your web layer objects like HttpSession should never be available? A static method that integrates with ContextHolder achieves that.

          Comment


          • #6
            Originally posted by Ben Alex
            It also avoids dependency on the HttpSession. What would happen if you decided you needed your user details from a services layer method, where your web layer objects like HttpSession should never be available? A static method that integrates with ContextHolder achieves that.
            Ah-ha! I was sure I was missing something. Since I had been stepping through the code, I only saw the path my app was using and was obviously missing the bigger picture.

            Thanks a lot for your patience in helping me see the light.

            Best,
            Chris

            Comment

            Working...
            X