App to a database with a managed identity — Azure SQL, Cosmos DB, PostgreSQL, MySQL and Managed Redis side by side
The keyless handoff from an Azure-hosted app to each managed database — what turns the app's managed identity into a database principal (CREATE USER FROM EXTERNAL PROVIDER, a Cosmos sqlRoleAssignment, pgaadauth_create_principal, CREATE AADUSER, a Redis access policy assignment), the token scope, the switch that turns passwords or keys off, the private DNS zone — and the known-bad configurations with the error each produces and which side is wrong.
markdownpatternv1SF89-S31Ystage: buildtrust: officialservice: sqlservice: cosmos-dbservice: postgresqlservice: mysqlservice: redisservice: managed-identityinterface: iacinterface: sdkmanaged identity databasepasswordless database Azurewhich Azure role for database data accessAzure SQL managed identity userCosmos DB managed identity data rolePostgreSQL managed identity roleMySQL managed identity AADUSERRedis managed identity access policytoken scope database.windows.netcosmos.azure.comossrdbms-aad.database.windows.netredis.azure.comOwner can't read database datadisplay name mismatch database useruser-assigned identity client ID database
App to a database with a managed identity
None of these databases reads Azure RBAC for data. Owner or Contributor on the resource manages it; reading rows, items or keys needs a principal inside the database's own permission system. Use a user-assigned identity so the database principal survives redeploys, and pass its client ID to ManagedIdentityCredential (or AZURE_CLIENT_ID for DefaultAzureCredential).
Known-good
| Database | Make the identity a principal | Token scope (SDKs request it) | Keys or passwords off | Private DNS zone |
|---|---|---|---|---|
| Azure SQL | CREATE USER [<identity name>] FROM EXTERNAL PROVIDER; in the app database, then roles. The server identity needs Graph read permissions | https://database.windows.net/.default | Entra-only authentication | privatelink.database.windows.net |
| Cosmos DB for NoSQL | sqlRoleAssignments with Built-in Data Contributor (…0002) at / or /dbs/<db> | <account endpoint>/.default (fallback https://cosmos.azure.com/.default) | disableLocalAuth: true | privatelink.documents.azure.com |
| PostgreSQL flexible | pgaadauth_create_principal('<identity name>', false, false) as an Entra admin, then GRANT | https://ossrdbms-aad.database.windows.net/.default | authConfig.passwordAuth: 'Disabled' | Private access: a zone ending .postgres.database.azure.com; endpoints: privatelink.postgres.database.azure.com |
| MySQL flexible | CREATE AADUSER '<identity name>'; as the Entra admin, then GRANT. The server needs a user-assigned identity with Graph permissions | https://ossrdbms-aad.database.windows.net/.default (cleartext plugin) | aad_auth_only = ON | privatelink.mysql.database.azure.com |
| Azure Managed Redis | accessPolicyAssignments with accessPolicyName: 'default' and the identity's object ID | https://redis.azure.com/.default | accessKeysAuthentication: 'Disabled' | privatelink.redis.azure.net |
TypeScript for each: guides/sql/connect-from-typescript.md, reference/cosmos-db/errors.md, reference/postgresql/flexible-server.md, reference/mysql/flexible-server.md, reference/redis/managed-redis.md.
Known-bad
| Configuration | What you see | Wrong side |
|---|---|---|
| Only an Azure role (even Owner) on the database resource | SQL 18456; Cosmos 403 does not have required RBAC permissions; PostgreSQL password authentication failed; Redis auth failure | Database: no principal |
SQL user created in master instead of the app database | 4060 or 18456 | Database |
Name in CREATE USER / pgaadauth_create_principal doesn't match the identity (a different identity's name, wrong case) | Login fails | Database |
| System-assigned identity recreated with the app | Worked yesterday, 18456 today: new object ID | Identity choice |
DefaultAzureCredential on a host with several identities and no AZURE_CLIENT_ID | Token for the wrong identity | App |
Cosmos role assigned with az role assignment create | Still 403 | Identity: wrong permission system |
| App creates Cosmos containers at start-up with an Entra token | 403 substatus 5300 | App: do it in Bicep |
| PostgreSQL client without TLS settings | no pg_hba.conf entry … no encryption hides the real error | App |
| MySQL client without the cleartext plugin | Login fails although the token is valid | App |
| Redis groups in the user list, or a token never refreshed | Groups aren't supported; connections drop when the token expires | Database / app |
| Keys disabled before every client switched | Old clients fail at once (Redis drops all connections when the setting changes) | Rollout order |
| Private endpoint without its zone linked to the app's VNet | SQL 47073, Cosmos 403 path message, timeouts | Network (reference/networking/private-endpoints-and-dns.md) |