<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="basic">
    <info>
        <title>Basic and Digest Authentication</title>
    </info>
    <para>Basic and digest authentiation are alternative authentication mechanisms which are popular
        in web applications. Basic authentication is often used with stateless clients which pass
        their credentials on each request. It's quite common to use it in combination with
        form-based authentication where an application is used through both a browser-based user
        interface and as a web-service. However, basic authentication transmits the password as
        plain text so it should only really be used over an encrypted transport layer such as
        HTTPS.</para>
    <section xml:id="basic-processing-filter">
        <info>
            <title><classname>BasicAuthenticationFilter</classname></title>
        </info>
        <para><literal>BasicAuthenticationFilter</literal> is responsible for processing basic
            authentication credentials presented in HTTP headers. This can be used for
            authenticating calls made by Spring remoting protocols (such as Hessian and Burlap), as
            well as normal browser user agents (such as Firefox and Internet Explorer). The standard
            governing HTTP Basic Authentication is defined by RFC 1945, Section 11, and
            <literal>BasicAuthenticationFilter</literal> conforms with this RFC. Basic
            Authentication is an attractive approach to authentication, because it is very widely
            deployed in user agents and implementation is extremely simple (it's just a Base64
            encoding of the username:password, specified in an HTTP header).</para>
        <section xml:id="basic-config">
            <info>
                <title>Configuration</title>
            </info>
            <para>To implement HTTP Basic Authentication, you need to add a
                <literal>BasicAuthenticationFilter</literal> to your filter chain. The application
                context should contain <literal>BasicAuthenticationFilter</literal> and its required
                collaborator:</para>
            <para> <programlisting language="xml"><![CDATA[
<bean id="basicAuthenticationFilter"
  class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
  <property name="authenticationManager" ref="authenticationManager"/>
  <property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
</bean>

<bean id="authenticationEntryPoint"
  class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
  <property name="realmName" value="Name Of Your Realm"/>
</bean>]]>
                </programlisting> </para>
            <para>The configured <interfacename>AuthenticationManager</interfacename> processes each
                authentication request. If authentication fails, the configured
                <interfacename>AuthenticationEntryPoint</interfacename> will be used to retry the
                authentication process. Usually you will use the filter in combination with a
                <literal>BasicAuthenticationEntryPoint</literal>, which returns a 401 response with
                a suitable header to retry HTTP Basic authentication. If authentication is
                successful, the resulting <interfacename>Authentication</interfacename> object will
                be placed into the <classname>SecurityContextHolder</classname> as usual.</para>
            <para>If the authentication event was successful, or authentication was not attempted
                because the HTTP header did not contain a supported authentication request, the
                filter chain will continue as normal. The only time the filter chain will be
                interrupted is if authentication fails and the
                <interfacename>AuthenticationEntryPoint</interfacename> is called.</para>
        </section>
    </section>
    <section xml:id="digest-processing-filter">
        <title><classname>DigestAuthenticationFilter</classname></title>
        <para><classname>DigestAuthenticationFilter</classname> is capable of processing digest
            authentication credentials presented in HTTP headers. Digest Authentication attempts to
            solve many of the weaknesses of Basic authentication, specifically by ensuring
            credentials are never sent in clear text across the wire. Many user agents support
            Digest Authentication, including FireFox and Internet Explorer. The standard governing
            HTTP Digest Authentication is defined by RFC 2617, which updates an earlier version of
            the Digest Authentication standard prescribed by RFC 2069. Most user agents implement
            RFC 2617. Spring Security's <classname>DigestAuthenticationFilter</classname> is
            compatible with the "<literal>auth</literal>" quality of protection
            (<literal>qop</literal>) prescribed by RFC 2617, which also provides backward
            compatibility with RFC 2069. Digest Authentication is a more attractive option if you
            need to use unencrypted HTTP (i.e. no TLS/HTTPS) and wish to maximise security of the
            authentication process. Indeed Digest Authentication is a mandatory requirement for the
            WebDAV protocol, as noted by RFC 2518 Section 17.1.</para>
        <para>Digest Authentication is definitely the most secure choice between Form
            Authentication, Basic Authentication and Digest Authentication, although extra security
            also means more complex user agent implementations. Central to Digest Authentication is
            a "nonce". This is a value the server generates. Spring Security's nonce adopts the
            following format:</para>
        <para>
            <programlisting language="txt">
  base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))

  expirationTime:   The date and time when the nonce expires, expressed in milliseconds
  key:              A private key to prevent modification of the nonce token
            </programlisting> </para>
        <para>The <classname>DigestAuthenticatonEntryPoint</classname> has a property specifying the
            <literal>key</literal> used for generating the nonce tokens, along with a
            <literal>nonceValiditySeconds</literal> property for determining the expiration time
            (default 300, which equals five minutes). Whist ever the nonce is valid, the digest is
            computed by concatenating various strings including the username, password, nonce, URI
            being requested, a client-generated nonce (merely a random value which the user agent
            generates each request), the realm name etc, then performing an MD5 hash. Both the
            server and user agent perform this digest computation, resulting in different hash codes
            if they disagree on an included value (eg password). In Spring Security implementation,
            if the server-generated nonce has merely expired (but the digest was otherwise valid),
            the <classname>DigestAuthenticationEntryPoint</classname> will send a
            <literal>"stale=true"</literal> header. This tells the user agent there is no need to
            disturb the user (as the password and username etc is correct), but simply to try again
            using a new nonce.</para>
        <para>An appropriate value for <classname>DigestAuthenticationEntryPoint</classname>'s
            <literal>nonceValiditySeconds</literal> parameter will depend on your application.
            Extremely secure applications should note that an intercepted authentication header can
            be used to impersonate the principal until the <literal>expirationTime</literal>
            contained in the nonce is reached. This is the key principle when selecting an
            appropriate setting, but it would be unusual for immensely secure applications to not be
            running over TLS/HTTPS in the first instance.</para>
        <para>Because of the more complex implementation of Digest Authentication, there are often
            user agent issues. For example, Internet Explorer fails to present an
            "<literal>opaque</literal>" token on subsequent requests in the same session. Spring
            Security filters therefore encapsulate all state information into the
            "<literal>nonce</literal>" token instead. In our testing, Spring Security's
            implementation works reliably with FireFox and Internet Explorer, correctly handling
            nonce timeouts etc.</para>
        <section xml:id="digest-config">
            <title>Configuration</title>
            <para>Now that we've reviewed the theory, let's see how to use it. To implement HTTP
                Digest Authentication, it is necessary to define
                <literal>DigestAuthenticationFilter</literal> in the filter chain. The application
                context will need to define the <literal>DigestAuthenticationFilter</literal> and
                its required collaborators:</para>
            <para> <programlisting language="xml"><![CDATA[
<bean id="digestFilter" class=
    "org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
  <property name="userDetailsService" ref="jdbcDaoImpl"/>
  <property name="authenticationEntryPoint" ref="digestEntryPoint"/>
  <property name="userCache" ref="userCache"/>
</bean>

<bean id="digestEntryPoint" class=
    "org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
  <property name="realmName" value="Contacts Realm via Digest Authentication"/>
  <property name="key" value="acegi"/>
  <property name="nonceValiditySeconds" value="10"/>
</bean>]]>
                </programlisting> </para>
            <para>The configured <interfacename>UserDetailsService</interfacename> is needed because
                <literal>DigestAuthenticationFilter</literal> must have direct access to the clear
                text password of a user. Digest Authentication will NOT work if you are using
                encoded passwords in your DAO <footnote><para>It is possible to encode the password in the
                format HEX( MD5(username:realm:password) ) provided the
                <code>DigestAuthenticationFilter.passwordAlreadyEncoded</code> is set to <code>true</code>.
                However, other password encodings will not work with digest authentication.</para></footnote>.
                The DAO collaborator, along with the <literal>UserCache</literal>, are typically shared directly
                with a <classname>DaoAuthenticationProvider</classname>. The
                <literal>authenticationEntryPoint</literal> property must be
                <classname>DigestAuthenticationEntryPoint</classname>, so that
                <classname>DigestAuthenticationFilter</classname> can obtain the correct
                <literal>realmName</literal> and <literal>key</literal> for digest
                calculations.</para>
            <para>Like <literal>BasicAuthenticationFilter</literal>, if authentication is successful
                an <interfacename>Authentication</interfacename> request token will be placed into
                the <classname>SecurityContextHolder</classname>. If the authentication event was
                successful, or authentication was not attempted because the HTTP header did not
                contain a Digest Authentication request, the filter chain will continue as normal.
                The only time the filter chain will be interrupted is if authentication fails and
                the <interfacename>AuthenticationEntryPoint</interfacename> is called, as discussed
                in the previous paragraph.</para>
            <para>Digest Authentication's RFC offers a range of additional features to further
                increase security. For example, the nonce can be changed on every request. Despite
                this, Spring Security implementation was designed to minimise the complexity of the
                implementation (and the doubtless user agent incompatibilities that would emerge),
                and avoid needing to store server-side state. You are invited to review RFC 2617 if
                you wish to explore these features in more detail. As far as we are aware, Spring
                Security's implementation does comply with the minimum standards of this RFC.</para>
        </section>
    </section>
</chapter>
