Saturday, April 19, 2025

Error at "using Microsoft.IdentityModel.Clients.ActiveDirectory" in D365FO update 10.0.43

 If you used Azure Active Directory Authentication Library (ADAL) in your customization, and get a compilation error at "using Microsoft.IdentityModel.Clients.ActiveDirectory" statement in 10.0.43 update, this is because ADAL is deprecated and MS have removed the reference from the AOT. 

You will need to migrate your code to Microsoft Authentication Library (MSAL).

In order to do that, you will need to add the Microsoft.Identity.Client.dll library to your bin-folder (can be found in other subfolders under K:\AosService\PackagesLocalDirectory), and add a corresponding reference to a VS project. The reference will then be created as an XML-file. Both the DLL and the XML files must be added to source control via "Add Items to Folder...", like this:

K:\AosService\PackagesLocalDirectory\<package name>\bin\Microsoft.Identity.Client.dll

K:\AosService\PackagesLocalDirectory\<package name>\<model name>\AxReference\Microsoft.Identity.Client.xml

Then, you will need to change the code.

Before:

using Microsoft.IdentityModel.Clients.ActiveDirectory;


            ClientCredential clientCrendential = new ClientCredential(clientId, clientSecret);
            AuthenticationContext authContext = new AuthenticationContext(authority);
            AuthenticationResult authResult = authContext.AcquireToken(resource, clientCrendential);
            accessToken = authResult.AccessToken;


After change, it will be like this:

using Microsoft.Identity.@Client;


            ConfidentialClientApplicationBuilder clientApplicationbuilder = ConfidentialClientApplicationBuilder::Create(clientId);

            IConfidentialClientApplication app = clientApplicationbuilder.WithClientSecret(clientSecret).WithAuthority(authority).Build();

            System.Collections.Generic.List<System.String> scopes = new System.Collections.Generic.List<System.String>();

            scopes.Add(resource + '/.default');

            System.Collections.IEnumerable enumerable = scopes;

            AcquireTokenForClientParameterBuilder parameterBuilder = app.AcquireTokenForClient(enumerable);

            var task = parameterBuilder.ExecuteAsync();

            task.Wait();

            AuthenticationResult authResult = task.Result;

            accessToken = authResult.AccessToken;



Here is the code to test the above written code and generate token using X++ job:

public static void main(Args _args)

{

    str clientId            = 'xxxxxxxxxxxxxxxxxxxx'; 
    str clientSecret     = 'xxxxxxxxxxxxxxxxxxxx'; 
    str resource          =  '<EnvironmentId>';
    str tenant             = 'xxxxxxxxxxxxxxxxxxxx';

    //Before

    //Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext context;
    //Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential credential;
    //Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationResult result;
    //str accessToken;
    //context = new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext("https://login.microsoftonline.com/"+ tenant +"/oauth2/token");
    //credential = new Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential(clientId, clientSecret);
    //result = context.AcquireToken(resource, credential);
    //accessToken = result.AccessToken;
    //info(accessToken);

    //After

    ConfidentialClientApplicationBuilder clientApplicationbuilder = ConfidentialClientApplicationBuilder::Create(clientId);
    IConfidentialClientApplication app = clientApplicationbuilder.WithClientSecret(clientSecret).WithAuthority("https://login.microsoftonline.com/"+ tenant +"/oauth2/token").Build();
    str accessToken;
    System.Collections.Generic.List<System.String> scopes = new System.Collections.Generic.List<System.String>();
    scopes.Add(resource + '/.default');
    System.Collections.IEnumerable enumerable = scopes;
    AcquireTokenForClientParameterBuilder parameterBuilder = app.AcquireTokenForClient(enumerable);
    var task = parameterBuilder.ExecuteAsync();
    task.Wait();
    AuthenticationResult authResult = task.Result;
    accessToken = authResult.AccessToken;
    info(accessToken);

}


Note: where resource is enviornment url in both cases.

No comments:

Post a Comment