7 Replies Latest reply on Nov 16, 2010 11:23 AM by babazs

    Specific error message for user when not authorized

    orr94

      I am using @Restrict to secure my component methods, like this:


      @Restrict("#{s:hasRole('mysystem.admin')}")


      @Restrict("#{s:hasRole('someothersystem.admin')}")


      And my pages.xml handles the corresponding AuthorizationException like this:




      <exception class="org.jboss.seam.security.AuthorizationException">
        <redirect view-id="/error.xhtml">
          <message severity="error">You don't have permission to access this resource</message>
        </redirect>
      </exception>





      The issue with this is that when a user attempt to access that method, the only message they get is You don't have permission to access this resource. It doesn't specify what role they are missing.


      Is there any way to provide more information to the end user about the authorization error?

        • 1. Re: Specific error message for user when not authorized
          babazs
          Just try this, It will help you:



          @Startup
          @Scope(ScopeType.APPLICATION)
          @BypassInterceptors
          @Install(precedence = Install.APPLICATION)
          @Name("org.jboss.seam.security.facesSecurityEvents")
          public class CustomFacesSecurityEvents extends FacesSecurityEvents {

               @Observer(Identity.EVENT_NOT_AUTHORIZED)
               public void notAuthorized(Identity identity) {
                          if(role1)
                    StatusMessages.instance().addFromResourceBundleOrDefault(Severity.ERROR, "msg.role1","");
                          else     
                    StatusMessages.instance().addFromResourceBundleOrDefault(Severity.ERROR, "msg.role1","");
               }


          • 2. Re: Specific error message for user when not authorized
            orr94

            Thanks, that's what I was looking for!


            One question, though: from this observer, how do I determine the role/expression that was being checked? In your example, you refer to a variable role1, but that isn't defined in your example. Without knowing any details of what caused the EVENTNOTAUTHORIZED event, I don't know what message to add to StatusMessages.

            • 3. Re: Specific error message for user when not authorized
              babazs

              Hy!


              You can determine the role with Identity.instance().hasRole(mysystem.admin) or Identity.instance().hasRole(someothersystem.admin).

              • 4. Re: Specific error message for user when not authorized
                orr94

                Maybe I'm missing something. In this code example that you gave:




                @Observer(Identity.EVENT_NOT_AUTHORIZED)
                 public void notAuthorized(Identity identity) {
                                if(role1)
                  StatusMessages.instance().addFromResourceBundleOrDefault(Severity.ERROR, "msg.role1","");
                                else     
                  StatusMessages.instance().addFromResourceBundleOrDefault(Severity.ERROR, "msg.role1","");
                 }





                This code is called when an AuthorizationException is thrown from a @Restrict annotation. In your code, it looks like you add a message based on which missing role caused the exception. However, I don't know what role was missing that caused the exception; thus, I don't know what error message to add.

                • 5. Re: Specific error message for user when not authorized
                  babazs
                  If you get an AuthorizationException you know that one of the role is missing. So you should check these two roles.


                  @Observer(Identity.EVENT_NOT_AUTHORIZED)
                  public void notAuthorized(Identity identity) {

                                  if(Identity.instance().hasRole("mysystem.admin"))
                    StatusMessages.instance().addFromResourceBundleOrDefault(Severity.ERROR, "MISSING_someothersystem.adminROLE","");
                            
                       else if(Identity.instance().hasRole("someothersystem.admin")     
                    StatusMessages.instance().addFromResourceBundleOrDefault(Severity.ERROR, "MISSING_mysystem.admin_ROLE","");
                  }
                  • 6. Re: Specific error message for user when not authorized
                    orr94

                    But that will just give an error message for each possible role that the user doesn't have; it may give error messages for roles that weren't involved in the security check. For example:


                    Roles:



                    • a.user




                    • b.user




                    • c.user



                    Methods:


                    @Restrict("#{s:hasRole('a.user')}")
                    public methodA() {...}
                    
                    @Restrict("#{s:hasRole('b.user')}")
                    public methodB() {...}
                    
                    @Restrict("#{s:hasRole('c.user')}")
                    public methodC() {...}



                    Now say a user John is only in the role a.user, but attempts to access methodC(). The code you've described would produce the following two error messages:




                    • You must be in role b.user




                    • You must be in role c.user



                    But really, we only would want to display You must be in role c.user, since that is the role required to access methodC().


                    Basically, to make use of @Observer(Identity.EVENTNOTAUTHORIZED), I need to know what @Restrict expression failed, so that I can add an appropriate message.


                    Any thoughts?









                    • 7. Re: Specific error message for user when not authorized
                      babazs

                      Yes, It works only with two roles (your original example).