users@glassfish.java.net

JAAS HTTP Status 403 - Access to the requested resource has been denied

From: Daniel H. Cavalcanti <dhcavalcanti_at_gmail.com>
Date: Mon, 19 Jan 2009 12:49:10 -0500

Hi,

We have an application that uses a database whose schema doesn't fit the
JDBCRealm schema. So to use JAAS we had to implement our own LoginModule
and Realm classes:

public class AccessManagerLoginModule
      extends AppservPasswordLoginModule{

      @Override
      protected void authenticateUser()
      throws LoginException {

          try {

              if (!(_currentRealm instanceof AccessManagerRealm))
                  throw new LoginException("Bad realm: " + _currentRealm);

              AccessManagerRealm realm = (AccessManagerRealm) _currentRealm;
              String[] groups = realm.authenticateUser(_username,
_password);

              commitUserAuthentication(groups);

          } catch (LoginException ex) {
              log.error("Login failed", ex);
              throw ex;
          } catch (Throwable ex) {
              log.error("Unexpected error.", ex);
              throw new LoginException("Unexpected error.");
          }

      }

}

and

public class AccessManagerRealm
      extends AppservRealm {

      public static final String AUTH_TYPE = "FlexiQ AccessManager Custom
Realm";

      public static final String[] GROUPS = new String[]
{"administrator", "supervisor", "operator", "guest"};

      public static final String USERNAME = "dhcavalcanti";
      public static final String PASSWORD = "123456";

      private Log log = LogFactory.getLog(getClass());

      protected void init(Properties props)
      throws BadRealmException, NoSuchRealmException {
          super.init(props);
      }

      @Override
      public String getAuthType() {
          return AUTH_TYPE;
      }

      @Override
      public Enumeration getGroupNames(String username)
      throws InvalidOperationException, NoSuchUserException {
          List<String> groups = new ArrayList<String>(GROUPS.length);
          for (String group : GROUPS)
              groups.add(group);
          System.out.println("groups: " + groups);
          return Collections.enumeration(groups);
      }

      public String[] authenticateUser(String username, String password)
      throws LoginException, PersistenceException {

          if (log.isTraceEnabled())
              log.trace("Authenticating user: " + username + " [" +
password + "]");

          if (!USERNAME.equals(username))
              throw new LoginException("User not found: " + username);
          if (!PASSWORD.equals(password))
              throw new LoginException("Invalid password");

          return GROUPS;

      }

}

So far we hard coded the username and password to test this custom classes.

In the web.xml we added

      <security-constraint>
          <display-name>FlexiQ AccessManager Security - Login</display-name>
          <web-resource-collection>
              <web-resource-name>FlexiQ AccessManager protected
