Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,9 @@ public AccessTokenProvider getTokenProvider() throws TokenAccessProviderExceptio
String authEndpoint = getPasswordString(FS_AZURE_ACCOUNT_OAUTH_CLIENT_ENDPOINT);
String username = getPasswordString(FS_AZURE_ACCOUNT_OAUTH_USER_NAME);
String password = getPasswordString(FS_AZURE_ACCOUNT_OAUTH_USER_PASSWORD);
tokenProvider = new UserPasswordTokenProvider(authEndpoint, username, password);
String clientId = getPasswordString(FS_AZURE_ACCOUNT_OAUTH_CLIENT_ID);
String clientSecret = getPasswordString(FS_AZURE_ACCOUNT_OAUTH_CLIENT_SECRET);
tokenProvider = new UserPasswordTokenProvider(authEndpoint, username, password, clientId, clientSecret);
LOG.trace("UserPasswordTokenProvider initialized");
} else if (tokenProviderClass == MsiTokenProvider.class) {
String authEndpoint = getTrimmedPasswordString(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,53 @@ public static AzureADToken getTokenFromMsi(final String authEndpoint,
return getTokenCall(authEndpoint, qp.serialize(), headers, "GET", true);
}


/**
* gets Azure Active Directory token using the user's username and password. This only
* works if the identity can be authenticated directly by microsoftonline.com. It will likely
* not work if the domain is federated and/or multi-factor authentication or other form of
* strong authentication is configured for the user.
*
* @param authEndpoint the OAuth 2.0 token endpoint associated
* with the user's directory (obtain from
* Active Directory configuration)
* @param username the user name of the user
* @param password the password of the user
* @param clientId the client ID (GUID) of the client web app
* obtained from Azure Active Directory configuration
* @param clientSecret (optional) the secret key of the client web app
* If the app is a confidential client, then it must be included
* @return {@link AzureADToken} obtained using the creds
* @throws IOException throws IOException if there is a failure in connecting to Azure AD
*/
public static AzureADToken getTokenUsingUserCreds(String authEndpoint,
String username, String password, String clientId,
String clientSecret) throws IOException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like clientSecret is not required. Why are we still passing this?

Preconditions.checkNotNull(authEndpoint, "authEndpoint");
Preconditions.checkNotNull(username, "username");
Preconditions.checkNotNull(password, "password");
Preconditions.checkNotNull(clientId, "clientId");
boolean isVersion2AuthenticationEndpoint = authEndpoint.contains("/oauth2/v2.0/");

QueryParams qp = new QueryParams();
if (isVersion2AuthenticationEndpoint) {
qp.add("scope", SCOPE);
} else {
qp.add("resource", RESOURCE_NAME);
}
qp.add("grant_type", "password");
qp.add("client_id", clientId);
qp.add("username",username);
qp.add("password",password);

if (clientSecret != null && clientSecret.length() > 0) {
qp.add("client_secret", clientSecret);
}

LOG.debug("AADToken: starting to fetch token using username and password");
return getTokenCall(authEndpoint, qp.serialize(), null, null);
}

/**
* Gets Azure Active Directory token using refresh token.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,30 @@ public class UserPasswordTokenProvider extends AccessTokenProvider {

private final String password;

private final String clientId;

private final String clientSecret;

private static final Logger LOG = LoggerFactory.getLogger(AccessTokenProvider.class);

public UserPasswordTokenProvider(final String authEndpoint,
final String username, final String password) {
final String username, final String password,
final String clientId, final String clientSecret) {
Preconditions.checkNotNull(authEndpoint, "authEndpoint");
Preconditions.checkNotNull(username, "username");
Preconditions.checkNotNull(password, "password");
Preconditions.checkNotNull(clientId, "clientId");

this.authEndpoint = authEndpoint;
this.username = username;
this.password = password;
this.clientId = clientId;
this.clientSecret = clientSecret;
}

@Override
protected AzureADToken refreshToken() throws IOException {
LOG.debug("AADToken: refreshing user-password based token");
return AzureADAuthenticator.getTokenUsingClientCreds(authEndpoint, username, password);
return AzureADAuthenticator.getTokenUsingUserCreds(authEndpoint, username, password, clientId, clientSecret);
}
}
14 changes: 14 additions & 0 deletions hadoop-tools/hadoop-azure/src/site/markdown/abfs.md
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,20 @@ An OAuth 2.0 endpoint, username and password are provided in the configuration/J
password for account
</description>
</property>
<property>
<name>fs.azure.account.oauth2.client.id</name>
<value></value>
<description>
Client ID
</description>
</property>
<property>
<name>fs.azure.account.oauth2.client.secret</name>
<value></value>
<description>
Optional Secret
</description>
</property>
```

### <a name="oauth-refresh-token"></a> OAuth 2.0: Refresh Token
Expand Down