adal4j authentication with ClientCredential + login/password

973 views Asked by At

I connect to a Azure AD with Adal4j to let a Native App access MS CRM Web api.

We use this method to get the token:

AuthenticationContext : public Future<AuthenticationResult> acquireToken(
    final String resource, final String clientId,
    final String username, final String password,
    final AuthenticationCallback callback)

Now I wan to use the same code for a web application. So I have registered a Web app in Azure AD with 'Delegate Permissions' and 'Access CRM Online as organization uses' checked.

I first tried with any change and I have received this error :

{"error_description":"AADSTS70002: The request body must contain the following parameter: 'client_secret or client_assertion'.\r\nTrace ID: xxxxxxxxxxxxxxxxxxxx\r\nCorrelation ID: xxxxxxxxxxxxx\r\nTimestamp: 2017-12-01 14:18:03Z","error":"invalid_client"}

Just to test, I have updated ClientAuthenticationPost.toParameters() method to force the client_secret, and it works:

Map<String, String> toParameters() {

    Map<String, String> params = new HashMap<String, String>();

    params.put("client_id", getClientID().getValue());
    params.put("client_secret", "___my_client_secret___"); // added line

    return params;
}

My question is, why there is no such a method 'clientCredential + Login/password' :

AuthenticationContext : public Future<AuthenticationResult> acquireToken(
    final String resource, final ClientCredential clientCredential, // ClientCredential = client_id + client_secret
    final String username, final String password,
    final AuthenticationCallback callback)

Should it be added ? Or the way I authenticate is wrong ?

Best regards.

1

There are 1 answers

1
Y. Piel On

Here is the helper method I have added AuthenticationContext Class:

public Future<AuthenticationResult> acquireToken(final String resource,
                                                 final ClientCredential clientCredential, final String username,
                                                 final String password, final AuthenticationCallback callback) {
    if (StringHelper.isBlank(resource)) {
        throw new IllegalArgumentException("resource is null or empty");
    }

    if (clientCredential == null) {
        throw new IllegalArgumentException("client credential is null");
    }

    if (StringHelper.isBlank(username)) {
        throw new IllegalArgumentException("username is null or empty");
    }

    if (StringHelper.isBlank(password)) {
        throw new IllegalArgumentException("password is null or empty");
    }

    final ClientAuthentication clientAuth = new ClientSecretPost(
            new ClientID(clientCredential.getClientId()), new Secret(
            clientCredential.getClientSecret()));

    return this.acquireToken(new AdalAuthorizatonGrant(
                    new ResourceOwnerPasswordCredentialsGrant(username, new Secret(
                            password)), resource), clientAuth, callback);
}

It works fine for my registered Web app with delegated permissions.

Why this was missing ? This way of connexion does have a meaning or it's a no-sens ?

Best regards.