Posts Java retrieve kerberos ticket
Post
Cancel

Java retrieve kerberos ticket

  • All imports
1
2
3
4
5
6
7
8
9
10
import org.apache.xmlbeans.impl.util.Base64;
import org.ietf.jgss.*;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.security.PrivilegedAction;
  • Code to generate temporary keytab file
1
2
3
4
5
6
7
8
9
10
11
    private File generateKrb5Conf() throws IOException {
        final File temporaryKrb5Conf = File.createTempFile("krb5.conf", null);
        final PrintStream printStream = new PrintStream(new FileOutputStream(temporaryKrb5Conf));
        printStream.print(String.format(
                "[libdefaults]\n" +
                        "default_realm = YOUR_ORG_DOMAIN"
        ));
        printStream.close();
        temporaryKrb5Conf.deleteOnExit();
        return temporaryKrb5Conf;
    }
  • Code to generate temporary jass login file
1
2
3
4
5
6
7
8
9
10
11
    private File generateJaasConf() throws IOException {
        final File jaasConfFile = File.createTempFile("jaas.conf", null);
        final PrintStream printStream = new PrintStream(new FileOutputStream(jaasConfFile));
        // KRB5
        printStream.print(String.format("Krb5LoginContext { com.sun.security.auth.module.Krb5LoginModule required refreshKrb5Config=true useTicketCache=true debug=true ; };"));
        //For SQLServer Kerberos Login
        //printStream.print(String.format("SQLSERVER { com.sun.security.auth.module.Krb5LoginModule required refreshKrb5Config=true useTicketCache=true debug=true ; };"));
        printStream.close();
        jaasConfFile.deleteOnExit();
        return jaasConfFile;
    }
  • Code to configure Kerberos system parameters
1
2
3
4
5
6
7
    private void configureKerberosSystemParameters() throws IOException {
        System.setProperty("java.security.krb5.conf", generateKrb5Conf().getAbsolutePath());
        System.setProperty("java.security.auth.login.config", generateJaasConf().getAbsolutePath());
        System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
        System.setProperty("sun.security.krb5.debug", "true");
        System.setProperty("sun.security.jgss.debug", "true");
    }
  • Code to pass credentials
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import javax.security.auth.callback.*;
import java.io.IOException;

public class CredentialsCallbackHandler implements CallbackHandler {
    private final String username = "USER_NAME";
    private final String password = "PASSWORD";

    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        for (Callback callback : callbacks) {
            if (callback instanceof NameCallback) {
                NameCallback nameCallback = (NameCallback) callback;
                nameCallback.setName(username);
            } else if (callback instanceof PasswordCallback) {
                PasswordCallback passwordCallback = (PasswordCallback) callback;
                passwordCallback.setPassword(password.toCharArray());
            } else throw new UnsupportedCallbackException(callback, "Unrecognised callback");
        }
    }
}
  • Code to get kerberos ticket
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
public class KerberosTicket implements PrivilegedAction {
        private final String serverName;
        private String ticket;
        private String userPrincipal;

        private KerberosTicket(final String serverName) {
            this.serverName = serverName;
        }

        public Object run() {
            try {
                this.ticket = loginAndGetTicketDetailsAsString();
            } catch (Exception e) {
                e.printStackTrace();
                this.ticket = "";
            }
            return this.ticket;
        }

        private String loginAndGetTicketDetailsAsString() throws GSSException {
            final Oid krb5PrincipalNameOid = new Oid("1.2.840.113554.1.2.2.1");
            final GSSManager manager = GSSManager.getInstance();
            final GSSName clientName = manager.createName(userPrincipal, krb5PrincipalNameOid);
            final Oid Krb5_v5_oid = new Oid("1.2.840.113554.1.2.2");
            final int ticketValidFor = 8 * 3600;
            final GSSCredential clientCred = manager.createCredential(clientName,
                    ticketValidFor,
                    Krb5_v5_oid,
                    GSSCredential.INITIATE_ONLY);
            final GSSContext context = manager.createContext(manager.createName(serverName, krb5PrincipalNameOid),
                    Krb5_v5_oid,
                    clientCred,
                    GSSContext.DEFAULT_LIFETIME);
            context.requestMutualAuth(true);
            context.requestConf(false);
            context.requestInteg(true);

            try {
                final byte[] retrieveToken = context.initSecContext(new byte[0], 0, 0);
                return generateOutputString(context, retrieveToken);
            } finally {
                context.dispose();
            }
        }

        private String generateOutputString(GSSContext context, byte[] retrieveToken) throws GSSException {
            StringBuilder stringBuilder = new StringBuilder("Context Source Name is ")
                    .append("[")
                    .append(context.getSrcName())
                    .append("]")
                    .append(System.lineSeparator())
                    .append("Context Target Name is ")
                    .append("[")
                    .append(context.getTargName())
                    .append("]")
                    .append(System.lineSeparator())
                    .append("Token is ")
                    .append("[")
                    .append(new Base64().encode(retrieveToken))
                    .append("]");
            return stringBuilder.toString();
        }

        public String getTicketDetails() throws LoginException, IOException {
            final Subject subject = new Subject();
            final LoginContext loginContext = new LoginContext("Krb5LoginContext", subject, new CredentialsCallbackHandler());
            loginContext.login();

            if (subject.getPrincipals().size() == 1) {
                this.userPrincipal = subject.getPrincipals().stream().findFirst().get().getName();
                Subject.doAsPrivileged(loginContext.getSubject(), this, null);
                return ticket;
            } else {
                throw new AssertionError("Either zero or multiple principals found: " + subject.getPrincipals());
            }
        }
    }
  • Call the above code to test that ticket is obtained
1
2
  configureKerberosSystemParameters();
  System.out.println(new KerberosTicket("SERVER Name").getTicketDetails());
This post is licensed under CC BY 4.0 by the author.