Hi,
I am trying to authenticate with IFS 10 using Azure AD. That authentication works correctly when Aurena or Entreprise Explorer are used. When trying to access from an external .NET program, it is not working. The token seems to be wrong and an "Error 401--Unauthorized" error is returned. The original program is a WPF application but I written a console app to extract (and rework) the authentication logic but the result is still the same one. A code nearly identical is working in other projects where we use Microsoft Dynamics 365 BC and Microsoft Dynamics 365 FO instead of IFS as the ERP.
The NuGet packages used are:
- Microsoft.Azure.ActiveDirectory.GraphClient 2.1.1
- Microsoft.Identity.Client 4.43.1
- Newtonsoft.Json 13.0.1
- RestSharpSigned 105.2.3
The main code, cleaned for clarity, is as follow:
System.Net.ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
{
return true;
};
System.Net.ServicePointManager.SecurityProtocol = System.Net.ServicePointManager.SecurityProtocol | System.Net.SecurityProtocolType.Tls12;
// Authentication
string resourceId = _clientId; // Azure AD -> resourceId = clientId
//stringt] scopes = new stringt] { "user.read" };
stringt] scopes = new stringt] { resourceId + "/.default" }; // Only scope that work
//stringt] scopes = new stringt] { resourceId + "/user_impersonation" }; // https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-v1-app-scopes
// https://docs.microsoft.com/en-us/azure/active-directory/develop/console-app-quickstart?pivots=devlang-dotnet-core
Console.WriteLine(string.Format("Client ID = {0}", _clientId));
Console.WriteLine(string.Format("Client Secret = {0}", _clientSecret));
//string authority = string.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}", _tenant);
string authority = string.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}/v2.0", _tenant);
//string authority = _tenant;
Console.WriteLine(string.Format("Authority = {0}", authority));
IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(_clientId)
.WithClientSecret(_clientSecret)
.WithAuthority(new Uri(authority))
//.WithRedirectUri(_callbackUrl)
//.WithRedirectUri("http://localhost") // needed only for the system browser
//.WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient") // needed only for the system browser
.Build();
var result = app.AcquireTokenForClient(scopes).ExecuteAsync().GetAwaiter().GetResult();
//string authCode = "";
//var result = await app.AcquireTokenByAuthorizationCode(scopes, authCode).ExecuteAsync();
Console.WriteLine();
string token = result.AccessToken;
Console.WriteLine(string.Format("AccessToken = {0}", token));
string header = result.CreateAuthorizationHeader();
Console.WriteLine();
Console.WriteLine(string.Format("AuthorizationHeader = {0}", header));
// Reading a part to test the token
Newtonsoft.Json.Linq.JObject part = ReadPartCatalog(_baseUrl, token, "3145561");
Console.WriteLine();
Console.WriteLine(string.Format("Part = {0}", part.ToString()));