area.</web-resource-name>
              <url-pattern>/authenticated/*</url-pattern>
              <http-method>GET</http-method>
              <http-method>POST</http-method>
              <http-method>HEAD</http-method>
              <http-method>PUT</http-method>
              <http-method>OPTIONS</http-method>
              <http-method>TRACE</http-method>
              <http-method>DELETE</http-method>
          </web-resource-collection>
          <auth-constraint>
              <role-name>administrator</role-name>
              <role-name>supervisor</role-name>
              <role-name>operator</role-name>
              <role-name>guest</role-name>
          </auth-constraint>
          <user-data-constraint>
              <transport-guarantee>CONFIDENTIAL</transport-guarantee>
          </user-data-constraint>
      </security-constraint>

      <security-role>
          <role-name>administrator</role-name>
      </security-role>
      <security-role>
          <role-name>supervisor</role-name>
      </security-role>
      <security-role>
          <role-name>operator</role-name>
      </security-role>
      <security-role>
          <role-name>guest</role-name>
      </security-role>

      <login-config>
          <auth-method>BASIC</auth-method>
          <realm-name>access-manager</realm-name>
      </login-config>

and in the sun-web.xml we added

      <security-role-mapping>
          <role-name>administrator</role-name>
          <group-name>administrator</group-name>
      </security-role-mapping>
      <security-role-mapping>
          <role-name>supervisor</role-name>
          <group-name>supervisor</group-name>
      </security-role-mapping>
      <security-role-mapping>
          <role-name>operator</role-name>
          <group-name>operator</group-name>
      </security-role-mapping>
      <security-role-mapping>
          <role-name>guest</role-name>
          <group-name>guest</group-name>
      </security-role-mapping>

In <domain>/config/login.conf we added

accessManagerRealm {
      com.localmatters.flexiq.accessmanager.jaas.AccessManagerLoginModule
required;
};

Etc.

When we test the web application, we expectedly get the credentials
prompt, enter the username/password and successfully get the page we
requested. However, if we refresh the browser, we simply get the HTTP
403 error code.

We don't know what's going on here. I removed most of the logging code
from the classes to make it clean, but we have logging for the username
and password, and even when we refresh the page, we see the correct
username/password.

For example, when we get the prompt and enter the right
username/password, the log shows:

deployed with moduleid = access-manager-web
Initializing Sun's JavaServer Faces implementation (1.2_04-b20-p03) for
context '/access-manager'
Initializing Sun's JavaServer Faces implementation (1.2_04-b20-p03) for
context ''
JACC Policy Provider: PolicyWrapper.implies,
context(access-manager-web/access-manager-web)-
permission((javax.security.jacc.WebUserDataPermission
/authenticated/home.faces GET)) domain that failed(ProtectionDomain
(file:/access-manager-web/access-manager-web <no signer certificates>)
   null
   <no principals>
   java.security.Permissions_at_d2c05d (
   (javax.management.MBeanPermission [com.sun.messaging.jms.*:*] *)
   (javax.management.MBeanTrustPermission register)
   (unresolved javax.security.jacc.WebUserDataPermission
/:/authenticated/* null)
   (unresolved javax.security.jacc.WebUserDataPermission /authenticated/*
!DELETE,GET,HEAD,OPTIONS,POST,PUT,TRACE)
   (unresolved javax.security.jacc.WebUserDataPermission /authenticated/*
DELETE,GET,HEAD,OPTIONS,POST,PUT,TRACE:CONFIDENTIAL)
   (unresolved
com.sun.corba.ee.impl.presentation.rmi.DynamicAccessPermission access null)
   (unresolved javax.security.jacc.WebResourcePermission /authenticated/*
!DELETE,GET,HEAD,OPTIONS,POST,PUT,TRACE)
   (unresolved javax.security.jacc.WebResourcePermission
/:/authenticated/* null)
   (unresolved com.sun.enterprise.security.CORBAObjectPermission * *)
   (java.net.SocketPermission localhost:1024- listen,resolve)
   (java.net.SocketPermission * connect,resolve)
   (java.lang.RuntimePermission getClassLoader)
   (java.lang.RuntimePermission loadLibrary.*)
   (java.lang.RuntimePermission accessDeclaredMembers)
   (java.lang.RuntimePermission getProtectionDomain)
   (java.lang.RuntimePermission modifyThreadGroup)
   (java.lang.RuntimePermission stopThread)
   (java.lang.RuntimePermission setContextClassLoader)
   (java.lang.RuntimePermission queuePrintJob)
   (javax.security.auth.PrivateCredentialPermission
javax.resource.spi.security.PasswordCredential * "*" read)
   (java.io.FilePermission /tmp/- delete)
   (java.io.FilePermission
/var/lib/glassfishv2/domains/domain1/lib/databases/- delete)
   (java.io.FilePermission <<ALL FILES>> read,write)
   (java.util.PropertyPermission line.separator read)
   (java.util.PropertyPermission java.vm.version read)
   (java.util.PropertyPermission java.vm.specification.version read)
   (java.util.PropertyPermission java.vm.specification.vendor read)
   (java.util.PropertyPermission java.vendor.url read)
   (java.util.PropertyPermission java.vm.name read)
   (java.util.PropertyPermission * read,write)
   (java.util.PropertyPermission os.name read)
   (java.util.PropertyPermission java.vm.vendor read)
   (java.util.PropertyPermission path.separator read)
   (java.util.PropertyPermission java.specification.name read)
   (java.util.PropertyPermission os.version read)
   (java.util.PropertyPermission os.arch read)
   (java.util.PropertyPermission java.class.version read)
   (java.util.PropertyPermission java.version read)
   (java.util.PropertyPermission file.separator read)
   (java.util.PropertyPermission java.vendor read)
   (java.util.PropertyPermission java.vm.specification.name read)
   (java.util.PropertyPermission java.specification.version read)
   (java.util.PropertyPermission java.specification.vendor read)
)
)
Resolving realm...
Realm resolved: access-manager. Delegating authentication to realm...
Authenticating user: dhcavalcanti [123456]
[TopLink Info]: 2009.01.19
12:44:00.348--ServerSession(10893564)--TopLink, version: Oracle TopLink
Essentials - 2.0.1 (Build SNAPSHOT (02/01/2008))
[TopLink Info]: 2009.01.19
12:44:01.519--ServerSession(10893564)--file:/home/dhcavalcanti/projects/FlexiAccessManager/implementation/access-manager-JAAS/dist/access-manager-JAAS.jar-AccessManagerPersistence

login successful
Committing user authentication: bind user to group membership.
User authenticated.
Added Library from:
jar:file:/home/dhcavalcanti/projects/FlexiAccessManager/implementation/access-manager-web/build/web/WEB-INF/lib/jsf-facelets.jar!/META-INF/jsf-core.taglib.xml
Added Library from:
jar:file:/home/dhcavalcanti/projects/FlexiAccessManager/implementation/access-manager-web/build/web/WEB-INF/lib/jsf-facelets.jar!/META-INF/jsf-html.taglib.xml
Added Library from:
jar:file:/home/dhcavalcanti/projects/FlexiAccessManager/implementation/access-manager-web/build/web/WEB-INF/lib/jsf-facelets.jar!/META-INF/jsf-ui.taglib.xml
Added Library from:
jar:file:/home/dhcavalcanti/projects/FlexiAccessManager/implementation/access-manager-web/build/web/WEB-INF/lib/jsf-facelets.jar!/META-INF/jstl-core.taglib.xml
Added Library from:
jar:file:/home/dhcavalcanti/projects/FlexiAccessManager/implementation/access-manager-web/build/web/WEB-INF/lib/jsf-facelets.jar!/META-INF/jstl-fn.taglib.xml
Added Library from:
jar:file:/home/dhcavalcanti/projects/FlexiAccessManager/implementation/access-manager-web/build/web/WEB-INF/lib/trinidad-impl-1.2.10.jar!/META-INF/tr.taglib.xml
Added Library from:
jar:file:/home/dhcavalcanti/projects/FlexiAccessManager/implementation/access-manager-web/build/web/WEB-INF/lib/trinidad-impl-1.2.10.jar!/META-INF/trh.taglib.xml

We get the page as expected. Then we refresh the page through the
browser and get the HTTP 403 error page, the log (continued from the one
above) shows:

Resolving realm...
Realm resolved: access-manager. Delegating authentication to realm...
Authenticating user: dhcavalcanti [123456]
Committing user authentication: bind user to group membership.
User authenticated.

Is this a bug, are we doing something wrong?
Any help is greatly appreciated.

thanks,
Daniel