1 Reply Latest reply on Jun 25, 2009 2:37 PM by Shervin Asgari

    Authentication method only fires once

    Shervin Asgari Master

      I have modified the seam login to identify a user and retrieve its email and send a one-time generated password which needs to be correctly entered before I correctly login the user.


      This works fine. The only problem is that if the user enters the wrong one-time password and tries again, then the authenticator method isnt executed anymore. Why, I don't know.


      So my login.xhtml contains a username/password field which the user enters.
      That executes a action class that checks the username/password and sends an email.


      Then I render this div:



      <s:div rendered="#{oneTimePasswordIsSent}">
           <h:messages showSummary="true" showDetail="true" globalOnly="true" />
           <h:form>
                <h:outputLabel for='onepw'>Onetimepassword</h:outputLabel><h:inputText id="onepw" value="#{myOnetimepw}"/>
                <br/>
                                         
                <h:commandButton id="loginBtn" styleClass="actionButton" value="Login" action="#{identity.login}" title="Login" />
                <s:button styleClass="actionButton" value="Retry" action="#{loggInn.relogin}" title="Retry"/>
           </h:form>
      
      </s:div>



      My authenticator class:




      @Name("authenticator")
      public class Authenticator {
           @Logger
           private Log log;
      
           @In
           private Identity identity;
      
           @In
           private Credentials credentials;
      
           @In(scope=ScopeType.SESSION)
           private Long timeoutTimer;
           
           @In(scope=ScopeType.SESSION)
           private Boolean oneTimePasswordIsSent;
      
           @In(value="theActualOnetimePassword", scope = ScopeType.SESSION)
           private String otherOnetimepw;
           
           @Out(required = false)
           @In(required = false)
           private String myOnetimepw;
           
           @In(create = true)
           private ProcessUser currentUser;
      
           /***
            * Authenticates the user according to the username, password, one-time password and
            * organization.
            * 
            * @return
            */
           public boolean authenticate() {
                try {
                     if(!oneTimePasswordIsSent)
                          throw new NullPointerException("Onetime password is not sent");
                     
                     if (currentUser.getId() == 0L)
                          throw new NullPointerException("Didnt find any user");
      
                     credentials.setUsername(currentUser.getUsername());
                     credentials.setPassword(currentUser.getPasswordHash());
                     
                     //Find out if the one hour has passed
                     final long now = System.currentTimeMillis();
                     final long timer = timeoutTimer.longValue();
                     if(timer == 0L)
                          throw new NullPointerException("Error, couldnt get timeoutTimer");
                     
                     final long actualTime = timer - now;
                     if(actualTime / 1000 > 3600) {
                          throw new Exception("1 hour passed since onetime pass is sent, relogin please");
                     }
                     
                     if(!MyString.empty(myOnetimepw) && !myOnetimepw.trim().equals(otherOnetimepw)) {
                          throw new Exception("Onetime passwords didn't match");
                     }
      
                     final Set<Role> roles = currentUser.getRoles();
                     for (Role role : roles) {
                          identity.addRole(role.getName());
                     }
      
                     Events.instance().raiseEvent("Authenticator.authenticated", currentUser, true);
                     return true;
                } catch (NoResultException ex) {
                     //logFailedAttempt();
                     log.error(ex);
                     return false;
                } catch (Exception ot) {
                     //logFailedAttempt();
                     log.error(ot);
                     return false;
                }
           }
           
           /*
            * If the user is valid then log failed login attempts
            */
           private void logFailedAttempt() {
                if(currentUser.getId() != 0L) {
                     Events.instance().raiseAsynchronousEvent("loginFailed", credentials.getUsername(), currentUser.getOrganization() != null ? currentUser.getOrganization().getName() : "");
                }
           }
      }
      



      The authenticator method is executed the first time, but if wrong password is entered and it returns false, It is never executed again.
      Does anyone spot the problem?