<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="jaas">
    <info>
        <title>Java Authentication and Authorization Service (JAAS) Provider</title>
    </info>

    <section xml:aid="jaas-overview">
        <info>
            <title>Overview</title>
        </info>
        <para>Spring Security provides a package able to delegate authentication requests to the
            Java Authentication and Authorization Service (JAAS). This package is discussed in
            detail below.</para>
    </section>

    <section xml:id="jaas-abstractjaasauthenticationprovider">
        <info>
            <title>AbstractJaasAuthenticationProvider</title>
        </info>
        <para>The <classname>AbstractJaasAuthenticationProvider</classname> is the basis for the
            provided JAAS <interfacename>AuthenticationProvider</interfacename> implementations. Subclasses
            must implement a method that creates the <classname>LoginContext</classname>. The
            <classname>AbstractJaasAuthenticationProvider</classname> has a number of dependencies that can
            be injected into it that are discussed below.</para>

        <section xml:id="jaas-callbackhandler">
            <info>
                <title xml:id="jaas-callback-handler">JAAS CallbackHandler</title>
            </info>

            <para>Most JAAS <literal>LoginModule</literal>s require a callback of some sort. These
                callbacks are usually used to obtain the username and password from the user.</para>

            <para>In a Spring Security deployment, Spring Security is responsible for this user
                interaction (via the authentication mechanism). Thus, by the time the authentication
                request is delegated through to JAAS, Spring Security's authentication mechanism
                will already have fully-populated an <interfacename>Authentication</interfacename>
                object containing all the information required by the JAAS
                <literal>LoginModule</literal>.</para>

            <para>Therefore, the JAAS package for Spring Security provides two default callback
                handlers, <literal>JaasNameCallbackHandler</literal> and
                <literal>JaasPasswordCallbackHandler</literal>. Each of these callback handlers
                implement <literal>JaasAuthenticationCallbackHandler</literal>. In most cases these
                callback handlers can simply be used without understanding the internal
                mechanics.</para>

            <para>For those needing full control over the callback behavior, internally
                <classname>AbstractJaasAuthenticationProvider</classname> wraps these
                <literal>JaasAuthenticationCallbackHandler</literal>s with an
                <literal>InternalCallbackHandler</literal>. The
                <literal>InternalCallbackHandler</literal> is the class that actually implements
                JAAS’ normal <literal>CallbackHandler</literal> interface. Any time that the JAAS
                <literal>LoginModule</literal> is used, it is passed a list of application context
                configured <literal>InternalCallbackHandler</literal>s. If the
                <literal>LoginModule</literal> requests a callback against the
                <literal>InternalCallbackHandler</literal>s, the callback is in-turn passed to the
                <literal>JaasAuthenticationCallbackHandler</literal>s being wrapped.</para>
        </section>

        <section xml:id="jaas-authoritygranter">
            <info>
                <title xml:id="jaas-authority-granter">JAAS AuthorityGranter</title>
            </info>

            <para>JAAS works with principals. Even "roles" are represented as principals in JAAS.
                Spring Security, on the other hand, works with
                <interfacename>Authentication</interfacename> objects. Each
                <interfacename>Authentication</interfacename> object contains a single principal,
                and multiple <interfacename>GrantedAuthority</interfacename>s. To facilitate
                mapping between these different concepts, Spring Security's JAAS package includes an
                <literal>AuthorityGranter</literal> interface.</para>

            <para>An <literal>AuthorityGranter</literal> is responsible for inspecting a JAAS
                principal and returning a set of <literal>String</literal>s, representing the
                authorities assigned to the principal. For each returned authority string, the
                <classname>AbstractJaasAuthenticationProvider</classname> creates a
                <classname>JaasGrantedAuthority</classname> (which implements Spring Security’s
                <interfacename>GrantedAuthority</interfacename> interface) containing the authority
                string and the JAAS principal that the
                <interfacename>AuthorityGranter</interfacename> was passed. The
                <classname>AbstractJaasAuthenticationProvider</classname> obtains the JAAS principals by
                firstly successfully authenticating the user’s credentials using the JAAS
                <literal>LoginModule</literal>, and then accessing the
                <literal>LoginContext</literal> it returns. A call to
                <literal>LoginContext.getSubject().getPrincipals()</literal> is made, with each
                resulting principal passed to each <interfacename>AuthorityGranter</interfacename>
                defined against the
                <literal>AbstractJaasAuthenticationProvider.setAuthorityGranters(List)</literal>
                property.</para>

            <para>Spring Security does not include any production
                <interfacename>AuthorityGranter</interfacename>s given that every JAAS principal has
                an implementation-specific meaning. However, there is a
                <literal>TestAuthorityGranter</literal> in the unit tests that demonstrates a simple
                <literal>AuthorityGranter</literal> implementation.</para>
        </section>
    </section>
    <section xml:id="jaas-defaultjaasauthenticationprovider">
        <info>
            <title>DefaultJaasAuthenticationProvider</title>
        </info>
        <para>The <classname>DefaultJaasAuthenticationProvider</classname> allows a JAAS
            <classname>Configuration</classname> object to be injected into it as a dependency. It then
            creates a <classname>LoginContext</classname> using the injected JAAS <classname>Configuration</classname>.
            This means that <classname>DefaultJaasAuthenticationProvider</classname> is not bound any particular implementation
            of <classname>Configuration</classname> as <classname>JaasAuthenticationProvider</classname> is.</para>

            <section xml:id="jaas-inmemoryconfiguration">
                <info>
                    <title>InMemoryConfiguration</title>
                </info>
                <para>In order to make it easy to inject a <classname>Configuration</classname> into
                    <classname>DefaultJaasAuthenticationProvider</classname>, a default in memory
                    implementation named <classname>InMemoryConfiguration</classname> is provided. The
                    implementation constructor accepts a <interfacename>Map</interfacename> where each key represents a
                    login configuration name and the value represents an <classname>Array</classname> of
                    <classname>AppConfigurationEntry</classname>s.
                    <classname>InMemoryConfiguration</classname> also supports a default
                    <classname>Array</classname> of <classname>AppConfigurationEntry</classname> objects that
                    will be used if no mapping is found within the provided <interfacename>Map</interfacename>. For
                    details, refer to the class level javadoc of <classname>InMemoryConfiguration</classname>.</para>
            </section>

            <section xml:id="jaas-djap-config">
                <info>
                    <title>DefaultJaasAuthenticationProvider Example Configuration</title>
                </info>
                <para>While the Spring configuration for <classname>InMemoryConfiguration</classname> can be
                    more verbose than the standarad JAAS configuration files, using it in conjuction with
                    <classname>DefaultJaasAuthenticationProvider</classname> is more flexible than
                    <classname>JaasAuthenticationProvider</classname> since it not dependant on the default
                    <classname>Configuration</classname> implementation.</para>
                <para>An example configuration of <classname>DefaultJaasAuthenticationProvider</classname> using
                    <classname>InMemoryConfiguration</classname> is provided below. Note that custom implementations of
                    <classname>Configuration</classname> can easily be injected into
                    <classname>DefaultJaasAuthenticationProvider</classname> as well.</para>
                <programlisting language="xml"><![CDATA[
<bean id="jaasAuthProvider"
   class="org.springframework.security.authentication.jaas.DefaultJaasAuthenticationProvider">
 <property name="configuration">
  <bean class="org.springframework.security.authentication.jaas.memory.InMemoryConfiguration">
   <constructor-arg>
    <map>
     <!--
       SPRINGSECURITY is the default loginContextName
       for AbstractJaasAuthenticationProvider
     -->
     <entry key="SPRINGSECURITY">
      <array>
       <bean class="javax.security.auth.login.AppConfigurationEntry">
        <constructor-arg value="sample.SampleLoginModule" />
         <constructor-arg>
          <util:constant static-field=
            "javax.security.auth.login.AppConfigurationEntry$LoginModuleControlFlag.REQUIRED"/>
         </constructor-arg>
         <constructor-arg>
          <map></map>
         </constructor-arg>
        </bean>
       </array>
      </entry>
     </map>
    </constructor-arg>
   </bean>
  </property>
  <property name="authorityGranters">
   <list>
    <!-- You will need to write your own implementation of AuthorityGranter -->
    <bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/>
   </list>
  </property>
</bean>
]]></programlisting>
            </section>
    </section>

    <section xml:id="jaas-jaasauthenticationprovider">
        <info>
            <title>JaasAuthenticationProvider</title>
        </info>
        <para>The <classname>JaasAuthenticationProvider</classname> assumes the default <classname>Configuration</classname> is an instance of
            <link xlink:href="http://download.oracle.com/javase/1.4.2/docs/guide/security/jaas/spec/com/sun/security/auth/login/ConfigFile.html">
            ConfigFile</link>. This assumption is made in order to attempt to update the <classname>Configuration</classname>. The
            <classname>JaasAuthenticationProvider</classname> then uses the default <classname>Configuration</classname> to create the
            <classname>LoginContext</classname>.</para>

        <para>Let’s assume we have a JAAS login configuration file,
            <literal>/WEB-INF/login.conf</literal>, with the following contents:
            <programlisting language="txt">
