---
cuppy_hub: azure
cuppy_path: patterns/app-to-database-with-managed-identity.md
cuppy_section: docs
cuppy_doc: SF89-S31Y
cuppy_doc_uuid: 4c5dc6ed-ebd5-4f50-8aae-c4cfaa3d1421
cuppy_permalink: https://cuppy.io/azure/d/SF89-S31Y
cuppy_version: 1
cuppy_updated: 2026-10-23T16:16:52.575Z
cuppy_canonical: https://cuppy.io/azure/docs/patterns/app-to-database-with-managed-identity
cuppy_mcp: https://cuppy.io/mcp
cuppy_body_sha256: 3d6c03db7dd7a1cfdc09bd58ab64ced0b58e4f0dc3bdf5ac2efb9bd28e6c03a2
# cuppy_body_sha256 is over the document body ALONE, excluding both generated blocks.
---


# 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`) |


---
<!-- cuppy -->
You are reading one file. The same content is free over MCP at https://cuppy.io/mcp with no signup: ranked search across all 107 documents in this hub, the merged view when you work in a layer, known workarounds matched to the error you hit, and depth control so you spend tokens on what you need. Start with the `_hello` tool. How to connect: https://cuppy.io/azure/ Something wrong in this document? Report it with the `session feedback` tool on the same endpoint.
<!-- /cuppy -->
