dinesh
dinesh

Reputation: 31

Getting an exception when tried to implement Azure AD authentication using java

I am using the Username-Password Flow to acquire the token. Below is my sample code:

public class UsernamePasswordFlowTest {

private static String authority;
private static Set<String> scope;
private static String clientId;
private static String username;
private static String password;
public static void main(String args[]) throws Exception {

    setUpSampleData();

    PublicClientApplication pca = PublicClientApplication.builder(clientId)
            .authority(authority)
            .build();

    //Get list of accounts from the application's token cache, and search them for the configured username
    //getAccounts() will be empty on this first call, as accounts are added to the cache when acquiring a token
    Set<IAccount> accountsInCache = pca.getAccounts().join();
    IAccount account = getAccountByUsername(accountsInCache, username);

    //Attempt to acquire token when user's account is not in the application's token cache
    IAuthenticationResult result = acquireTokenUsernamePassword(pca, scope, account, username, password);
    System.out.println("Account username: " + result.account().username());
    System.out.println("Access token:     " + result.accessToken());
    System.out.println("Id token:         " + result.idToken());
    System.out.println();

    accountsInCache = pca.getAccounts().join();
    account = getAccountByUsername(accountsInCache, username);

    //Attempt to acquire token again, now that the user's account and a token are in the application's token cache
    result = acquireTokenUsernamePassword(pca, scope, account, username, password);
    System.out.println("Account username: " + result.account().username());
    System.out.println("Access token:     " + result.accessToken());
    System.out.println("Id token:         " + result.idToken());
}

private static IAuthenticationResult acquireTokenUsernamePassword(PublicClientApplication pca,
                                                                  Set<String> scope,
                                                                  IAccount account,
                                                                  String username,
                                                                  String password) throws Exception {
    IAuthenticationResult result;
    try {
        SilentParameters silentParameters =
                SilentParameters
                        .builder(scope)
                        .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();
        System.out.println("==acquireTokenSilently call succeeded");
    } catch (Exception ex) {
        if (ex.getCause() instanceof MsalException) {
            System.out.println("==acquireTokenSilently call failed: " + ex.getCause());
            UserNamePasswordParameters parameters =
                    UserNamePasswordParameters
                            .builder(scope, 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();
            System.out.println("==username/password flow succeeded");
        } else {
            // Handle other exceptions accordingly
            throw ex;
        }
    }
    return result;
}

/**
 * Helper function to return an account from a given set of accounts based on the given username,
 * or return null if no accounts in the set match
 */
private static IAccount getAccountByUsername(Set<IAccount> accounts, String username) {
    if (accounts.isEmpty()) {
        System.out.println("==No accounts in cache");
    } else {
        System.out.println("==Accounts in cache: " + accounts.size());
        for (IAccount account : accounts) {
            if (account.username().equals(username)) {
                return account;
            }
        }
    }
    return null;
}

/**
 * Helper function unique to this sample setting. In a real application these wouldn't be so hardcoded, for example
 * values such as username/password would come from the user, and different users may require different scopes
 */
private static void setUpSampleData() throws IOException {
    authority = "https://login.microsoftonline.com/{tenantId}"; // tenantid = xxxxxxxx
    scope = Collections.singleton("user.read");
    clientId = "ebxxxx1c-e1xxx-4xxx-bxxx-dxxxxeaxxxx";
    username = "testuser";
    password = "xxxx";
}

}

But getting exception :

com.microsoft.aad.msal4j.MsalClientException: Token not found in the cache at com.microsoft.aad.msal4j.AcquireTokenSilentSupplier.execute(AcquireTokenSilentSupplier.java:98) at com.microsoft.aad.msal4j.AuthenticationResultSupplier.get(AuthenticationResultSupplier.java:59) at com.microsoft.aad.msal4j.AuthenticationResultSupplier.get(AuthenticationResultSupplier.java:17) at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1700)

Caused by: com.microsoft.aad.msal4j.MsalServiceException: Unknown service exception. Http request returned status code 404 with no response body at com.microsoft.aad.msal4j.MsalServiceExceptionFactory.fromHttpResponse(MsalServiceExceptionFactory.java:52) at com.microsoft.aad.msal4j.UserDiscoveryRequest.execute(UserDiscoveryRequest.java:34) at com.microsoft.aad.msal4j.AcquireTokenByAuthorizationGrantSupplier.processPasswordGrant(AcquireTokenByAuthorizationGrantSupplier.java:91)

Can someone help me to understand this exception?

Upvotes: 1

Views: 4936

Answers (1)

ShrutiJoshi-MT
ShrutiJoshi-MT

Reputation: 1851

com.microsoft.aad.msal4j.MsalServiceException

This exception can be thrown if your application was not registered as a public client application in Azure AD. In the Azure portal, edit the manifest for your application and set allowPublicClient to true.

And also check with The specified client_secret does not match the expected value for this client. Correct the client_secret and try again.

MsalClientException is thrown when an error occurs that is local to the library or device.

more details refer this document

You can follow the below code sample in Github:https://github.com/Azure-Samples/ms-identity-java-desktop/blob/master/Username-Password-Flow/README.md

Upvotes: 1

Related Questions