<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
                 "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<!-- 
    ====================================================================
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at
    
    http://www.apache.org/licenses/LICENSE-2.0
    
    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.
    ====================================================================
-->
<chapter id="authentication">
    <title>HTTP authentication</title>
    <para>HttpClient provides full support for authentication schemes defined by the HTTP standard
        specification as well as a number of widely used non-standard authentication schemes such 
        as <literal>NTLM</literal> and <literal>SPNEGO</literal>.</para>
    <section>
        <title>User credentials</title>
        <para>Any process of user authentication requires a set of credentials that can be used to
            establish user identity. In the simplest form user credentials can be just a user name /
            password pair. <classname>UsernamePasswordCredentials</classname> represents a set of
            credentials consisting of a security principal and a password in clear text. This
            implementation is sufficient for standard authentication schemes defined by the HTTP
            standard specification.</para>
        <programlisting><![CDATA[
UsernamePasswordCredentials creds = new UsernamePasswordCredentials("user", "pwd");
System.out.println(creds.getUserPrincipal().getName());
System.out.println(creds.getPassword());
        ]]></programlisting>
        <para>stdout &gt;</para>
        <programlisting><![CDATA[
user
pwd
]]></programlisting>
        <para><classname>NTCredentials</classname> is a Microsoft Windows specific implementation
            that includes in addition to the user name / password pair a set of additional Windows
            specific attributes such as the name of the user domain. In a Microsoft Windows network
            the same user can belong to multiple domains each with a different set of
            authorizations.</para>
        <programlisting><![CDATA[
NTCredentials creds = new NTCredentials("user", "pwd", "workstation", "domain");
System.out.println(creds.getUserPrincipal().getName());
System.out.println(creds.getPassword());
]]></programlisting>
        <para>stdout &gt;</para>
        <programlisting><![CDATA[
DOMAIN/user
pwd
]]></programlisting>
    </section>
    <section>
        <title>Authentication schemes</title>
        <para>The <interfacename>AuthScheme</interfacename> interface represents an abstract
            challenge-response oriented authentication scheme. An authentication scheme is expected
            to support the following functions:</para>
        <itemizedlist>
            <listitem>
                <para>Parse and process the challenge sent by the target server in response to
                    request for a protected resource.</para>
            </listitem>
            <listitem>
                <para>Provide properties of the processed challenge: the authentication scheme type
                    and its parameters, such the realm this authentication scheme is applicable to,
                    if available</para>
            </listitem>
            <listitem>
                <para>Generate the authorization string for the given set of credentials and the HTTP
                    request in response to the actual authorization challenge.</para>
            </listitem>
        </itemizedlist>
        <para>Please note that authentication schemes may be stateful involving a series of
            challenge-response exchanges.</para>
        <para>HttpClient ships with several <interfacename>AuthScheme</interfacename>
            implementations:</para>
        <itemizedlist>
            <listitem>
                <formalpara>
                    <title>Basic:</title>
                    <para>Basic authentication scheme as defined in RFC 2617. This authentication
                        scheme is insecure, as the credentials are transmitted in clear text.
                        Despite its insecurity Basic authentication scheme is perfectly adequate if
                        used in combination with the TLS/SSL encryption.</para>
                </formalpara>
            </listitem>
            <listitem>
                <formalpara>
                    <title>Digest</title>
                    <para>Digest authentication scheme as defined in RFC 2617. Digest authentication
                        scheme is significantly more secure than Basic and can be a good choice for
                        those applications that do not want the overhead of full transport security
                        through TLS/SSL encryption.</para>
                </formalpara>
            </listitem>
            <listitem>
                <formalpara>
                    <title>NTLM:</title>
                    <para>NTLM is a proprietary authentication scheme developed by Microsoft and
                        optimized for Windows platforms. NTLM is believed to be more secure than
                        Digest.</para>
                </formalpara>
            </listitem>
            <listitem>
                <formalpara>
                    <title>SPNEGO:</title>
                    <para><literal>SPNEGO</literal> (<emphasis>S</emphasis>imple and
                            <emphasis>P</emphasis>rotected <literal>GSSAPI</literal>
                        <emphasis>Nego</emphasis>tiation Mechanism) is a <literal>GSSAPI</literal>
                        "pseudo mechanism" that is used to negotiate one of a number of possible
                        real mechanisms. SPNEGO's most visible use is in Microsoft's <literal>HTTP
                            Negotiate</literal> authentication extension. The negotiable
                        sub-mechanisms include NTLM and Kerberos supported by Active Directory.
                        At present HttpClient only supports the Kerberos sub-mechanism. </para>
                </formalpara>
            </listitem>
            <listitem>
                <formalpara>
                    <title>Kerberos:</title>
                    <para>Kerberos authentication implementation. </para>
                </formalpara>
            </listitem>
        </itemizedlist>
    </section>
    <section>
        <title>Credentials provider</title>
        <para>Credentials providers are intended to maintain a set of user credentials and to be
            able to produce user credentials for a particular authentication scope. Authentication
            scope consists of a host name, a port number, a realm name and an authentication scheme
            name. When registering credentials with the credentials provider one can provide a wild
            card (any host, any port, any realm, any scheme) instead of a concrete attribute value.
            The credentials provider is then expected to be able to find the closest match for a
            particular scope if the direct match cannot be found.</para>
        <para>HttpClient can work with any physical representation of a credentials provider that
            implements the <interfacename>CredentialsProvider</interfacename> interface. The default
                <interfacename>CredentialsProvider</interfacename> implementation called
                <classname>BasicCredentialsProvider</classname> is a simple implementation backed by
            a <classname>java.util.HashMap</classname>.</para>
        <programlisting><![CDATA[
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
    new AuthScope("somehost", AuthScope.ANY_PORT), 
    new UsernamePasswordCredentials("u1", "p1"));
credsProvider.setCredentials(
    new AuthScope("somehost", 8080), 
    new UsernamePasswordCredentials("u2", "p2"));
credsProvider.setCredentials(
    new AuthScope("otherhost", 8080, AuthScope.ANY_REALM, "ntlm"), 
    new UsernamePasswordCredentials("u3", "p3"));

System.out.println(credsProvider.getCredentials(
    new AuthScope("somehost", 80, "realm", "basic")));
System.out.println(credsProvider.getCredentials(
    new AuthScope("somehost", 8080, "realm", "basic")));
System.out.println(credsProvider.getCredentials(
    new AuthScope("otherhost", 8080, "realm", "basic")));
System.out.println(credsProvider.getCredentials(
    new AuthScope("otherhost", 8080, null, "ntlm")));
]]></programlisting>
        <para>stdout &gt;</para>
        <programlisting><![CDATA[
[principal: u1]
[principal: u2]
null
[principal: u3]
]]></programlisting>
    </section>
    <section>
        <title>HTTP authentication and execution context</title>
        <para>HttpClient relies on the <classname>AuthState</classname> class to keep track of
            detailed information about the state of the authentication process. HttpClient creates
            two instances of <classname>AuthState</classname> in the course of HTTP request
            execution: one for target host authentication and another one for proxy authentication.
            In case the target server or the proxy require user authentication the respective
                <classname>AuthScope</classname> instance will be populated with the
                <classname>AuthScope</classname>, <interfacename>AuthScheme</interfacename> and
                <interfacename>Crednetials</interfacename> used during the authentication process.
            The <classname>AuthState</classname> can be examined in order to find out what kind of
            authentication was requested, whether a matching
                <interfacename>AuthScheme</interfacename> implementation was found and whether the
            credentials provider managed to find user credentials for the given authentication
            scope.</para>
        <para>In the course of HTTP request execution HttpClient adds the following authentication
            related objects to the execution context:</para>
        <itemizedlist>
            <listitem>
                <formalpara>
                    <para><interfacename>Lookup</interfacename> instance representing the actual
                        authentication scheme registry. The value of this attribute set in the local
                        context takes precedence over the default one.</para>
                </formalpara>
            </listitem>
            <listitem>
                <formalpara>
                    <para><interfacename>CredentialsProvider</interfacename> instance representing
                        the actual credentials provider. The value of this attribute set in the
                        local context takes precedence over the default one.</para>
                </formalpara>
            </listitem>
            <listitem>
                <formalpara>
                    <para><classname>AuthState</classname> instance representing the actual target
                        authentication state. The value of this attribute set in the local context
                        takes precedence over the default one.</para>
                </formalpara>
            </listitem>
            <listitem>
                <formalpara>
                    <para><classname>AuthState</classname> instance representing the actual proxy
                        authentication state. The value of this attribute set in the local context
                        takes precedence over the default one.</para>
                </formalpara>
            </listitem>
            <listitem>
                <formalpara>
                    <para><interfacename>AuthCache</interfacename> instance representing the actual
                        authentication data cache. The value of this attribute set in the local 
                        context takes precedence over the default one.</para>
                </formalpara>
            </listitem>
        </itemizedlist>
        <para>The local <interfacename>HttpContext</interfacename> object can be used to customize
            the HTTP authentication context prior to request execution, or to examine its state after
            the request has been executed:</para>
        <programlisting><![CDATA[
CloseableHttpClient httpclient = <...>

CredentialsProvider credsProvider = <...>
Lookup<AuthSchemeProvider> authRegistry = <...>
AuthCache authCache = <...>

HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
context.setAuthSchemeRegistry(authRegistry);
context.setAuthCache(authCache);
HttpGet httpget = new HttpGet("http://somehost/");
CloseableHttpResponse response1 = httpclient.execute(httpget, context);
<...>

AuthState proxyAuthState = context.getProxyAuthState();
System.out.println("Proxy auth state: " + proxyAuthState.getState());
System.out.println("Proxy auth scheme: " + proxyAuthState.getAuthScheme());
System.out.println("Proxy auth credentials: " + proxyAuthState.getCredentials());
AuthState targetAuthState = context.getTargetAuthState();
System.out.println("Target auth state: " + targetAuthState.getState());
System.out.println("Target auth scheme: " + targetAuthState.getAuthScheme());
System.out.println("Target auth credentials: " + targetAuthState.getCredentials());
]]></programlisting>
    </section>
    <section>
        <title>Caching of authentication data</title>
        <para>As of version 4.1 HttpClient automatically caches information about hosts it has 
            successfully authenticated with. Please note that one must use the same execution 
            context to execute logically related requests in order for cached authentication data
            to propagate from one request to another. Authentication data will be lost as soon as 
            the execution context goes out of scope.</para>
    </section>
    <section>
        <title>Preemptive authentication</title>
        <para>HttpClient does not support preemptive authentication out of the box, because if
            misused or used incorrectly the preemptive authentication can lead to significant
            security issues, such as sending user credentials in clear text to an unauthorized third
            party. Therefore, users are expected to evaluate potential benefits of preemptive
            authentication versus security risks in the context of their specific application
            environment.</para>
        <para>Nonetheless one can configure HttpClient to authenticate preemptively by prepopulating
            the authentication data cache.</para>
        <programlisting><![CDATA[
CloseableHttpClient httpclient = <...>

HttpHost targetHost = new HttpHost("localhost", 80, "http");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
        new AuthScope(targetHost.getHostName(), targetHost.getPort()),
        new UsernamePasswordCredentials("username", "password"));

// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate BASIC scheme object and add it to the local auth cache
BasicScheme basicAuth = new BasicScheme();
authCache.put(targetHost, basicAuth);

// Add AuthCache to the execution context
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
context.setAuthCache(authCache);

HttpGet httpget = new HttpGet("/");
for (int i = 0; i < 3; i++) {
    CloseableHttpResponse response = httpclient.execute(
            targetHost, httpget, context);
    try {
        HttpEntity entity = response.getEntity();

    } finally {
        response.close();
    }
}
]]></programlisting>
    </section>

    <section id="ntlm">
        <title>NTLM Authentication</title>
        <para>As of version 4.1 HttpClient provides full support for NTLMv1, NTLMv2, and NTLM2 
            Session authentication out of the box. One can still continue using an external 
            <literal>NTLM</literal> engine such as <ulink url="http://jcifs.samba.org/">JCIFS
            </ulink> library developed by the <ulink url="http://www.samba.org/">Samba</ulink>
            project as a part of their Windows interoperability suite of programs.
        </para>
        <section>
            <title>NTLM connection persistence</title>
            <para>The <literal>NTLM</literal> authentication scheme is significantly more expensive
                in terms of computational overhead and performance impact than the standard 
                <literal>Basic</literal> and <literal>Digest</literal> schemes. This is likely to be
                one of the main reasons why Microsoft chose to make <literal>NTLM</literal> 
                authentication scheme stateful. That is, once authenticated, the user identity is 
                associated with that connection for its entire life span. The stateful nature of 
                <literal>NTLM</literal> connections makes connection persistence more complex, as 
                for the obvious reason persistent <literal>NTLM</literal> connections may not be 
                re-used by users with a different user identity. The standard connection managers 
                shipped with HttpClient are fully capable of managing stateful connections. However, 
                it is critically important that logically related requests within the same session 
                use the same execution context in order to make them aware of the current user 
                identity. Otherwise, HttpClient will end up creating a new HTTP connection for each 
                HTTP request against <literal>NTLM</literal> protected resources. For detailed 
                discussion on stateful HTTP connections please refer to 
                <link linkend="stateful_conn">this </link> section. </para>
                <!-- Note: the stateful_conn anchor is in the file advanced.xml -->
            <para>As <literal>NTLM</literal> connections are stateful it is generally recommended
                to trigger <literal>NTLM</literal> authentication using a relatively cheap method,
                such as <literal>GET</literal> or <literal>HEAD</literal>, and re-use the same 
                connection to execute more expensive methods, especially those enclose a request
                entity, such as <literal>POST</literal> or <literal>PUT</literal>. </para>
            <programlisting><![CDATA[
CloseableHttpClient httpclient = <...>

CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,
        new NTCredentials("user", "pwd", "myworkstation", "microsoft.com"));

HttpHost target = new HttpHost("www.microsoft.com", 80, "http");

// Make sure the same context is used to execute logically related requests
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);

