1

I have a daemon written in Java and running on AWS. It calls multiple Microsoft APIs using tokens based on client Id, client secret and tenant id for each of 100s of user accounts that I am supporting. All worked fine with MS Azure Active Directory Library for Java (ADAL4J). But that is going bye bye and so I am being forced over to MS Authentication Library for Java (MSAL4J).

Basically, I need to use a client id, secret and tenant to get an accessToken that is required for a MS API.

After much meandering through the examples (many of which compile), it seems that this is the closest code I can get to:

    public static String getToken( String apiUrl, 
            String clientId, 
            String clientSecret,
            String tenantId,
            String authUrl ) {

        String token = null ;

        if ( !authUrl.endsWith("/")){
            authUrl = authUrl + "/" ;
        }
/*
  NOTE: This is derived from the following:
  https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-desktop-acquire-token?tabs=java

  I simplified the code by taking out the SilentParameters support.

*/

        // BAD:  authUrl = authUrl + "organizations/";
        // BAD:  authUrl = "https://login.microsoftonline.com/" + tenantId + "/";
        // BAD:  authUrl = "https://login.microsoftonline.com/organizations/";
        authUrl = "https://login.microsoftonline.com/organizations/" + tenantId + "/" ;

        // BAD:  Set<String> SCOPE = Collections.singleton("https://graph.microsoft.com/.default");
        // BAD:  Set<String> scope = Collections.singleton(clientId);
        Set<String> scope = Collections.singleton("");

        // Load token cache from file and initialize token cache aspect. The token cache will have
        // dummy data, so the acquireTokenSilently call will fail.
        ITokenCacheAccessAspect tokenCacheAspect = new TokenPersistence("");

        PublicClientApplication pca;
        try {
            pca = PublicClientApplication 
            .builder(clientId)
            .authority(authUrl)
            .setTokenCacheAccessAspect(tokenCacheAspect)
            .build();
        } catch (MalformedURLException e) {
            return null ;
        }

        IAuthenticationResult result;

        /*
        BAD:  ClientCredentialParameters parameters =
        BAD:     ClientCredentialParameters
        BAD:         .builder(SCOPE)
        BAD:         .build();
        */
        UserNamePasswordParameters parameters =
                    UserNamePasswordParameters
                    .builder(scope, clientId, clientSecret.toCharArray())
                    .build();

        result = pca.acquireToken(parameters).join();

        token = result.accessToken() ;
        return token ;
    }

So, it compiles (even the BAD commented out code compiles), and it runs but it generates:

com.microsoft.aad.msal4j.MsalClientException: com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class com.microsoft.aad.msal4j.InstanceDiscoveryMetadataEntry]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)

The above is generated on the acquireToken call (near the bottom).

I can't figure out what code needs a default constructor (to make the JSON happy). OTOH, I don't know if these are the calls that I should even be making; there seem to be about 47 different ways through and around this MSAL stuff and I am not at ALL sure if I have found "the right path".

Help Me, Obi-Wan Kenobi. You're My Only Hope!

Jay Riddell
  • 11
  • 1
  • 1
  • 2
  • I am also having a similar issue I posted about here that you may find helpful: https://learn.microsoft.com/en-us/answers/questions/835430/how-to-acquire-access-token-using-client-secret-us.html I have been able to acquire a token, but I can only acquire a token to the graph API scope, and not the manually defined app-only scopes that I want so I am still stuck. – Matt Mazzola May 05 '22 at 18:34

2 Answers2

3

Checkout the ms-identity-java-daemon sample: https://github.com/Azure-Samples/ms-identity-java-daemon.

sgonzalez
  • 741
  • 6
  • 20
  • I've done that; that example doesn't work for me EITHER. I have an open github issue at https://github.com/Azure-Samples/ms-identity-java-daemon/issues/4 . The code I posted there is based on the example you provided. – Jay Riddell Apr 14 '20 at 20:06
  • Did you try running a clean clone of the sample with you clientid, tenantid, and secret as suggested? I ask that because in the description in the issue you submitted, you say you are using com.fasterxml.jackson.dataformat jackson-dataformat-cbor2.10.3. That is not part of the sample, and might be the reason you are running into issues. – sgonzalez Apr 14 '20 at 23:32
  • First step though is to check if the sample without those extra dependencies works for you, because it does for me. – sgonzalez Apr 14 '20 at 23:34
  • I cloned the code, changed the constants, ran it and it failed. See link above. Also, Santiago, check your LinkedIn account. I sent the "secrets" to you there. – Jay Riddell Apr 16 '20 at 00:05
3

Try not using TokenCacheAccessAspect at all and see if that works? I.e. something like:

IClientCredential credential = ClientCredentialFactory.createFromSecret(clientSecret);    

ConfidentialClientApplication cca = ConfidentialClientApplication.builder(clientId, credential)
                    .authority(authUrl)
                    .build();

Set<String> scope = ImmutableSet.of();

ClientCredentialParameters parameters =
                     ClientCredentialParameters.builder(scope)
                             .build();

result = cca.acquireToken(parameters).join();

Where authUrl should look like https://login.microsoftonline.com/<tenantId>

See: https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-daemon-acquire-token?tabs=java

steve
  • 537
  • 1
  • 7
  • 17
  • Right, there is no need to configure anything about the cache by default, right? https://learn.microsoft.com/nl-nl/azure/active-directory/develop/msal-java-get-remove-accounts-token-cache – Jaap Jan 14 '21 at 14:50
  • What am I doing wrong, if the result throws NPE? – mavok Nov 23 '22 at 15:33