[ 
https://issues.apache.org/jira/browse/HTTPCLIENT-1912?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16577144#comment-16577144
 ] 

Nicholas DiPiazza edited comment on HTTPCLIENT-1912 at 8/11/18 8:27 PM:
------------------------------------------------------------------------

The following example shows how you can do preemptive spnego login with HTTP 
client that uses a custom entry in the {{login.conf}}. This completely bypasses 
the AuthScheme stuff and does all the work of generating the "authorization" 
header. So you will notice the example is just a simple minimal http client 
with a single header on the httpget request doing all the authentication work.

{code}
... better version below ...
{code}

Might be worth trying to find some way to get this as a supported auth scheme 
type, or add this example to the docs. 


was (Author: ndipiazza_gmail):
The following example shows how you can do preemptive spnego login with HTTP 
client that uses a custom entry in the {{login.conf}}. This completely bypasses 
the AuthScheme stuff and does all the work of generating the "authorization" 
header. So you will notice the example is just a simple minimal http client 
with a single header on the httpget request doing all the authentication work.

{code}
import org.apache.commons.io.IOUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.GSSName;
import org.ietf.jgss.Oid;

import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import java.io.File;
import java.net.InetAddress;
import java.security.PrivilegedExceptionAction;
import java.util.Base64;

public class AsyncHttpSpnego {

  public static final String SPNEGO_OID = "1.3.6.1.5.5.2";
  private static final String KERBEROS_OID = "1.2.840.113554.1.2.2";

  public static void main(String[] args) throws Exception {

    InetAddress inetAddress = InetAddress.getLocalHost();

    String host = inetAddress.getHostName().toUpperCase();

    System.setProperty("java.security.krb5.conf", new File(host + 
"-krb5.ini").getCanonicalPath());
    System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
    System.setProperty("java.security.auth.login.config", new File(host + 
"-login.conf").getCanonicalPath());
    LoginContext lc = new LoginContext("anotherentry");
    lc.login();
    byte[] token = new byte[0];

    token = getAuthToken(host, lc, token);

    String authorizationHeader = "Negotiate" + " " + 
Base64.getEncoder().encodeToString(token);

    System.out.println("Next Authorization header: " + authorizationHeader);

    CloseableHttpClient closeableHttpClient = HttpClients.createMinimal();
    HttpGet httpget = new HttpGet("http://"; + host + ":81/nick.txt");
    httpget.setHeader("Authorization", authorizationHeader);
    CloseableHttpResponse closeableHttpResponse = 
closeableHttpClient.execute(httpget);
    try {
      
System.out.println(IOUtils.toString(closeableHttpResponse.getEntity().getContent()));
    } finally {
      closeableHttpResponse.close();
    }
  }

  private static byte[] getAuthToken(String host, LoginContext lc, byte[] 
inToken) throws GSSException, java.security.PrivilegedActionException {
    Oid negotiationOid = new Oid(SPNEGO_OID);

    GSSManager manager = GSSManager.getInstance();
    final PrivilegedExceptionAction<GSSCredential> action = () -> 
manager.createCredential(null,
        GSSCredential.INDEFINITE_LIFETIME, negotiationOid, 
GSSCredential.INITIATE_AND_ACCEPT);

    boolean tryKerberos = false;
    GSSContext gssContext = null;
    try {
      GSSName serverName = manager.createName("HTTP@" + host, 
GSSName.NT_HOSTBASED_SERVICE);
      gssContext = 
manager.createContext(serverName.canonicalize(negotiationOid), negotiationOid, 
Subject.doAs(lc.getSubject(), action),
          GSSContext.DEFAULT_LIFETIME);
      gssContext.requestMutualAuth(true);
      gssContext.requestCredDeleg(true);
    } catch (GSSException ex) {
      if (ex.getMajor() == GSSException.BAD_MECH) {
        System.out.println("GSSException BAD_MECH, retry with Kerberos MECH");
        tryKerberos = true;
      } else {
        throw ex;
      }
    }
    if (tryKerberos) {
      Oid kerbOid = new Oid(KERBEROS_OID);
      GSSName serverName = manager.createName("HTTP@" + host, 
GSSName.NT_HOSTBASED_SERVICE);
      gssContext = manager.createContext(serverName.canonicalize(kerbOid), 
kerbOid, Subject.doAs(lc.getSubject(), action),
          GSSContext.DEFAULT_LIFETIME);
      gssContext.requestMutualAuth(true);
      gssContext.requestCredDeleg(true);
    }

    return gssContext.initSecContext(inToken, 0, inToken.length);
  }
}
{code}

Might be worth trying to find some way to get this as a supported auth scheme 
type, or add this example to the docs. 

> AuthSchemes.SPNEGO should be able to specify login conf and krb5 conf as 
> parameters instead of system properties
> ----------------------------------------------------------------------------------------------------------------
>
>                 Key: HTTPCLIENT-1912
>                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-1912
>             Project: HttpComponents HttpClient
>          Issue Type: Improvement
>          Components: HttpClient (classic)
>    Affects Versions: 4.5.2
>            Reporter: Nicholas DiPiazza
>            Priority: Major
>              Labels: volunteers-wanted
>             Fix For: Stuck
>
>
> in order to use spenego 
> see 
> [example|https://github.com/jumarko/kerberos-auth-example/blob/master/src/main/java/net/curiousprogrammer/auth/kerberos/example/KerberosAuthExample.java]
> you need to specify system properties to specify a custom krb5.conf or 
> login.conf location.
> It would be very useful if these could be given as parameters somehow instead 
> of system properties, because in our cloud apps use case, sharing these as 
> system properties at the jvm level is causing conflicts. 



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@hc.apache.org
For additional commands, e-mail: dev-h...@hc.apache.org

Reply via email to