Search code examples
javamicrosoft-graph-api

Azure Identity => ERROR in getToken() call with microsoft-graph


We migrated one small java Spring Boot application that fetches emails from Office365, from on-prem to the cloud - a lot of infrastructure was changed at the same time. Before, the application was using a proxy, but in our new setup, the proxy is not here anymore, and we "simply" need to open firewall rules to let our application access the right external URLs.

I can see in microsoft-graph jar that the main URL is https://graph.microsoft.com/v1.0 , so I requested the route opening. but when I deploy in our managed Kubernetes, it fails to retrieve the email, I simply get :

Azure Identity => ERROR in getToken() call for scopes [https://graph.microsoft.com/.default]: Failed to acquire token with username and password. To mitigate this issue, please refer to the troubleshooting guidelines here at https://aka.ms/azsdk/net/identity/usernamepasswordcredential/troubleshoot

When connecting to the container, a curl to https://graph.microsoft.com/v1.0 is successful, so the route is open.

When running the code on my machine, it has always worked. So the credentials are correct.

I am really not sure how to proceed here.. I don't understand why it doesn't work when deployed in our regular environment(s)


Solution

  • Here's how I proceeded :

    • since it is running on my machine, I had a closer look at the debug logs
    • I especially looked at the calls that were made, and I found that there were more than https://graph.microsoft.com/v1.0. the interesting (edited) lines are the ones logged by reactor.netty.http.client.HttpClientConnect :
        15:19:09.978 [reactor-http-nio-1] DEBUG reactor.netty.http.client.HttpClientConnect - [id:feb11a80-1 - R:login.microsoftonline.com] Handler is being applied: {uri=https://login.microsoftonline.com/common/userrealm/firstname.lastname@my-domain.com?api-version=1.0, method=GET}
        15:19:10.780 [reactor-http-nio-2] DEBUG reactor.netty.http.client.HttpClientConnect - [id:4952bd80-1 - R:some.internal.domain.com] Handler is being applied: {uri=https://some.internal.domain.com/foo/services/trust/mex, method=GET} 
        15:19:10.989 [reactor-http-nio-2] DEBUG reactor.netty.http.client.HttpClientConnect - [id:4952bd80-2 - R:some.internal.domain.com] Handler is being applied: {uri=https://some.internal.domain.com/foo/services/trust/13/usernamemixed, method=POST}
        15:19:11.306 [reactor-http-nio-1] DEBUG reactor.netty.http.client.HttpClientConnect - [id:feb11a80-2 - R:login.microsoftonline.com] Handler is being applied: {uri=https://login.microsoftonline.com/common/discovery/instance?api-version=1.1&authorization_endpoint=https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize, method=GET}
        15:19:11.448 [reactor-http-nio-1] DEBUG reactor.netty.http.client.HttpClientConnect - [id:feb11a80-3 - R:login.microsoftonline.com] Handler is being applied: {uri=https://login.microsoftonline.com/organizations/oauth2/v2.0/token, method=POST}
    

    So we clearly see that there's a first call to login.microsoftonline.com, and then to some internal domain (for some extra authentication of some kind I guess..) - I was not aware of that step, since it happens "auto-magically"..

    It works on my machine because the routing of the calls based on the URL happens automatically. But when deployed, now that there's no proxy anymore, it doesn't happen and the application gets a timeout when calling https://some.internal.domain.com/foo/services/trust/mex .

    So I guess I now have 2 options :

    • set up a proxy in the new environment, more or less like it was before
    • play with the options in ProxyOptions , to do the routing myself based on the URL pattern, and use it in an httpClient that I inject in the GraphServiceClient.