Azure.Identity package version 1.11.0 caused an error with SqlClient
and Dynamics 365.
I connected to Dynamics 365 using Microsoft Entra Service Principal
authentication, and everything worked perfectly. I used SQL Server Management Studio 20.0.70.0.
Also, I have a C# application using Dapper and SqlClient
(check the code below).
Everything worked perfectly until I upgraded the Azure.Identity
Package to 1.11.0
(updated five days ago). Downgrading it to 1.10.4
will make it work.
I cannot find any solution in Microsoft Docs.
Thank you.
Exception:
ClientSecretCredential authentication failed: AADSTS900023: Specified tenant identifier 'authorize' is neither a valid DNS name, nor a valid external domain. Trace ID: 52222220-3332-3331-3033-222225335233 Correlation ID: fddd3533-aaaa-4fab-8b49-22ea71b32723 Timestamp: 2024-04-14 20:20:52Z
Code:
I finally found it here, But I applied minor modifications to make it work with Dynamics 365. Here is the code
private SqlAuthenticationToken? _sqlAuthenticationToken;
protected Func<SqlAuthenticationParameters, CancellationToken, Task<SqlAuthenticationToken?>> GetTokenCallback()
{
var tenantId = "[Taken From Azure Portal]";
var clientId = "[Taken From Azure Portal]";
var clientSecret = "[Taken From Azure Portal]";
const string defaultScopeSuffix = ".default";
var cred = new ClientSecretCredential(tenantId, clientId, clientSecret);
return TokenCallback;
async Task<SqlAuthenticationToken?> TokenCallback(SqlAuthenticationParameters ctx, CancellationToken cancellationToken)
{
var validToken = _sqlAuthenticationToken != null && _sqlAuthenticationToken.ExpiresOn.UtcDateTime > dateTimeService.Now;
if (validToken) return _sqlAuthenticationToken;
string scope = ctx.Resource.EndsWith(defaultScopeSuffix)
? ctx.Resource
: ctx.Resource + defaultScopeSuffix;
var token = await cred.GetTokenAsync(new TokenRequestContext([scope]), CancellationToken.None);
_sqlAuthenticationToken = new SqlAuthenticationToken(token.Token, token.ExpiresOn);
return _sqlAuthenticationToken;
}
}
Then I modified the creation of SqlConnection
to be like this
await using var connection = new SqlConnection(ConnectionString);
connection.AccessTokenCallback = GetTokenCallback();
One more thing: You need to modify the connection string from this
"Server=your-app.crm.dynamics.com; Authentication=Active Directory Service Principal; Encrypt=True; Database=[db-name]; User Id=[clientId]; Password=[clientSecret]"
to this
"Server=your-app.crm.dynamics.com; Encrypt=True; Database=[db-name];
So I removed User Id
, Password
, and Authentication
.