1 Reply Latest reply on Jan 6, 2012 7:30 PM by twic

    Can container-managed authentication be exposed via JAAS?

    twic

      This question is quite lengthy; sorry about it. It's that way because i want to supply all the relevant details. But the upshot is: if a web app authenticates users in the normal way (with a security-constraint in the web.xml), is it possible to make the identity available as a JAAS Subject via the AccessControlContext?

       

      I am using JBoss 7.0.2.Final (i'm holding off 7.1 until it goes final). I want to write a web application with two relevant features.

       

      The first relevant feature is that it should authenticate all users. Any access to the app should require a login, ultimately via a form login, but for now, via HTTP basic authentication. This is a very basic bit of development, and i've done it. This looks just like every other web app with authentication, but in the interests of completeness, i'll show what i've done. My web.xml contains the following:

       

      <security-role>
          <role-name>User</role-name>
      </security-role>
      
      <security-constraint>
          <web-resource-collection>
              <web-resource-name>site</web-resource-name>
              <url-pattern>/*</url-pattern>
          </web-resource-collection>
          <auth-constraint>
              <role-name>*</role-name>
          </auth-constraint>
      </security-constraint>
      
      <login-config>
          <auth-method>BASIC</auth-method>
          <realm-name>JAAS Demo</realm-name>
      </login-config>
      

       

      And my standalone.xml contains this:

       

      <subsystem xmlns="urn:jboss:domain:security:1.0">
          <security-domains>
              <security-domain name="other" cache-type="default">
                  <authentication>
                      <login-module code="UsersRoles" flag="required">
                          <module-option name="usersProperties" value="users.properties"/>
                          <module-option name="rolesProperties" value="roles.properties"/>
                      </login-module>
                  </authentication>
              </security-domain>
          </security-domains>
      </subsystem>
      

       

      I have a users.properties and a roles.properties on my webapp classpath that set up a user called alice with the User role.

       

      That's all the configuration i have (notably, i don't seemt to need a jboss-web.xml). With that, i bring up the app, and everything works as expected: i have to log in as alice to see any pages. I have a servlet which logs out the value of request.getRemoteUser() and request.getUserPrincipal(), both of which show that alice is logged in.

       

      The second relevant feature is that i want to use Apache Jackrabbit. There are all sorts of challenges in getting Jackrabbit working, but the one that's relevant here is authentication. Jackrabbit uses JAAS for authentication; the documentation on configuration says:

       

      By default Jackrabbit uses the Java Authentication and Authorization Service (JAAS) to authenticate users who try to access the repository. The appName parameter in the <Security/> element is used as the JAAS application name of the repository.

       

      That's not a very in-depth explanation. The "first hops" tutorial says:

       

      The default Repository.login() method starts a repository session using the default workspace and no user credentials. Jackrabbit tries to use the Java Authentication and Authorization Service (JAAS) configuration in such cases, but defaults to the anonymous user if a JAAS Subject is not found.

       

      Reading the code for the login process makes it clear exactly how Jackrabbit does this; in org.apache.jackrabbit.core.RepositoryImpl.extendAuthentication, there is:

       

      Subject subject = null;
      try {
          AccessControlContext acc = AccessController.getContext();
          subject = Subject.getSubject(acc);
      } catch (SecurityException e) {
          log.warn("Can't check for preauthentication. Reason:", e.getMessage());
      }
      if (subject == null) {
          log.debug("No preauthenticated subject found -> return null.");
          return null;
      }
      

       

      The central bit is the calls to AccessController.getContext and Subject.getSubject. I have seen that combination elsewhere; it seems to be a standard pattern in JAAS for asking something like "who is the current user?".

       

      I haven't yet tried to integrate Jackrabbit, but i have written a servlet which uses that code to find the current Subject. What i was hoping was that this code would retrieve a Subject corresponding to the current user, as authenticated by the container-managed authentication.

       

      The problem is that no Subject is found. Subject.getSubject returns null.

       

      Is my desire, that the logged-in user would be available through JAAS like this, reasonable? Should it work out of the box? Is there more configuration i need to do? Is this a misunderstanding of how authentication works in JBoss?

       

      If anyone has any ideas, comments, suggestions, anything really, i would be very interested to hear them.

       

      The complete application, including JBoss configuration, is available at https://bitbucket.org/twic/jaasdemowebapp/src - if you clone this, you will need to install Ivy, and set environment variables as directed in the get-dependencies.sh script, following which you can run build.sh to build the whole thing. You should be able to use the result as a complete JBoss standalone server.

        • 1. Re: Can container-managed authentication be exposed via JAAS?
          twic

          Section 4.1.2 of the Java Authorization Contract for Containers specification says:

           

          Before it dispatches a call to a web resource, the container must associate with the call thread an AccessControlContext containing the principals of (only) the target component’s runAs identity (as defined in Section 4.5, “Component runAs Identity).

           

          Section 4.5 in turn says:

           

          By default (and unless otherwise specified in the EJB or Servlet specifications), components are configured such that they are assigned the identity of their caller (such as it is) as their runAs identity.

           

          The specification is fairly arcane, so i'm not sure what "their caller (such as it is)" means. If it means the user making the request, and if JBoss supports JACC, then it looks like the code i describe in my question should work.