JMS
JMS

Reputation: 13

Generate SPNEGO Token Failured

I tried to generate the token which can be used as the HTTP header to authenticate to the HDFS WebHDFS URL and Oozie REST API URL. I referenced the url below to have the below code to generate the Negotiate token. https://www.ibm.com/support/knowledgecenter/en/SS7JFU_8.5.5/com.ibm.websphere.express.doc/ae/tsec_SPNEGO_token.html

public class TokenCreation {
  private 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 byte[] genToken(String principal) {
    System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
    byte[] spnegoToken = new byte[0];
    try {
      Oid spnegoMechOid = new Oid(SPNEGO_OID);
      Oid krb5MechOid = new Oid(KERBEROS_OID);
      GSSCredential clientGssCreds = null;
      GSSManager manager = GSSManager.getInstance();
      GSSName gssUserName = manager.createName(principal, GSSName.NT_USER_NAME, krb5MechOid);
      clientGssCreds = manager.createCredential(gssUserName.canonicalize(krb5MechOid),
          GSSCredential.INDEFINITE_LIFETIME,
          krb5MechOid,
          GSSCredential.INITIATE_ONLY);
      clientGssCreds.add(gssUserName,
          GSSCredential.INDEFINITE_LIFETIME,
          GSSCredential.INDEFINITE_LIFETIME,
          spnegoMechOid, GSSCredential.INITIATE_ONLY);
      GSSName gssServerName = manager.createName(principal, GSSName.NT_USER_NAME);
      GSSContext clientContext = manager.createContext(gssServerName.canonicalize(spnegoMechOid),
          spnegoMechOid,
          clientGssCreds,
          GSSContext.DEFAULT_LIFETIME);
      // optional enable GSS credential delegation
      clientContext.requestCredDeleg(true);
      // create a SPNEGO token for the target server
      spnegoToken = clientContext.initSecContext(spnegoToken, 0, spnegoToken.length);
    } catch (GSSException e) {
      e.printStackTrace();
    }
    return spnegoToken;
  }

But after running the above code, I always got the below prompt:

2019-09-25 14:12:51 760 [INFO] [pool-2-thread-1] c.s.n.c.u.security.KrbUtils - after loginUserFromKeytab............AtoimcUser:HTTP/[email protected]
2019-09-25 14:12:51 760 [INFO] [pool-2-thread-1] c.s.n.app.oozie.OozieAppCaller - ->>>>>>User Name is HTTP/[email protected]
2019-09-25 14:12:51 760 [INFO] [pool-2-thread-1] c.s.n.app.oozie.OozieAppCaller - ->>>>>>Mode is KERBEROS
>>>KinitOptions cache name is /tmp/krb5cc_0
Kerberos username [root]: ^C^C^C
Kerberos password for root:

You can see at the end of the above output log. The "Kerberos username" is always prompt to ask for username.

Also I have tried to manually run kinit the keytab. and the above class can generate the token successfully. But manually run kinit is NOT the way I wanted.

Would you please help it? Thanks.

Upvotes: 0

Views: 1058

Answers (1)

bedrin
bedrin

Reputation: 4586

Kerberos and SPNEGO support in Java is cumbersome unfortunately.

I've created a small library to simplify some Kerberos use cases: https://github.com/bedrin/kerb4j You can use it like this to generate SPNEGO token:

SpnegoClient spnegoClient = SpnegoClient.loginWithKeyTab("svc_consumer", "/opt/myapp/consumer.keytab");
URL url = new URL("http://api.provider.acme.com/api/operation1");
SpnegoContext context = spnegoClient.createContext("http://provider.acme.com"); // Will result in HTTP/provider.acme.com SPN
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", context.createTokenAsAuthroizationHeader());

Upvotes: 1

Related Questions