6 Replies Latest reply on Jul 4, 2007 3:11 AM by rapowder

    Securing components

    rapowder

      Hi I am trying to add user management to my seam application (v. 1.2.1GA) and I'm getting some problems when assigning specific method access to different roles. Precisely, when I call

      Identity.instance().hasRole("admin")
      I get false although I setted the correct user role at login. Here is my Login class:

      @Stateless
      @Name("login")
      public class LoginAction implements Login {
      
       @In @Out
       private User user;
      
       @In(create = true, value = "spotme2EM")
       private EntityManager em;
      
      [...]
      
       public String login() {
      
       User userReference = find(user.getName(), user.getPassword());
      
       if(userReference != null) {
      
       Identity id = Identity.instance();
       id.setUsername(userReference.getName());
       id.setPassword(userReference.getPassword());
       id.addRole(userReference.getRole().name());
       try {
       id.authenticate();
       } catch (LoginException e) {
       e.printStackTrace();
       }
      
       sessionContext.set("loggedIn", true);
      
       return "home";
       }
       else {
       log.info("Invalid Login!");
       facesContext.addMessage(null, new FacesMessage("Invalid login"));
       return null;
       }
      
      


      In another bean, I do the check like this:

      public String delete() {
       public String deleteItem() {
      
       if (!Identity.instance().hasRole(CoreConstants.UserRole.ADMIN.name()))
       throw new AuthorizationException("Must be admin to perform this action!");
      
       [...]
       }
      


      And of course the exception is always thrown... Any suggestions?

        • 1. Re: Securing components
          pmuir

          You need to use your debugger to step through and find out why the this is happening - check to see if the role was added, and if it is there when you check for it.

          • 2. Re: Securing components
            shane.bryzak

            You can't call Identity.addRole() there, it needs to be called in your authenticator method. Pre-authenticated roles are cleared before authentication is performed.

            • 3. Re: Securing components
              rapowder

              Ok I moved my addRole() method to the autenticate method:

              public boolean authenticate() {
              
               Identity id = Identity.instance();
               User userReference = getUserFromDB(id.getUsername(), id.getPassword());
              
               if(userReference == null) {
               return false;
               }
               else {
               log.info("Setting role: " + userReference.getRole().name());
               id.addRole(userReference.getRole().name());
               log.info("Set role " + CoreConstants.UserRole.ADMIN.name() + "? "
               + id.hasRole(CoreConstants.UserRole.ADMIN.name()));
               return true;
               }
               }


              As you can notice I added some debug messages before and after the addRole() method and I noticed that it has no effect, since the output is:

              02:32:37,756 INFO [LoginAction] Setting role: ADMIN
              02:32:37,757 INFO [LoginAction] Set role ADMIN? false


              Any suggestions?


              • 4. Re: Securing components
                rapowder

                Something else: if I call the method addRole() after id.authenticate() the role is actually added, but when I load the pages where I actually want to check if the user is ADMIN (see first post when i call delete()) the method still returns false.

                Some additional info: I declared the authenticator method in components.xml as follows:

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


                and pages.xml looks like follows:

                <pages login-view-id="/auth_login.xhtml">
                ...
                 <page view-id="/mypage.xhtml" no-conversation-view-id="/auth_login.xhtml" login-required="true">
                 ...
                 </page>
                ...
                </pages>
                


                I noticed that if I don't call the authenticate() method manually from the login page (see first post) it is never called and any page that I try to render redirects me to the login page. Shouldn't the authenticate method be called automatically?


                • 5. Re: Securing components
                  shane.bryzak

                  You shouldn't call your authenticate method directly, you need to call identity.login() and it will perform a JAAS login which in turn calls your authenticate method. Also, addRole() only adds a role to the list of pre-authenticated roles for the user. It doesn't become a "real" role until authentication is successful, which is why when you call hasRole() inside your authentication method, it returns false (authentication hasn't completed yet!).

                  • 6. Re: Securing components
                    rapowder

                    I solved the problem, actually in my login page I was correctly calling id.authenticate() and id.addRole() right after authentication, but inside the delete() method I was checking the role with a misspelled String (stupid me....).

                    Thank you anyway :)