package com.hclsoftware.sso.kerberos.controller;

import org.ietf.jgss.*;

import javax.security.auth.login.LoginException;
import java.io.IOException;
import java.security.PrivilegedAction;

//Code to get kerberos ticket
public class KerberosTicket implements PrivilegedAction {

	private final String serverName;
	private String ticket;
	private String userPrincipal;

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

	@Override
	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());
		}*/
		return null;
	}

}
