Hello Mark S,
Welcome to the Microsoft Q&A and thank you for posting your questions here.
I understand that your Azure SQL Database login fails with error 916 for least-privilege SQL user and managed identity, but admin login works.
Error 916 occurs when the identity authenticated by Azure SQL cannot access the named database under its current security context. Existing CONNECT and role grants do not solve the problem if they were granted to a different database principal or if the application selected a different managed identity. - https://learn.microsoft.com/en-us/sql/relational-databases/errors-events/mssqlserver-916-database-engine-error?view=sql-server-ver17, https://learn.microsoft.com/en-us/azure/azure-sql/database/authentication-azure-ad-user-assigned-managed-identity?view=azuresql. The failure is at the managed-identity selection and target-database user-mapping boundary.
Best method to resolve this is to:
- Keep the user-assigned managed identity assigned to the correct App Service or deployment slot.
- Verify the deployed Microsoft.Data.SqlClient version.
- For SqlClient 3.0 or later, place the UAMI client ID in
User Id; SqlClient 2.1 instead expects the UAMI object ID.
- Create or validate the UAMI as a contained external user in the target database only.
- Specify the target database explicitly in the application connection string.
- Remove
TrustServerCertificate=True.
- Restart the App Service to clear configuration and connection-pool state.
- Validate the resolved database identity with
USER_NAME() after connection.
- If the corrected configuration still fails, enable Azure SQL auditing and review
FAILED_DATABASE_AUTHENTICATION_GROUP before escalating. - https://learn.microsoft.com/en-us/azure/azure-sql/database/auditing-setup?view=azuresql, https://learn.microsoft.com/en-us/azure/azure-sql/database/auditing-analyze-audit-logs?view=azuresql
Use the following production connection string with Microsoft.Data.SqlClient 3.0 or later:
Server=tcp:sql-intranet-prod.database.windows.net,1433;
Database=sqldb-riga-balticvip-dev-import;
Authentication=Active Directory Managed Identity;
User Id=<UAMI-CLIENT-ID>;
Encrypt=True;
TrustServerCertificate=False;
Connection Timeout=30;
The managed identity should be created in the target database as follows:
CREATE USER [mi-supplierportal-sql]
FROM EXTERNAL PROVIDER;
GRANT CONNECT TO [mi-supplierportal-sql];
ALTER ROLE [<application-runtime-role>]
ADD MEMBER [mi-supplierportal-sql];
Azure SQL Database supports contained Microsoft Entra users directly in the target database, and App Service supports passwordless Azure SQL access through system-assigned or user-assigned managed identities. A separate login in virtual master is not required for this application connection. - https://learn.microsoft.com/en-us/sql/t-sql/statements/create-user-transact-sql?view=sql-server-ver17, https://learn.microsoft.com/en-us/azure/app-service/tutorial-connect-msi-azure-database, https://learn.microsoft.com/en-us/azure/app-service/tutorial-connect-msi-sql-database
If the name mi-supplierportal-sql is not unique in Microsoft Entra ID, create an unambiguous SQL alias using the UAMI object ID:
CREATE USER [mi-supplierportal-sql-uami]
FROM EXTERNAL PROVIDER
WITH OBJECT_ID = '<UAMI-OBJECT-ID>';
GRANT CONNECT TO [mi-supplierportal-sql-uami];
ALTER ROLE [<application-runtime-role>]
ADD MEMBER [mi-supplierportal-sql-uami];
WITH OBJECT_ID is specifically intended to resolve nonunique Microsoft Entra principal names and should not replace the standard syntax when the display name is unique. - https://learn.microsoft.com/en-us/sql/relational-databases/security/authentication-access/authentication-microsoft-entra-create-users-with-nonunique-names?view=sql-server-ver17, https://learn.microsoft.com/en-us/sql/relational-databases/security/authentication-access/authentication-microsoft-entra-create-users-with-nonunique-names?view=sql-server-ver17
After applying the corrected connection string, restart the App Service and run:
SELECT
DB_NAME() AS database_name,
ORIGINAL_LOGIN() AS original_login,
SUSER_SNAME() AS server_principal,
USER_NAME() AS database_user,
CURRENT_USER AS current_database_user;
The expected result is:
database_name = sqldb-riga-balticvip-dev-import
database_user = mi-supplierportal-sql
current_database_user = mi-supplierportal-sql
Do not grant access to guest, enable TRUSTWORTHY, grant db_owner, or create an unnecessary login in master. Those actions weaken security and do not correct managed-identity selection or contained-user mapping. Use associated resource links for more reading and steps.
I hope this is helpful. Please! Do not hesitate to let me know if you have any other questions, steps or clarifications.
Please do not close the thread by upvoting and accepting the answer if any part of it is helpful.