Skip to content

Commit

Permalink
Feature | Active Directory MSI Authentication support (#838)
Browse files Browse the repository at this point in the history
  • Loading branch information
cheenamalhotra authored Dec 25, 2018
1 parent 33bbc84 commit 3f9635a
Show file tree
Hide file tree
Showing 11 changed files with 369 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ static boolean isDllLoaded() {
enabled = true;
} catch (UnsatisfiedLinkError e) {
temp = e;
authLogger.warning("Failed to load the sqljdbc_auth.dll cause : " + e.getMessage());
// This is not re-thrown on purpose - the constructor will terminate the properly with the appropriate error
// string
} finally {
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/microsoft/sqlserver/jdbc/IOBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ final class TDS {
static final int TDS_FEDAUTH_LIBRARY_RESERVED = 0x7F;
static final byte ADALWORKFLOW_ACTIVEDIRECTORYPASSWORD = 0x01;
static final byte ADALWORKFLOW_ACTIVEDIRECTORYINTEGRATED = 0x02;
static final byte ADALWORKFLOW_ACTIVEDIRECTORYMSI = 0x03;
static final byte FEDAUTH_INFO_ID_STSURL = 0x01; // FedAuthInfoData is token endpoint URL from which to acquire fed
// auth token
static final byte FEDAUTH_INFO_ID_SPN = 0x02; // FedAuthInfoData is the SPN to use for acquiring fed auth token
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -805,4 +805,19 @@ public interface ISQLServerDataSource extends javax.sql.CommonDataSource {
* indicates whether Bulk Copy API should be used for Batch Insert operations.
*/
public void setUseBulkCopyForBatchInsert(boolean useBulkCopyForBatchInsert);

/**
* Sets the client id to be used to retrieve access token from MSI EndPoint.
*
* @param msiClientId
* Client ID of User Assigned Managed Identity
*/
public void setMSIClientId(String msiClientId);

/**
* Returns the value for the connection property 'msiClientId'.
*
* @return msiClientId property value
*/
public String getMSIClientId();
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,26 @@ static SqlFedAuthToken getSqlFedAuthToken(SqlFedAuthInfo fedAuthInfo, String use
ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID, user, password, null);

AuthenticationResult authenticationResult = future.get();
SqlFedAuthToken fedAuthToken = new SqlFedAuthToken(authenticationResult.getAccessToken(),
authenticationResult.getExpiresOnDate());

return fedAuthToken;
return new SqlFedAuthToken(authenticationResult.getAccessToken(), authenticationResult.getExpiresOnDate());
} catch (MalformedURLException | InterruptedException e) {
throw new SQLServerException(e.getMessage(), e);
} catch (ExecutionException e) {
MessageFormat form = new MessageFormat(SQLServerException.getErrString("R_ADALExecution"));
Object[] msgArgs = {user, authenticationString};

// the cause error message uses \\n\\r which does not give correct format
// change it to \r\n to provide correct format
/*
* the cause error message uses \\n\\r which does not give correct format change it to \r\n to provide
* correct format
*/
String correctedErrorMessage = e.getCause().getMessage().replaceAll("\\\\r\\\\n", "\r\n");
AuthenticationException correctedAuthenticationException = new AuthenticationException(
correctedErrorMessage);

// SQLServerException is caused by ExecutionException, which is caused by
// AuthenticationException
// to match the exception tree before error message correction
/*
* SQLServerException is caused by ExecutionException, which is caused by AuthenticationException to match
* the exception tree before error message correction
*/
ExecutionException correctedExecutionException = new ExecutionException(correctedAuthenticationException);

throw new SQLServerException(form.format(msgArgs), null, 0, correctedExecutionException);
Expand All @@ -69,8 +70,10 @@ static SqlFedAuthToken getSqlFedAuthTokenIntegrated(SqlFedAuthInfo fedAuthInfo,
ExecutorService executorService = Executors.newFixedThreadPool(1);

try {
// principal name does not matter, what matters is the realm name
// it gets the username in principal_name@realm_name format
/*
* principal name does not matter, what matters is the realm name it gets the username in
* principal_name@realm_name format
*/
KerberosPrincipal kerberosPrincipal = new KerberosPrincipal("username");
String username = kerberosPrincipal.getName();

Expand All @@ -83,10 +86,8 @@ static SqlFedAuthToken getSqlFedAuthTokenIntegrated(SqlFedAuthInfo fedAuthInfo,
ActiveDirectoryAuthentication.JDBC_FEDAUTH_CLIENT_ID, username, null, null);

AuthenticationResult authenticationResult = future.get();
SqlFedAuthToken fedAuthToken = new SqlFedAuthToken(authenticationResult.getAccessToken(),
authenticationResult.getExpiresOnDate());

return fedAuthToken;
return new SqlFedAuthToken(authenticationResult.getAccessToken(), authenticationResult.getExpiresOnDate());
} catch (InterruptedException | IOException e) {
throw new SQLServerException(e.getMessage(), e);
} catch (ExecutionException e) {
Expand All @@ -97,15 +98,18 @@ static SqlFedAuthToken getSqlFedAuthTokenIntegrated(SqlFedAuthInfo fedAuthInfo,
// the case when Future's outcome has no AuthenticationResult but exception
throw new SQLServerException(form.format(msgArgs), null);
} else {
// the cause error message uses \\n\\r which does not give correct format
// change it to \r\n to provide correct format
/*
* the cause error message uses \\n\\r which does not give correct format change it to \r\n to provide
* correct format
*/
String correctedErrorMessage = e.getCause().getMessage().replaceAll("\\\\r\\\\n", "\r\n");
AuthenticationException correctedAuthenticationException = new AuthenticationException(
correctedErrorMessage);

// SQLServerException is caused by ExecutionException, which is caused by
// AuthenticationException
// to match the exception tree before error message correction
/*
* SQLServerException is caused by ExecutionException, which is caused by AuthenticationException to
* match the exception tree before error message correction
*/
ExecutionException correctedExecutionException = new ExecutionException(
correctedAuthenticationException);

Expand Down
Loading

0 comments on commit 3f9635a

Please sign in to comment.