0 Replies Latest reply on Mar 16, 2010 4:52 AM by Filip Schlosser

    LoginCommand v checked exceptions

    Filip Schlosser

      Hi,

       

      I am implementing a custom authentication/authorization mechanism for my app using Flex / BlazeDS / Java and I ran into a quite anoying issue.

       

      - The user enters a username / password combination and clicks "login" ....

       

       

      <s:Button
           width="24%"
           label="Login"
           id="btnLogin"
           click="loginDomainModel.AttemptLogIn( txtUsername.text, txtPassword.text )"
           />
      

       

       

       

      public function AttemptLogIn( username : String, password : String ) : void 
           {
                this.username = username;
                _token = _cs.login( username, password );
                _token.addResponder( new AsyncResponder( LoginResultEvent, LoginFaultEvent, _token ) );     
           }
      

       

       

       

      Now, on the server side (Java) the "doAuthentication(String username, Object credentials)" method on my CustomLoginCommand class is being called. The LoginCommand returns a Principal object (containing username, roles, etc,..) on successfull authentication and returns null in case of a failure.

       

      My Java code contains an exception handling mechanism that throws custom exceptions in various parts of the call stack if something goes wrong with user authentication. For example if no user record is found in the DB for the given username a "NoSuchUserException" will be thrown or if the passwords don't match an "InvalidPasswordException" is being generated, etc...(all these extend AuthenticationException) On any failure (exceptions flying around, in this case), a FaultEvent is returned to the client.

       

      The Flex FaultEvent has a property "message" which in turns holds a property "rootCause". This "rootCause" property is supposed to hold the exception object that has been thrown by the Java class so that you can use any information included in the exception and take an appropriate action on the client side.

       

      All my Java exceptions propagate up the call stack untill they reach LoginCommand.doAuthentication. Since CustomLoginCommand implements the LoginCommand interface I cannot alter the method signature of "doAuthentication" to accomodate a throws XYZException clause.

       

       

      @Override
      public PocPrincipal doAuthentication(String username, Object credentials) {
           try {
              Boolean authenticated = false;
           authenticated = authenticationService.tryAuthentication(presentedUsername, presentedPassword);
           return new PocPrincipal(username, authenticationService.getUser().getRole());
           } catch (AuthenticationException e) {
                //what do we do here? Make e an unchecked RuntimeException?
           }
      }
      

       

       

      So since I cannot rethrow my caught exception it looks like I cannot pass any information about what caused the server side failure to the client.

      A, not so satisfying, workaround is to throw a new RuntimeException from within "doAuthentication". For this I don't need to alter the method signature since runtimexceptions are unchecked. This way at least some information will be visible in the "faultString" property of the faultEvent, but not in the "rootCause" property (where we want it to be).

       

      Another way to solve this is to just return a Principal = null and handle the resulting FaultEvent in a faultHandler on the client and then display a message saying "Login failed. Username or password is wrong", or something similar.... The thing is; we want to specify to the user what exactly happened; is the username wrong OR the password? For that I need to send accross the right exception with its embedded message.....

       

      So, all this boils down to the folowing question; is there a way to place server side unchecked exceptions as a rootCause element in a faultEvent? Or is there a much better way to deal with this scenario?

       

      This looks like a dead end street at this point but I am pretty sure there is a workaround....

       

      Regards,

       

      FS