Skip to content

Dataverse Client sending authentication request to the wrong tenant #494

Description

@whobday

I'm using the client to connect to environments in separate tenants (ABC and XYZ) using an AppRegistration. I'm providing the client a connectionString that looks something like this:

AuthType=Certificate;url=https://abc.dynamics.com/;thumbprint=;ClientId=;UseUniqueConnectionInstance=True;RequireNewInstance=True"
AuthType=Certificate;url=https://xyz.dynamics.com/;thumbprint=;ClientId=;UseUniqueConnectionInstance=True;RequireNewInstance=True"

abc and xyz are different tenants

Occasionally I will see this error:

Microsoft.PowerPlatform.Dataverse.Client.Utils.DataverseConnectionException: Failed to connect to Dataverse ---> Microsoft.Identity.Client.MsalServiceException: AADSTS700016: Application with identifier '<abcAppRegistrationGuid>' was not found in the directory 'XYZ Directory'. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You may have sent your authentication request to the wrong tenant. Trace ID: 2797c8fc-e8a5-4b03-b7da-06091b1e4000 Correlation ID: 54a8a6da-abb4-4f5e-a4e2-9dddd4469943 Timestamp: 2025-01-21 21:31:24Z

at Microsoft.PowerPlatform.Dataverse.Client.Auth.AuthProcessor.<ProcessMsalExecptionAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.PowerPlatform.Dataverse.Client.Auth.AuthProcessor.<ExecuteAuthenticateServiceProcessAsync>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.PowerPlatform.Dataverse.Client.ConnectionService.<ConnectAndInitServiceAsync>d__204.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.PowerPlatform.Dataverse.Client.ConnectionService.<DoDirectLoginAsync>d__185.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.PowerPlatform.Dataverse.Client.ConnectionService.<InitServiceAsync>d__184.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.PowerPlatform.Dataverse.Client.ConnectionService.GetCachedService(ConnectionService& ConnectionObject) at Microsoft.PowerPlatform.Dataverse.Client.ConnectionService.IntilizeService(ConnectionService& ConnectionObject) at Microsoft.PowerPlatform.Dataverse.Client.ServiceClient.CreateServiceConnection(Object externalOrgServiceProxy, AuthenticationType requestedAuthType, String hostName, String port, String orgName, NetworkCredential credential, String userId, SecureString password, String domain, String Geo, String claimsHomeRealm, Boolean useSsl, Boolean useUniqueInstance, OrganizationDetail orgDetail, String clientId, Uri redirectUri, PromptBehavior promptBehavior, OrganizationWebProxyClientAsync externalOrgWebProxyClient, String certificateThumbPrint, StoreName certificateStoreName, X509Certificate2 certificate, Uri instanceUrl, Boolean isCloned, Boolean useDefaultCreds, Version incomingOrgVersion, ILogger externalLogger, String tokenCacheStorePath) --- End of inner exception stack trace --- at Microsoft.PowerPlatform.Dataverse.Client.ServiceClient.CreateServiceConnection(Object externalOrgServiceProxy, AuthenticationType requestedAuthType, String hostName, String port, String orgName, NetworkCredential credential, String userId, SecureString password, String domain, String Geo, String claimsHomeRealm, Boolean useSsl, Boolean useUniqueInstance, OrganizationDetail orgDetail, String clientId, Uri redirectUri, PromptBehavior promptBehavior, OrganizationWebProxyClientAsync externalOrgWebProxyClient, String certificateThumbPrint, StoreName certificateStoreName, X509Certificate2 certificate, Uri instanceUrl, Boolean isCloned, Boolean useDefaultCreds, Version incomingOrgVersion, ILogger externalLogger, String tokenCacheStorePath) at Microsoft.PowerPlatform.Dataverse.Client.ServiceClient.ConnectToService(String connectionString, ILogger logger)

You'll notice the AppRegistrationGuid does not align with the directory it should be connecting to. I make a client, connect, do my operation, and then destroy the client. Rinse. Repeat. 95% of the time this works flawlessly - the other 5% I get the above exception. Curiously, I observed the same behavior with the older CrmSdk client (which spurred the upgrade to the Dataverse Client).

FWIW, the application is multi-threaded.

Activity

  1. changed the title [-]Dataverse Client connecting to wrong tenant on occasion[/-] [+]Dataverse Client attempting to connect to wrong tenant on occasion[/+] on Jan 21, 2025
  2. changed the title [-]Dataverse Client attempting to connect to wrong tenant on occasion[/-] [+]Dataverse Client sendign authentication request to the wrong tenant[/+] on Jan 22, 2025
  3. changed the title [-]Dataverse Client sendign authentication request to the wrong tenant[/-] [+]Dataverse Client sending authentication request to the wrong tenant[/+] on Jan 22, 2025
  4. MattB-msft commented on Jan 29, 2025

    @MattB-msft
    Member

    Will Hobday (@whobday)

    Interesting. could you give me a sense of the volume of requests you're running here?
    How are you doing the parallel operations? are you using the shipped .net TPL bits in .net 6+ or are you using .net framework?
    Do you happen to be running this in an Azure Function?

    version of the DVSC Client?
    I have not seen this behavior myself, and we removed the client caching logic in DVSC ( that means that the RequireNewInstance=True is not wired to anything)

    In CSC ( CrmServiceClient ) this could happen if the system reused the cached client, but DVSC should not be able to do this (caching logic was removed), especially if your disposing the client.

    thanks

  5. whobday-afs commented on Feb 5, 2025

    @whobday-afs

    It's legacy WCF running as a Windows Service using .NET 4.8 and DVSC 1.2.2. The WCF service is configured PerCall. A typical method is going to create a connection to an org/environment, perform an operation, and dispose. It's bursty, but I'd call it low volume. I've been able to replicate the issue in a series of 20 or less connections.

    FWIW, I was happily connecting to DV using CSC until it stopped working forcing my hand with DVSC. Using XrmToolbox you can replicate the issue by attempting to connect to DV using a ConnectionString with AuthType=Certificate. The client connection fails with an ADAL error - I think. Curiously, you can connect to DV using the certificate connection wizard using the same certificate and AppID.

  6. MattB-msft commented on Feb 11, 2025

    @MattB-msft
    Member

    Thanks,
    You said it was working fine with CSC, can you tell me which version of the CSC you were using?
    The major difference in this flow is the use of MSAL.net vs ADAL.net.

  7. whobday commented on Feb 20, 2025

    @whobday
    Author

    I was using 9.1.1.65 of Microsoft.CrmSDK.XrmTooling.CoreAssembly. It connected to DV fine until it didn't, but it never had the wrong tenant issue. Just as a reminder, the clients were created using the connectiionString constructor on both DSC and CSC.

  8. MattB-msft commented on Mar 25, 2025

    @MattB-msft
    Member

    Will Hobday (@whobday) I've not had a chance to dig into this deeply yet.
    What I have tested has not yielded a repo,

    Are you using a multi-tenant app here?

    There are 2 ways to proceed here,

    1. Open a formal support ticket on this to allow us to pull logs from your tenants and investigate what is going on between DVSC+MSAL and Entra,
    2. Replace the Token Acquire flows with your own token logic where you can fully manage and troubleshoot it yourself at the level.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions