Constrained delegation is a Kerberos mechanism that allows a client application to delegate authentication to a second service. The client application informs the KDC that the second service is authorized to act on behalf of a specified Kerberos security principal, such as a user that has an Active Directory account. The second service can then delegate authentication to a database service principal name. (Refer to the Microsoft TechNet page About Kerberos constrained delegation for further details.)
To enable constrained delegation:
Important: Before you start, in the [libdefaults] section of the krb5.conf file, set the forwardable flag to true.
1. Authenticate the service principal and get a subject from the login context. The service principal needs a Kerberos granting ticket to be authenticated. You can use either a ticket cache or keytab file for the authentication step. The section you define in your JAAS login configuration file determines which method is used for authentication.
2. Call the impersonate method to generate the service ticket for the database user on behalf of the service principal identity.
3. Using the driver's GSSCredential property, specify the GSSCredential generated in the previous steps.
4. Call the driver's connect() method using the Properties object. The Properties object must contain the GSSCredential property and any additional properties needed to establish a connection to the database.
The following example code shows how a GSS credential object can be integrated into a client application to support constrained delegation.
Subject serviceSubject;
GSSCredential creds;
//Authenticate the service principal and get a subject from the login context.
LoginContext lc = new LoginContext("entry_from_your_jaas_config");
lc.login();
serviceSubject = lc.getSubject();
//Call the impersonate method to generate the service ticket for database user
//on behalf of the service principal identity.
try {
creds = Subject.doAs(serviceSubject, new PrivilegedExceptionAction<GSSCredential>() {
public GSSCredential run() throws Exception {
GSSManager manager = GSSManager.getInstance();
if (serviceCredentials == null) {
serviceCredentials = manager.createCredential(GSSCredential.INITIATE_ONLY);
}
GSSName other = manager.createName("userToImpersonate",GSSName.NT_USER_NAME);
return ((ExtendedGSSCredential)serviceCredentials).impersonate(other);
}
});
} catch (PrivilegedActionException pae) {
throw pae.getException();
}
final Properties sqlserverProperties;
sqlserverProperties = new Properties();
// Set the driver's GSSCredential property and the rest of the database
// connection properties
sqlserverProperties.put("GSSCredential", creds);
sqlserverProperties.put("ServerName", "yourServer");
sqlserverProperties.put("portNumber", "1433");
sqlserverProperties.put("authenticationMethod", "Kerberos");
sqlserverProperties.put("databaseName", "yourDatabase");
Connection con = DriverManager.getConnection("jdbc:datadirect:sqlserver:",sqlserverProperties);
DatabaseMetaData dbmd = con.getMetaData();