Andrea Boscaro
Andrea Boscaro

Reputation: 1

Dataverse C# .NET Core 6 - Using TokenCacheStorePath on Azure App Service WebApp

I'm trying to use the "TokenCacheStorePath" parameter in a Dataverse connection string for a WebApp published on an Windows Azure App Service but I can't get the ServiceClient to create the token file, even when debugging and locating it in my local machine.

The connection string is like this one (in this case, I'm trying to locate the file on my local machine):

"AuthType=ClientSecret;ClientId=xxx;ClientSecret=xxx;Url=https://xxx.crm4.dynamics.com;TokenCacheStorePath=C:\\Token\\token.json"

I'm using the Nuget package "Microsoft.PowerPlatform.Dataverse.Client" and the connection is very basic:

ServiceClient _crmServiceClient = new(connectionString)
{
    CallerId = callerId ?? Guid.Empty
};

What I'm doing wrong and where can I place the "token.json" file when working on Azure? Consider that I might publish the WebApp either on Windows or on Linux.

When working on Azure, I've tried using "D:\home\TokenCacheFile.dat" but no folder or file was created

Thanks

Upvotes: 0

Views: 173

Answers (2)

Piero
Piero

Reputation: 384

Use a simple local file like

TokenCacheStorePath=.\\tokencache;

It works for me.

Upvotes: 0

Reza
Reza

Reputation: 740

  1. The cache file is not in JSON format. The documentation proposes .dat extension and I recommend following the convention proposed in the official documentation.

  2. I also checked the source code of the client SDK and it turned out that if you do not provide any value it still provides a cache file path to the underlying Microsoft Entra library. The default file path is constructed using the following function which you can find in the FileBackedTokenCacheHints class.

    public FileBackedTokenCacheHints(string tokenPathAndFileName)
    {
      string str1 = "DvBaseClient";
      if (AppDomain.CurrentDomain != null)
        str1 = Path.GetFileNameWithoutExtension(Utilities.CleanUpPotentialFileName(AppDomain.CurrentDomain.FriendlyName));
      string xrmSdkFileVersion = Environs.XrmSdkFileVersion;
      string str2 = Utilities.CleanUpPotentialFileName(typeof (OrganizationDetail).Assembly.GetCustomAttribute<AssemblyCompanyAttribute>().Company);
      if (string.IsNullOrEmpty(tokenPathAndFileName))
        tokenPathAndFileName = Path.Combine(MsalCacheHelper.UserRootDirectory, str2?.Replace(" ", "_"), str1, xrmSdkFileVersion, "dvtokens.dat");
      Trace.WriteLine("TokenCacheFilePath: " + tokenPathAndFileName);
      this.cacheFileDirectory = Path.GetDirectoryName(tokenPathAndFileName);
      this.cacheFileName = Path.GetFileName(tokenPathAndFileName);
      this.macKeyChainServiceName = str1 + "_service";
      this.macKeyChainServiceAccount = str1 + "_account";
      this.linuxSchemaName = str1 + ".dvserviceclient.tokencache";
      this.linuxCollection = "default";
      this.linuxLabel = "Token Storage for " + str1;
      this.linuxAttr1 = new KeyValuePair<string, string>("Version", string.IsNullOrEmpty(xrmSdkFileVersion) ? "1.0" : xrmSdkFileVersion);
      this.linuxAttr2 = new KeyValuePair<string, string>("ProductGroup", str1);
    }

The file is stored in the user folder and its name is generated based on the of the AppDomain, company name of the assembly and some static predefined strings.

In your case you can simply not provide it and the file will be stored in the user folder of the account assigned to your app pool in IIS if you're hosting it on-premises (in that case make sure the user has the right to have a user profile.

If you are hosting it in the cloud or any other way, you need to make sure the path you provide is valid and accessible to the account / principal running your service. To be safe your can get a path using HostingEnvironment.MapPath("~/App_Data") and add the file name at the end for example. Then the file will be stored in D:\home\site\wwwroot\App_Data and you can access it from the Azure Portal. Kudu in Azure App Service can help you find it.

I also recommend writing a few lines of code to write a string and read it back and print it on screen as a PoC to solidly verify that you don't have a file access / IO issue.

Upvotes: 0

Related Questions