msgraph-sdk-java
msgraph-sdk-java copied to clipboard
Configuring GraphServiceClient with no scope throws UnsupportedOperationException during runtime
Expected behavior
Initializing GraphServiceClient with no scope argument should default to scope https://graph.microsoft.com/.default when using azure-identity TokenCredential and fetch the token
Actual behavior
Attempt to fetch Azure token fails with UnsupportedOperationException during runtime
Steps to reproduce the behavior
Java version:
openjdk version "17.0.10" 2024-01-16
OpenJDK Runtime Environment Temurin-17.0.10+7 (build 17.0.10+7)
OpenJDK 64-Bit Server VM Temurin-17.0.10+7 (build 17.0.10+7, mixed mode, sharing)
Include on classpath:
<dependency>
<groupId>com.microsoft.graph</groupId>
<artifactId>microsoft-graph</artifactId>
<version>6.4.0</version>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
<version>1.11.3</version>
</dependency>
Implement the following code:
public class MsGraphConsumer {
private final GraphServiceClient graphClient;
public MsGraphConsumer(AzureProperties azureProperties) {
ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder()
.tenantId(azureProperties.appTenantId())
.clientId(azureProperties.appClientId())
.clientSecret(azureProperties.appClientSecret())
.build();
this.graphClient = new GraphServiceClient(clientSecretCredential);
}
public Optional<User> getUser(String orgInternalId) {
try {
List<User> res = graphClient
.users()
.get(requestConfiguration -> {
requestConfiguration.headers.add("ConsistencyLevel", "eventual");
requestConfiguration.queryParameters.filter = "onPremisesSamAccountName eq '" + orgInternalId + "'";
requestConfiguration.queryParameters.count = true;
requestConfiguration.queryParameters.select = new String[]{"id"};
}).getValue();
if (res.isEmpty()) {
return Optional.empty();
}
return Optional.of(res.get(0));
} catch (ApiException e) {
throw e;
}
}
}
Execute the method msGraphConsumer.getUser("hello"). Observe the following stacktrace:
java.lang.UnsupportedOperationException: null
at java.base/java.util.AbstractList.add(AbstractList.java:153)
at java.base/java.util.AbstractList.add(AbstractList.java:111)
at com.microsoft.kiota.authentication.AzureIdentityAccessTokenProvider.getAuthorizationToken(AzureIdentityAccessTokenProvider.java:133)
at com.microsoft.kiota.authentication.BaseBearerTokenAuthenticationProvider.authenticateRequest(BaseBearerTokenAuthenticationProvider.java:46)
at com.microsoft.kiota.http.OkHttpRequestAdapter.getHttpResponseMessage(OkHttpRequestAdapter.java:709)
at com.microsoft.kiota.http.OkHttpRequestAdapter.send(OkHttpRequestAdapter.java:274)
at com.microsoft.graph.users.UsersRequestBuilder.get(UsersRequestBuilder.java:120)
at com.github.example.MsGraphConsumer.getUser(MsGraphConsumer.java:53)
Workaround
Set the scope directly or initialise scopes as null:
new GraphServiceClient(clientSecretCredential, "https://graph.microsoft.com/.default");
new GraphServiceClient(clientSecretCredential, null);
Authors remarks
Looks like this is due to com.microsoft.kiota.authentication.AzureIdentityAccessTokenProvider:66 assigns scopes using the Arrays.ArrayList type that does not implement add