In a microservice architecture you probably have an API gateway which is a single entry point for a native mobile app or a HTML5 application. The gateway can forward requests to several microservices and aggregates the results in a single response.

source: http://microservices.io/patterns/apigateway.html

The challenge here is to know which user is logged in at the backing REST services. In case of Kerberos it is possible to delegate the user credentials to these REST services. These microservice can validate the credentials again.

How does this work in Java?

Since Java is enterprise ready there is support for Kerberos since the early days (JDK 1.4) by the GSS-API. However, this API is pretty awkward to use. Luckily there is a kerberos plugin for Spring Security but this plugin has no out of the box support for credential delegation. So I have written some code to create a delegated service ticket: (note that this ticket is also forwardable)

import org.ietf.jgss.*;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.kerberos.authentication.KerberosServiceRequestToken;

import javax.security.auth.Subject;
import java.security.PrivilegedExceptionAction;

public static byte[] createServiceToken(String serviceName) throws Exception {
1.  KerberosServiceRequestToken authentication = (KerberosServiceRequestToken)
       SecurityContextHolder.getContext().getAuthentication();

2.  Subject subject = authentication.getTicketValidation().subject();

3.  return Subject.doAs(subject, (PrivilegedExceptionAction<byte[]>) () -> {
4.      GSSManager manager = GSSManager.getInstance();
5.      GSSName name = manager.createName("HTTP@" + serviceName, GSSName.NT_HOSTBASED_SERVICE);
6.      GSSContext context = manager.createContext(name, 
                                    null, 
                                    authentication.getTicketValidation().getGssContext().getDelegCred(), 
                                    GSSContext.INDEFINITE_LIFETIME);
7.      context.requestCredDeleg(true);
8.      byte[] serviceToken = context.initSecContext(authentication.getToken(), 0, authentication.getToken().length);
9.      context.dispose();
10.     return serviceToken;
    });
}

Some explanation:

  1. Retrieves the KeberosServiceToken from the Spring Security context
  2. Get the current logged in subject
  3. Run the lambda expression as this subject
  4. Get the GSSManager
  5. Create a GSSName for the REST endpoint
  6. Create a new GSSContext for this REST endpoint
  7. Request a forwardable Kerberos token, so the new service ticket is also forwardable
  8. Initiate the secure context with the current Kerberos token to get a new service ticket
  9. Close the context and
  10. Return the new ticket

A colleague of mine also created an extension to the Spring Security Kerberos plugin to delegate the user credentials to an LDAP server. So, there is no need to use a bind user (with special permissions) anymore. The major advantage is that you can create an audit trail of any user logged in to your systems.