11 Replies Latest reply on Mar 19, 2009 8:32 PM by nimo stephan

    authenticator and loginSuccessfull-Observer

    nimo stephan Master

      I have successfully registered an authenticator method:


      public class MyLogin{
      
      public boolean auth() {
      
      
      ...
      if (Events.exists())
      Events.instance().raiseEvent(Identity.EVENT_LOGIN_SUCCESSFUL, user);
      
      return true;
      
      }



      @Observer(Identity.EVENT_LOGIN_SUCCESSFUL)
      public void loginSuccessfull(Users user, Mailroom mailroom)
           {
      ..
      
      }
      
      }



      But now, when I log in, the Observer is called such as the Auth-Method more than once!
      How can I force, that the Observer is only called once, after the login was successfully?


      According to the seam-manual:



      When writing an authenticator method, it is important that it is kept minimal and free
      from any side-effects. This is because there is no guarantee as to how many times
      the authenticator method will be called by the security API, and as such it may be
      invoked multiple times during a single request. Because of this, any special code
      that should execute upon a successful or failed authentication should be written
      by implementing an event observer.


      What should I do?


        • 1. Re: authenticator and loginSuccessfull-Observer
          nimo stephan Master

          Okay found a solution:


          My Link


          Does anyone knows a solution without overriding the Identity-Class???

          • 2. Re: authenticator and loginSuccessfull-Observer
            nimo stephan Master

            I tried it according to


            My Link


            with:



            <event type="org.jboss.seam.security.loginSuccessful">
                <action execute="#{myLogin.loginSuccessfull}"/> 
            </event>



            and delete the Annotation Observer. However, the action loginSuccessfully is called more than once. The same problem.

            • 3. Re: authenticator and loginSuccessfull-Observer
              Nikolay Elenkov Master

              nimo mayr wrote on Mar 19, 2009 13:22:


              Does anyone knows a solution without overriding the Identity-Class???


              If all you need is the standard loginSuccessful event, you don't have to raise it in your authenticator
              component. Seam's default Identity component raises one on successful login. That's why you get two events: one from your authenticator, one from Identity.


              If you really need to pass User as the event parameter, simply choose a different event name, say myLoginSuccessfull.


              HTH

              • 4. Re: authenticator and loginSuccessfull-Observer
                Nikolay Elenkov Master

                Nikolay Elenkov wrote on Mar 19, 2009 14:46:


                If you really need to pass User as the event parameter, simply choose a different event name, say myLoginSuccessfull.



                But than you will have to override Identity... If you can't/don't want to, the easiest way would probably be
                to simply lookup User based on the current Identity's username. (at the expense of one more database hit)


                Something like:


                @In Credentials credentials
                
                @Observer("loginSuccessful")
                void onLoginSuccess() {
                  User user = userDao.findUser(credentials.getUsername())
                  // do whatever w/ user
                }





                • 5. Re: authenticator and loginSuccessfull-Observer
                  nimo stephan Master

                  public class MyLogin{
                  
                  // I use < Seam 2.1
                  @In(create=true) private Identity identity;
                  
                  public boolean auth() {
                  
                  // comment out
                  // Events.instance().raiseEvent(Identity.EVENT_LOGIN_SUCCESSFUL, user);
                  
                  return true;
                  
                  }
                  
                  @Observer(Identity.EVENT_LOGIN_SUCCESSFUL)
                  public void okay()
                  {
                  
                  ..
                  
                  }



                  The above Code does not init the okay-Method after login was successfully!

                  • 6. Re: authenticator and loginSuccessfull-Observer
                    Nikolay Elenkov Master

                    nimo mayr wrote on Mar 19, 2009 15:30:



                    public class MyLogin{
                    
                    // I use < Seam 2.1
                    @In(create=true) private Identity identity;
                    
                    public boolean auth() {
                    
                    // comment out
                    // Events.instance().raiseEvent(Identity.EVENT_LOGIN_SUCCESSFUL, user);
                    
                    return true;
                    
                    }
                    
                    @Observer(Identity.EVENT_LOGIN_SUCCESSFUL)
                    public void okay()
                    {
                    
                    ..
                    
                    }



                    The above Code does not init the okay-Method after login was successfully!



                    Try moving your okay method to a different component. And, you don't want to create Identity, it lives in
                    session scope and should be available.


                    • 7. Re: authenticator and loginSuccessfull-Observer
                      nimo stephan Master

                      I do Identity.instance... instead of


                      @In (create=true).




                      I upgraded to 2.1 and use Credentials.


                      But the Observer is not called..even the authenticator-method returns true!

                      • 8. Re: authenticator and loginSuccessfull-Observer
                        Nikolay Elenkov Master


                        But the Observer is not called..even the authenticator-method returns true!


                        Is your auth method called when you call #{identity.login} from your view? If you are really just returning true, Credentials or Identity doesn't matter really.


                        Post full code if possible and maybe check your configuration once again.


                        • 9. Re: authenticator and loginSuccessfull-Observer
                          nimo stephan Master

                          This case occurs after upgrading from SEAM 2.1.0 to SEAM 2.1.1:


                          In Seam 2.1.0, the authenticater works, but in 2.1.1 not:


                          my components.xml:


                          <security:identity authenticate-method="#{auther.authMe}"/>




                          My Auth-Method (for this scenario returns always true):




                          @Name("auther")
                          @Scope(SESSION)
                          public class Authenticate implements Serializable{
                          
                          private static final long serialVersionUID = -1929754859579432197L;
                          
                          @In Credentials credentials;
                               
                          @Logger private Log log;
                          
                          public boolean authMe() {
                          
                          log.info("credentials.getUsername() #0", credentials.getUsername());
                          log.info("credentials.getPassword() #0", credentials.getPassword());
                          
                          return true;
                                    
                          
                              }
                          
                          @Observer(Identity.EVENT_LOGIN_FAILED)
                          public void loginFailed()
                          {
                          log.info("login Failed : #0", credentials.getUsername());
                          
                          }
                          
                          @Observer(Identity.EVENT_LOGIN_SUCCESSFUL)
                          public void loginSuccessfully()
                          {
                          log.info("login Successfully : #0", credentials.getUsername());
                          }
                               
                          }
                          
                          
                          
                          



                          My View:



                          <h:form>
                          <h:outputLabel value="username" />
                          <h:inputText value="#{credentials.username}"/>
                          <h:outputLabel value="password" />
                          <h:inputSecret value="#{credentials.password}" redisplay="false"/>
                          
                          <h:commandButton value="login"  action="#{auther.authMe}"/>
                          </h:form>




                          When filling the form and clicking the button, the logger says me:


                          19:34:24,812 INFO  [STDOUT] BeforePhase: RESTORE_VIEW 1
                          19:34:24,843 INFO  [STDOUT] AfterPhase: RESTORE_VIEW 1
                          19:34:24,843 INFO  [STDOUT] BeforePhase: APPLY_REQUEST_VALUES 2
                          19:34:24,843 INFO  [STDOUT] AfterPhase: APPLY_REQUEST_VALUES 2
                          19:34:24,843 INFO  [STDOUT] BeforePhase: PROCESS_VALIDATIONS 3
                          19:34:24,843 INFO  [STDOUT] AfterPhase: PROCESS_VALIDATIONS 3
                          19:34:24,843 INFO  [STDOUT] BeforePhase: UPDATE_MODEL_VALUES 4
                          19:34:24,843 INFO  [STDOUT] AfterPhase: UPDATE_MODEL_VALUES 4
                          19:34:24,843 INFO  [STDOUT] BeforePhase: INVOKE_APPLICATION 5
                          19:34:24,843 INFO  [Authenticate] credentials.getUsername() testUser
                          19:34:24,843 INFO  [Authenticate] credentials.getPassword() testPassword
                          19:34:24,843 INFO  [STDOUT] AfterPhase: INVOKE_APPLICATION 5
                          19:34:24,843 INFO  [STDOUT] BeforePhase: RENDER_RESPONSE 6
                          19:34:24,875 INFO  [STDOUT] AfterPhase: RENDER_RESPONSE 6



                          But no other reaction occurs - no observer called, no login failed, no login succeed - even true returned. I have no clue what is behind the scene as no failure occurs in my logger.


                          • 10. Re: authenticator and loginSuccessfull-Observer
                            Nikolay Elenkov Master

                            nimo mayr wrote on Mar 19, 2009 19:37:


                            My View:

                            <h:commandButton value="login"  action="#{auther.authMe}"/>





                            You are not supposed to call your authMe method directly. You should call Identity.login and Seam takes care of calling your authentication method. That last bit should read:


                            <h:commandButton value="login" action="#{identity.login}" />
                            



                            Check out the dvdstore example to see how the whole thing is wired up.


                            • 11. Re: authenticator and loginSuccessfull-Observer
                              nimo stephan Master

                              gosh, I accidentally found exactly this failure and wanted to post it.


                              You are right:


                              #{identity.login}



                              was the solution.


                              thank you!