web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Finance | Project Operations, Human Resources, ...
Suggested Answer

Accessing custom web service with MSAL instead of ADAL ( C# )

(0) ShareShare
ReportReport
Posted on by 657

Hi,

I'm trying to convert the ADAL use case into MSAL use case for one of our external applications.

It is accessing a custom web service using a clientid & clientsecret.

My previous code was like this

authenticationContext = new AuthenticationContext("">login.windows.net/tenantid");
            credential = new ClientCredential("clientid", "clientsecret");
            authenticationResult = authenticationContext.AcquireTokenAsync("baseurl of the server", credential).Result;
            oAuthHeader = authenticationResult.CreateAuthorizationHeader();

            var contract = new { _request = requestObjectForTheMethod }; // Anonymous object

            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri("full url of the service");
            client.DefaultRequestHeaders.Add("Authorization", oAuthHeader);
            client.Timeout = TimeSpan.FromSeconds(1000);

            HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Post,
                                                    "full url of the service including the method name");
            httpRequest.Content = new StringContent(JsonConvert.SerializeObject(contract),
                                                Encoding.UTF8,
                                                "application/json");

I tried to convert it but already got stuck on the fact it is not returning any accounts via GetAccountsAsync()

ConfidentialClientApplicationOptions options = new ConfidentialClientApplicationOptions()
            {
                ClientId = "clientid",
                ClientSecret = "clientsecret",
                TenantId = "tenantid"
            };

            var _clientApp = ConfidentialClientApplicationBuilder.CreateWithApplicationOptions(options)
                .WithLogging(MyLoggingMethod, LogLevel.Info,
                       enablePiiLogging: true,
                       enableDefaultPlatformLogging: true)
                .Build();

            var accounts = _clientApp.GetAccountsAsync().Result;

            var result = _clientApp.AcquireTokenSilent(scopes, accounts.FirstOrDefault()).ExecuteAsync();

Not sure what I need to do to get this working again ...

Any idea's ?

Regards,

Sven Peeters

I have the same question (0)
  • Martin Dráb Profile Picture
    237,898 Most Valuable Professional on at

    First of all, let me make your code a bit nicer. Next time, please use Insert > Insert Code (in the rich formatting view) to paste source code and remove unnecessary indentation and such things.

    Snippet 1:

    authenticationContext = new AuthenticationContext("">login.windows.net/tenantid");
    credential = new ClientCredential("clientid", "clientsecret");
    authenticationResult = authenticationContext.AcquireTokenAsync("baseurl of the server", credential).Result;
    oAuthHeader = authenticationResult.CreateAuthorizationHeader();
    
    var contract = new { _request = requestObjectForTheMethod }; // Anonymous object
    
    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri("full url of the service");
    client.DefaultRequestHeaders.Add("Authorization", oAuthHeader);
    client.Timeout = TimeSpan.FromSeconds(1000);
    
    HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Post,
    										"full url of the service including the method name");
    httpRequest.Content = new StringContent(JsonConvert.SerializeObject(contract),
    									Encoding.UTF8,
    									"application/json");

    Snippet 2:

    ConfidentialClientApplicationOptions options = new ConfidentialClientApplicationOptions()
    {
    	ClientId = "clientid",
    	ClientSecret = "clientsecret",
    	TenantId = "tenantid"
    };
    
    var _clientApp = ConfidentialClientApplicationBuilder.CreateWithApplicationOptions(options)
    	.WithLogging(MyLoggingMethod, LogLevel.Info,
    		   enablePiiLogging: true,
    		   enableDefaultPlatformLogging: true)
    	.Build();
    
    var accounts = _clientApp.GetAccountsAsync().Result;
    
    var result = _clientApp.AcquireTokenSilent(scopes, accounts.FirstOrDefault()).ExecuteAsync();

  • Martin Dráb Profile Picture
    237,898 Most Valuable Professional on at

    Shouldn't you also set the redirect URI in options?

  • Sven Peeters Prodware Profile Picture
    657 on at

    I made some progress on the topic, appearantly you need to use a different method to get the token. You need to use AcquireTokenForClient and use "erp.dynamics.com/.default" as scope.

    Something like this :

            ConfidentialClientApplicationOptions options = new ConfidentialClientApplicationOptions()
            {
                ClientId = "clienbid",
                ClientSecret = "clientsecret",
                TenantId = "tenantid",
                RedirectUri = "redirect",
                Instance = "https://login.microsoftonline.com/"
            };
    
            var _clientApp = ConfidentialClientApplicationBuilder.CreateWithApplicationOptions(options)
                .WithAuthority("https://login.microsoftonline.com/tenantid")
                .WithLogging(MyLoggingMethod, LogLevel.Info,
                       enablePiiLogging: true,
                       enableDefaultPlatformLogging: true)
                .Build();
    
            string[] scopes = new string[] { "https://erp.dynamics.com/.default" };
            var result = await _clientApp.AcquireTokenForClient(scopes).ExecuteAsync();

    After that add its access token to your httpclient

            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri(JSONServiceUriBaseString);
            client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", result.AccessToken);
            client.Timeout = TimeSpan.FromSeconds(5);

    Unfortunately I always get a 401 (Unauthorized) :-(

    The MSAL logging states the following

    Authority - https://login.microsoftonline.com/tenantid/
    ApiId - AcquireTokenForClient
    IsConfidentialClient - True
    SendX5C - False
    LoginHint -
    IsBrokerConfigured - False
    HomeAccountId -
    
    MSAL Info True (True) MSAL 4.18.0.0 MSAL.Desktop Microsoft Windows NT 6.2.9200.0 [09/11/2020 06:20:25 - 12515503-1d08-45f3-83b6-ae519c3aa4ef] === Token Acquisition (ClientCredentialRequest) started:
            Authority: https://login.microsoftonline.com/tenantid/
            Scope: https://graph.windows.net/.default
            ClientId: clientid
    
    MSAL Info False (False) MSAL 4.18.0.0 MSAL.Desktop Microsoft Windows NT 6.2.9200.0 [09/11/2020 06:20:25 - 12515503-1d08-45f3-83b6-ae519c3aa4ef] Looking up access token in the cache.
    MSAL Info False (False) MSAL 4.18.0.0 MSAL.Desktop Microsoft Windows NT 6.2.9200.0 [09/11/2020 06:20:25 - 12515503-1d08-45f3-83b6-ae519c3aa4ef] No matching entry found for user or assertion
    MSAL Info True (True) MSAL 4.18.0.0 MSAL.Desktop Microsoft Windows NT 6.2.9200.0 [09/11/2020 06:20:26 - 12515503-1d08-45f3-83b6-ae519c3aa4ef] Fetching instance discovery from the network from host login.microsoftonline.com. Endpoint https://login.microsoftonline.com/common/discovery/instance
    MSAL Info False (False) MSAL 4.18.0.0 MSAL.Desktop Microsoft Windows NT 6.2.9200.0 [09/11/2020 06:20:26 - 12515503-1d08-45f3-83b6-ae519c3aa4ef] Resolving authority endpoints... Already resolved? - FALSE
    MSAL Info False (False) MSAL 4.18.0.0 MSAL.Desktop Microsoft Windows NT 6.2.9200.0 [09/11/2020 06:20:26 - 12515503-1d08-45f3-83b6-ae519c3aa4ef] ScopeSet was missing from the token response, so using developer provided scopes in the result.
    MSAL Info False (False) MSAL 4.18.0.0 MSAL.Desktop Microsoft Windows NT 6.2.9200.0 [09/11/2020 06:20:26 - 12515503-1d08-45f3-83b6-ae519c3aa4ef] Checking client info returned from the server..
    MSAL Info False (False) MSAL 4.18.0.0 MSAL.Desktop Microsoft Windows NT 6.2.9200.0 [09/11/2020 06:20:26 - 12515503-1d08-45f3-83b6-ae519c3aa4ef] Saving Token Response to cache..
    MSAL Info False (False) MSAL 4.18.0.0 MSAL.Desktop Microsoft Windows NT 6.2.9200.0 [09/11/2020 06:20:26 - 12515503-1d08-45f3-83b6-ae519c3aa4ef] ID Token not present in response.
    MSAL Info False (False) MSAL 4.18.0.0 MSAL.Desktop Microsoft Windows NT 6.2.9200.0 [09/11/2020 06:20:26 - 12515503-1d08-45f3-83b6-ae519c3aa4ef] Saving AT in cache and removing overlapping ATs...
    MSAL Info False (False) MSAL 4.18.0.0 MSAL.Desktop Microsoft Windows NT 6.2.9200.0 [09/11/2020 06:20:26 - 12515503-1d08-45f3-83b6-ae519c3aa4ef] Looking for scopes for the authority in the cache which intersect with https://erp.dynamics.com/.default
    MSAL Info False (False) MSAL 4.18.0.0 MSAL.Desktop Microsoft Windows NT 6.2.9200.0 [09/11/2020 06:20:26 - 12515503-1d08-45f3-83b6-ae519c3aa4ef] Intersecting scope entries count - 0
    MSAL Info False (False) MSAL 4.18.0.0 MSAL.Desktop Microsoft Windows NT 6.2.9200.0 [09/11/2020 06:20:26 - 12515503-1d08-45f3-83b6-ae519c3aa4ef] === Token Acquisition finished successfully. An access token was returned with Expiration Time: 09/11/2020 07:20:25  00:00 ===

    Why oh why does it has to be this complicated ...

  • Suggested answer
    Sven Peeters Prodware Profile Picture
    657 on at

    Found the solution on this page : msftblog.com/.../

    You need to mention your D365 Instance url as scope value.

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Neeraj Kumar – Community Spotlight

We are honored to recognize Neeraj Kumar as our Community Spotlight honoree for…

Leaderboard > Finance | Project Operations, Human Resources, AX, GP, SL

#1
Martin Dráb Profile Picture

Martin Dráb 544 Most Valuable Professional

#2
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 450 Super User 2025 Season 2

#3
Sohaib Cheema Profile Picture

Sohaib Cheema 250 User Group Leader

Last 30 days Overall leaderboard

Product updates

Dynamics 365 release plans