.NET Framework 4.7.2 accessing Azure SQL via User Assigned Managed Identity: Login failed for user ''
I'm using .NET Framework (not Core!) 4.7.2 and am trying to use a User-Assigned Managed Identity to connect to an Azure SQL Server. The Managed Identity object has been added to db_datareader
, db_datawriter
roles on the Azure SQL server and has permissions to connect. (independently verified with our ASP.NET Core app).
However it fails when we try to do it from our command-line .NET Framework app running on a VM that has been enabled on the managed identity. The code to connect to Azure SQL looks roughly like this:
// .NET Framework 4.7.2
using(SqlConnection connection = new SqlConnection("Server=tcp:myserver.database.windows.net,1433;Database=MyDb;")){
var credential = new ManagedIdentityCredential(ConfigurationManager.AppSettings["ManagedIdentityId"]);
conn.AccessToken = await credential.GetTokenAsync(
new TokenRequestContext(new[] { "https://database.windows.net/.default" })
);
....
}
It manages to grab a token just fine (from the logs below), but fails with this error
System.Data.SqlClient.SqlException (0x80131904): Login failed for user ''
What should I check?
(the very same code works fine from ASP.NET Core)
Appendix
* Very similar to this issue, but in our case not all forms of auth failed on the Azure SQL server. We were able to login manually with AAD accounts. It's only the User-Assigned Managed Identity called from .NET Framework 4.7.2 that is failing (it works fine from our ASP.NET Core program, same code)
* Logs here
2021-06-15 14:39:28.7200|INFO|Logger|Received TOKEN - [xxxx real token here xxxx]
2021-06-15 14:39:28.9387|ERROR|Logger|Exception occurred:
System.Data.SqlClient.SqlException (0x80131904): Login failed for user ''.
at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions,
SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance,
SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, DbConnectionPool pool, String accessToken,
Boolean applyTransientFaultHandling, SqlAuthenticationProviderManager sqlAuthProviderManager)
at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey,
Object poolGroupProviderInfo, DbConnectionPool pool,
DbConnection owningConnection, DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject,
DbConnectionOptions options, DbConnectionPoolKey poolKey,
DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout,
Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions,
DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionPool.WaitForPendingOpen()