JAASTest {
    sample.SampleLoginModule required;
};</programlisting></para>
        <para>Like all Spring Security beans, the <classname>JaasAuthenticationProvider</classname>
            is configured via the application context. The following definitions would correspond to
            the above JAAS login configuration file: <programlisting language="xml"><![CDATA[
<bean id="jaasAuthenticationProvider"
   class="org.springframework.security.authentication.jaas.JaasAuthenticationProvider">
 <property name="loginConfig" value="/WEB-INF/login.conf"/>
 <property name="loginContextName" value="JAASTest"/>
 <property name="callbackHandlers">
  <list>
   <bean
     class="org.springframework.security.authentication.jaas.JaasNameCallbackHandler"/>
   <bean
     class="org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler"/>
  </list>
  </property>
  <property name="authorityGranters">
    <list>
      <bean class="org.springframework.security.authentication.jaas.TestAuthorityGranter"/>
    </list>
  </property>
</bean>
]]></programlisting></para>
    </section>
    <section xml:id="jaas-apiprovision">
        <info>
            <title xml:id="jaas-api-provision">Running as a Subject</title>
        </info>
        <para>If configured, the <classname>JaasApiIntegrationFilter</classname> will attempt to
            run as the <literal>Subject</literal> on the
            <classname>JaasAuthenticationToken</classname>. This means that the
            <literal>Subject</literal> can be accessed using:
            <programlisting language="java"><![CDATA[
            Subject subject = Subject.getSubject(AccessController.getContext());
]]></programlisting>
            This integration can easily be configured using the
            <link xlink:href="#nsa-http-jaas-api-provision">jaas-api-provision</link> attribute. This
            feature is useful when integrating with legacy or external API's that rely on the
            JAAS Subject being populated.</para>
    </section>
</chapter>