Acquiring access token using MSAL for JAVA

Tobias Kuess 26 Reputation points
2022-11-07T14:35:01.22+00:00

Hello,

we used ADAL 4J for a couple of years now and it worked fine. Now we're migrating to MSAL. Our flow is:

  1. Acquire Token using Username & Password via PublicClientApplication
  2. Use the token to get User related information via Graph API and I can't get it to work because it always throws the following error: java.lang.ClassCastException: java.util.Collections$SingletonList (loaded by <bootstrap>) cannot be cast to java.lang.String (loaded by <bootstrap>)
    at com.nimbusds.oauth2.sdk.util.URLUtils.serializeParameters(URLUtils.java:105)
    at com.microsoft.aad.msal4j.TokenRequestExecutor.createOauthHttpRequest(TokenRequestExecutor.java:57)
    at com.microsoft.aad.msal4j.TokenRequestExecutor.executeTokenRequest(TokenRequestExecutor.java:35)
    at com.microsoft.aad.msal4j.AbstractClientApplicationBase.acquireTokenCommon(AbstractClientApplicationBase.java:128)
    at com.microsoft.aad.msal4j.AcquireTokenByAuthorizationGrantSupplier.execute(AcquireTokenByAuthorizationGrantSupplier.java:63)
    at com.microsoft.aad.msal4j.AuthenticationResultSupplier.get(AuthenticationResultSupplier.java:69)
    at com.microsoft.aad.msal4j.AuthenticationResultSupplier.get(AuthenticationResultSupplier.java:18)
    at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1604)
    at java.lang.Thread.run(Thread.java:838)

That happens when IAuthenticationResult.get() is called. This is the code snipped which is used to aquire the token:

 private static IAuthenticationResult getAccessTokenFromUserCredentials(String username, String password) throws Exception {  
 IAuthenticationResult result;  

 UserNamePasswordParameters parameters = UserNamePasswordParameters.builder(Collections.singleton("User.Read"), username, password.toCharArray()).build();  

 PublicClientApplication application = PublicClientApplication.builder(clientId).build();  

 result = application.acquireToken(parameters).get();  

 if (result == null) {  
 throw new ServiceUnavailableException("authentication result was null");  
 }  

 return result;  
 }  

Is there anything obvious I am missing?

EDIT:
updated code snipped based on github example:

            try {  
                SilentParameters silentParameters =  
                        SilentParameters  
                                .builder(Collections.singleton("User.Read"))  
                                .account(account)  
                                .build();  
                // Try to acquire token silently. This will fail on the first acquireTokenUsernamePassword() call  
                // because the token cache does not have any data for the user you are trying to acquire a token for  
                result = pca.acquireTokenSilently(silentParameters).join();  
                LOGGER.debug("AzureAPI | AuthenticationService | getAccessTokenFromUserCredentials | acquireTokenSilently call succeeded");  
            } catch (Exception ex) {  
                if (ex.getCause() instanceof MsalException) {  
                    System.out.println("==acquireTokenSilently call failed: " + ex.getCause());  
                    UserNamePasswordParameters parameters =  
                            UserNamePasswordParameters  
                                    .builder(Collections.singleton("User.Read"), username, password.toCharArray())  
                                    .build();  
                    // Try to acquire a token via username/password. If successful, you should see  
                    // the token and account information printed out to console  
                    result = pca.acquireToken(parameters).join();  
                    LOGGER.debug("AzureAPI | AuthenticationService | getAccessTokenFromUserCredentials | username/password flow succeeded");  
                } else {  
                    // Handle other exceptions accordingly  
                    throw ex;  
                }  
            }  
            return result;  
Microsoft Entra External ID
Microsoft Entra External ID
A modern identity solution for securing access to customer, citizen and partner-facing apps and services. It is the converged platform of Azure AD External Identities B2B and B2C. Replaces Azure Active Directory External Identities.
2,710 questions
Microsoft Entra ID
Microsoft Entra ID
A Microsoft Entra identity service that provides identity management and access control capabilities. Replaces Azure Active Directory.
20,121 questions
{count} votes