// Execute a cheap method first. This will trigger NTLM authentication
HttpGet httpget = new HttpGet("/ntlm-protected/info");
CloseableHttpResponse response1 = httpclient.execute(target, httpget, context);
try {
    HttpEntity entity1 = response1.getEntity();
} finally {
    response1.close();
}

// Execute an expensive method next reusing the same context (and connection)
HttpPost httppost = new HttpPost("/ntlm-protected/form");
httppost.setEntity(new StringEntity("lots and lots of data"));
CloseableHttpResponse response2 = httpclient.execute(target, httppost, context);
try {
    HttpEntity entity2 = response2.getEntity();
} finally {
    response2.close();
}
]]></programlisting>
        </section>
    </section>

    <section id="spnego">
        <title><literal>SPNEGO</literal>/Kerberos Authentication</title>
        <para>The <literal>SPNEGO</literal> (<emphasis>S</emphasis>imple and
            <emphasis>P</emphasis>rotected <literal>GSSAPI</literal>
            <emphasis>Nego</emphasis>tiation Mechanism) is designed to allow for authentication to
            services when neither end knows what the other can use/provide. It is most commonly used
            to do Kerberos authentication. It can wrap other mechanisms, however the current version
            in HttpClient is designed solely with Kerberos in mind. </para>
        <sidebar>
            <orderedlist numeration="arabic">
                <listitem>
                    <para>Client Web Browser does HTTP GET for resource.</para>
                </listitem>
                <listitem>
                    <para>Web server returns HTTP 401 status and a header:
                            <literal>WWW-Authenticate: Negotiate</literal></para>
                </listitem>
                <listitem>
                    <para>Client generates a <literal>NegTokenInit</literal>, base64 encodes it, and
                        resubmits the <literal>GET</literal> with an Authorization header:
                            <literal>Authorization: Negotiate &lt;base64
                            encoding&gt;</literal>.</para>
                </listitem>
                <listitem>
                    <para>Server decodes the <literal>NegTokenInit</literal>, extracts the supported
                            <literal>MechTypes</literal> (only Kerberos V5 in our case), ensures it
                        is one of the expected ones, and then extracts the
                            <literal>MechToken</literal> (Kerberos Token) and authenticates
                        it.</para>
                    <para>If more processing is required another HTTP 401 is returned to the client
                        with more data in the the <literal>WWW-Authenticate</literal> header. Client
                        takes the info and generates another token passing this back in the
                            <literal>Authorization</literal> header until complete.</para>
                </listitem>
                <listitem>
                    <para>When the client has been authenticated the Web server should return the
                        HTTP 200 status, a final <literal>WWW-Authenticate</literal> header and the
                        page content.</para>
                </listitem>
            </orderedlist>
        </sidebar>
        <section>
            <title><literal>SPNEGO</literal> support in HttpClient</title>
            <para>The <literal>SPNEGO</literal> authentication scheme is compatible with Sun Java
                versions 1.5 and up. However the use of Java >= 1.6 is strongly recommended as it 
                supports <literal>SPNEGO</literal> authentication more completely.</para>
            <para>The Sun JRE provides the supporting classes to do nearly all the Kerberos and
                    <literal>SPNEGO</literal> token handling. This means that a lot of the setup is
                for the GSS classes. The <classname>SPNegoScheme</classname> is a simple class to
                handle marshalling the tokens and reading and writing the correct headers.</para>
            <para>The best way to start is to grab the <literal>KerberosHttpClient.java</literal>
                file in examples and try and get it to work. There are a lot of issues that can
                happen but if lucky it'll work without too much of a problem. It should also provide some
                output to debug with.</para>

            <para>In Windows it should default to using the logged in credentials; this can be
                overridden by using 'kinit' e.g. <literal>$JAVA_HOME\bin\kinit
                    testuser@AD.EXAMPLE.NET</literal>, which is very helpful for testing and
                debugging issues. Remove the cache file created by kinit to revert back to the windows
                Kerberos cache.</para>
            <para>Make sure to list <literal>domain_realms</literal> in the
                    <literal>krb5.conf</literal> file. This is a major source of problems.</para>
        </section>
        <section>
            <title>GSS/Java Kerberos Setup</title>
            <para>This documentation assumes you are using Windows but much of the information
                applies to Unix as well.</para>
            <para>The <classname>org.ietf.jgss</classname> classes have lots of possible
                configuration parameters, mainly in the
                    <literal>krb5.conf</literal>/<literal>krb5.ini</literal> file. Some more info on
                the format at <ulink
                    url="http://web.mit.edu/kerberos/krb5-1.4/krb5-1.4.1/doc/krb5-admin/krb5.conf.html"
                    >http://web.mit.edu/kerberos/krb5-1.4/krb5-1.4.1/doc/krb5-admin/krb5.conf.html</ulink>.</para>
        </section>
        <section>
            <title><literal>login.conf</literal> file</title>
            <para>The following configuration is a basic setup that works in Windows XP against both
                    <literal>IIS</literal> and <literal>JBoss Negotiation</literal> modules.</para>
            <para>The system property <literal>java.security.auth.login.config</literal> can be used
                to point at the <literal>login.conf</literal> file.</para>
            <para><literal>login.conf</literal> content may look like the following:</para>
            <programlisting><![CDATA[
com.sun.security.jgss.login {
  com.sun.security.auth.module.Krb5LoginModule required client=TRUE useTicketCache=true;
};

com.sun.security.jgss.initiate {
  com.sun.security.auth.module.Krb5LoginModule required client=TRUE useTicketCache=true;
};

com.sun.security.jgss.accept {
  com.sun.security.auth.module.Krb5LoginModule required client=TRUE useTicketCache=true;
};
]]>
</programlisting>
        </section>
        <section>
            <title><literal>krb5.conf</literal> / <literal>krb5.ini</literal> file</title>
            <para>If unspecified, the system default will be used. Override if needed by setting the
                system property <literal>java.security.krb5.conf</literal> to point to a custom
                    <literal>krb5.conf</literal> file.</para>
            <para><literal>krb5.conf</literal> content may look like the following:</para>
            <programlisting><![CDATA[
[libdefaults]
    default_realm = AD.EXAMPLE.NET
    udp_preference_limit = 1
[realms]
    AD.EXAMPLE.NET = {
        kdc = KDC.AD.EXAMPLE.NET
    }
[domain_realms]
.ad.example.net=AD.EXAMPLE.NET
ad.example.net=AD.EXAMPLE.NET
]]>
</programlisting>
        </section>
        <section>
            <title>Windows Specific configuration</title>
            <para>To allow Windows to use the current user's tickets, the system property
                    <literal>javax.security.auth.useSubjectCredsOnly</literal> must be set to
                    <literal>false</literal> and the Windows registry key
                    <literal>allowtgtsessionkey</literal> should be added and set correctly to allow
                session keys to be sent in the Kerberos Ticket-Granting Ticket.</para>
            <para>On the Windows Server 2003 and Windows 2000 SP4, here is the required registry
                setting:</para>
            <programlisting><![CDATA[
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\Kerberos\Parameters
Value Name: allowtgtsessionkey
Value Type: REG_DWORD
Value: 0x01
]]>
            </programlisting>
            <para>Here is the location of the registry setting on Windows XP SP2:</para>
            <programlisting><![CDATA[
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\Kerberos\
Value Name: allowtgtsessionkey
Value Type: REG_DWORD
Value: 0x01
]]>
            </programlisting>
        </section>
    </section>

</chapter>
