Constrained delegation
- Last Updated: May 14, 2024
- 2 minute read
- DataDirect Connectors
- JDBC
- Microsoft SQL Server 6.0
- Documentation
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 Entra ID 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.- 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.
- Call the impersonate method to generate the service ticket for the database user on behalf of the service principal identity.
- Using the driver's GSSCredential property, specify the GSSCredential generated in the previous steps.
- 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();
System.out.println( "\nConnected with " + dbmd.getDriverName() + "\n"
+ " to " + dbmd.getDatabaseProductName() + "\n"
+ " " + dbmd.getDatabaseProductVersion() + "\n"
+ " " + dbmd.getDriverVersion() + "\n");