Skip to content
This repository was archived by the owner on Jun 15, 2026. It is now read-only.
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,32 @@
import com.microsoft.aad.adal4j.ClientCredential;
import com.microsoft.azure.AzureEnvironment;
import com.microsoft.rest.credentials.TokenCredentials;
import okhttp3.OkHttpClient;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* Token based credentials for use with a REST Service Client.
*/
public class ApplicationTokenCredentials extends TokenCredentials {
public class ApplicationTokenCredentials extends TokenCredentials implements AzureTokenCredentials {
/** A mapping from resource endpoint to its cached access token. */
private Map<String, AuthenticationResult> tokens;
/** The Azure environment to authenticate with. */
private AzureEnvironment environment;
/** The active directory application client id. */
private String clientId;
/** The tenant or domain the containing the application. */
private String domain;
/** The authentication secret for the application. */
private String secret;
/** The Azure environment to authenticate with. */
private AzureEnvironment environment;
/** The current authentication result. */
private AuthenticationResult authenticationResult;
/** The default subscription to use, if any. */
private String defaultSubscription;

Expand All @@ -48,14 +52,11 @@ public class ApplicationTokenCredentials extends TokenCredentials {
*/
public ApplicationTokenCredentials(String clientId, String domain, String secret, AzureEnvironment environment) {
super(null, null); // defer token acquisition
this.environment = environment;
this.clientId = clientId;
this.domain = domain;
this.secret = secret;
if (environment == null) {
this.environment = AzureEnvironment.AZURE;
} else {
this.environment = environment;
}
this.tokens = new HashMap<>();
}

/**
Expand Down Expand Up @@ -129,7 +130,7 @@ public static ApplicationTokenCredentials fromFile(File credentialsFile) throws
Properties authSettings = new Properties();
authSettings.put(CredentialSettings.AUTH_URL.toString(), AzureEnvironment.AZURE.getAuthenticationEndpoint());
authSettings.put(CredentialSettings.BASE_URL.toString(), AzureEnvironment.AZURE.getBaseUrl());
authSettings.put(CredentialSettings.MANAGEMENT_URI.toString(), AzureEnvironment.AZURE.getTokenAudience());
authSettings.put(CredentialSettings.MANAGEMENT_URI.toString(), AzureEnvironment.AZURE.getManagementEndpoint());

// Load the credentials from the file
FileInputStream credentialsFileStream = new FileInputStream(credentialsFile);
Expand All @@ -151,8 +152,8 @@ public static ApplicationTokenCredentials fromFile(File credentialsFile) throws
new AzureEnvironment(
authUrl,
mgmtUri,
true,
baseUrl)
baseUrl,
"https://graph.windows.net/") // TODO: cred file should contain GRAPH endpoint
).withDefaultSubscriptionId(defaultSubscriptionId);
}

Expand All @@ -170,6 +171,7 @@ public String getClientId() {
*
* @return the tenant or domain the containing the application.
*/
@Override
public String getDomain() {
return domain;
}
Expand All @@ -183,42 +185,40 @@ public String getSecret() {
return secret;
}

/**
* Gets the Azure environment to authenticate with.
*
* @return the Azure environment to authenticate with.
*/
public AzureEnvironment getEnvironment() {
return environment;
}

@Override
public String getToken() throws IOException {
if (authenticationResult == null
|| authenticationResult.getAccessToken() == null) {
acquireAccessToken();
public String getToken(String resource) throws IOException {
AuthenticationResult authenticationResult = tokens.get(resource);
if (authenticationResult == null || authenticationResult.getExpiresOnDate().before(new Date())) {
authenticationResult = acquireAccessToken(resource);
}
return authenticationResult.getAccessToken();
}

@Override
public void refreshToken() throws IOException {
acquireAccessToken();
public AzureEnvironment getEnvironment() {
return this.environment;
}

private void acquireAccessToken() throws IOException {
private AuthenticationResult acquireAccessToken(String resource) throws IOException {
String authorityUrl = this.getEnvironment().getAuthenticationEndpoint() + this.getDomain();
ExecutorService executor = Executors.newSingleThreadExecutor();
AuthenticationContext context = new AuthenticationContext(authorityUrl, this.getEnvironment().isValidateAuthority(), executor);
try {
authenticationResult = context.acquireToken(
this.getEnvironment().getTokenAudience(),
AuthenticationResult result = context.acquireToken(
resource,
new ClientCredential(this.getClientId(), this.getSecret()),
null).get();
tokens.put(resource, result);
return result;
} catch (Exception e) {
throw new IOException(e.getMessage(), e);
} finally {
executor.shutdown();
}
}

@Override
public void applyCredentialsFilter(OkHttpClient.Builder clientBuilder) {
clientBuilder.interceptors().add(new AzureTokenCredentialsInterceptor(this));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,21 @@
import com.microsoft.aad.adal4j.AuthenticationResult;
import com.microsoft.azure.AzureEnvironment;
import com.microsoft.rest.credentials.TokenCredentials;
import okhttp3.OkHttpClient;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
* Token based credentials for use with a REST Service Client.
*/
public class UserTokenCredentials extends TokenCredentials {
public class UserTokenCredentials extends TokenCredentials implements AzureTokenCredentials {
/** A mapping from resource endpoint to its cached access token. */
private Map<String, AuthenticationResult> tokens;
/** The Active Directory application client id. */
private String clientId;
/** The domain or tenant id containing this application. */
Expand All @@ -29,12 +34,8 @@ public class UserTokenCredentials extends TokenCredentials {
private String username;
/** The password for the Organization Id account. */
private String password;
/** The Uri where the user will be redirected after authenticating with AD. */
private String clientRedirectUri;
/** The Azure environment to authenticate with. */
private AzureEnvironment environment;
/** The current authentication result. */
private AuthenticationResult authenticationResult;

/**
* Initializes a new instance of the UserTokenCredentials.
Expand All @@ -43,22 +44,17 @@ public class UserTokenCredentials extends TokenCredentials {
* @param domain the domain or tenant id containing this application.
* @param username the user name for the Organization Id account.
* @param password the password for the Organization Id account.
* @param clientRedirectUri the Uri where the user will be redirected after authenticating with AD.
* @param environment the Azure environment to authenticate with.
* If null is provided, AzureEnvironment.AZURE will be used.
*/
public UserTokenCredentials(String clientId, String domain, String username, String password, String clientRedirectUri, AzureEnvironment environment) {
public UserTokenCredentials(String clientId, String domain, String username, String password, AzureEnvironment environment) {
super(null, null); // defer token acquisition
this.clientId = clientId;
this.domain = domain;
this.username = username;
this.password = password;
this.clientRedirectUri = clientRedirectUri;
if (environment == null) {
this.environment = AzureEnvironment.AZURE;
} else {
this.environment = environment;
}
this.environment = environment;
this.tokens = new HashMap<>();
}

/**
Expand All @@ -75,6 +71,7 @@ public String getClientId() {
*
* @return the tenant or domain the containing the application.
*/
@Override
public String getDomain() {
return domain;
}
Expand All @@ -97,13 +94,13 @@ public String getPassword() {
return password;
}

/**
* Gets the Uri where the user will be redirected after authenticating with AD.
*
* @return the redirecting Uri.
*/
public String getClientRedirectUri() {
return clientRedirectUri;
@Override
public String getToken(String resource) throws IOException {
AuthenticationResult authenticationResult = tokens.get(resource);
if (authenticationResult == null || authenticationResult.getExpiresOnDate().before(new Date())) {
authenticationResult = acquireAccessToken(resource);
}
return authenticationResult.getAccessToken();
}

/**
Expand All @@ -115,50 +112,47 @@ public AzureEnvironment getEnvironment() {
return environment;
}

@Override
public String getToken() throws IOException {
if (authenticationResult != null
&& authenticationResult.getExpiresOnDate().before(new Date())) {
acquireAccessTokenFromRefreshToken();
} else {
acquireAccessToken();
}
return authenticationResult.getAccessToken();
}

@Override
public void refreshToken() throws IOException {
acquireAccessToken();
}

private void acquireAccessToken() throws IOException {
private AuthenticationResult acquireAccessToken(String resource) throws IOException {
String authorityUrl = this.getEnvironment().getAuthenticationEndpoint() + this.getDomain();
AuthenticationContext context = new AuthenticationContext(authorityUrl, this.getEnvironment().isValidateAuthority(), Executors.newSingleThreadExecutor());
ExecutorService executor = Executors.newSingleThreadExecutor();
AuthenticationContext context = new AuthenticationContext(authorityUrl, this.getEnvironment().isValidateAuthority(), executor);
try {
authenticationResult = context.acquireToken(
this.getEnvironment().getTokenAudience(),
AuthenticationResult result = context.acquireToken(
resource,
this.getClientId(),
this.getUsername(),
this.getPassword(),
null).get();
tokens.put(resource, result);
return result;
} catch (Exception e) {
throw new IOException(e.getMessage(), e);
} finally {
executor.shutdown();
}
}

private void acquireAccessTokenFromRefreshToken() throws IOException {
// Refresh tokens are currently not used since we don't know if the refresh token has expired
private AuthenticationResult acquireAccessTokenFromRefreshToken(String resource) throws IOException {
String authorityUrl = this.getEnvironment().getAuthenticationEndpoint() + this.getDomain();
ExecutorService executor = Executors.newSingleThreadExecutor();
AuthenticationContext context = new AuthenticationContext(authorityUrl, this.getEnvironment().isValidateAuthority(), executor);
try {
authenticationResult = context.acquireTokenByRefreshToken(
authenticationResult.getRefreshToken(),
AuthenticationResult result = context.acquireTokenByRefreshToken(
tokens.get(resource).getRefreshToken(),
this.getClientId(),
null, null).get();
tokens.put(resource, result);
return result;
} catch (Exception e) {
throw new IOException(e.getMessage(), e);
} finally {
executor.shutdown();
}
}

@Override
public void applyCredentialsFilter(OkHttpClient.Builder clientBuilder) {
clientBuilder.interceptors().add(new AzureTokenCredentialsInterceptor(this));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ public class UserTokenCredentialsTests {
"domain",
"username",
"password",
"redirect",
AzureEnvironment.AZURE
);

Expand All @@ -36,8 +35,8 @@ public void testAcquireToken() throws Exception {
public static class MockUserTokenCredentials extends UserTokenCredentials {
private AuthenticationResult authenticationResult;

public MockUserTokenCredentials(String clientId, String domain, String username, String password, String clientRedirectUri, AzureEnvironment environment) {
super(clientId, domain, username, password, clientRedirectUri, environment);
public MockUserTokenCredentials(String clientId, String domain, String username, String password, AzureEnvironment environment) {
super(clientId, domain, username, password, environment);
}

@Override
Expand Down
Loading