Azure Database for MySQL flexible server — Entra authentication with a user-assigned identity, CREATE AADUSER, cleartext tokens from Node.js, versions and extended support

Signing in to MySQL flexible server with Microsoft Entra — the user-assigned server identity and its Graph permissions, aad_auth_only, the single Entra admin, CREATE AADUSER for apps and groups, tokens for ossrdbms-aad sent through the cleartext plugin (mysql2 needs enableCleartextPlugin), network modes, and the paid extended support that started for 5.7 on October 1, 2026 and starts for 8.0 on February 1, 2027.

markdownreferencev1138K-N2TYstage: buildtrust: officialservice: mysqlinterface: iacinterface: cliinterface: sdkAzure Database for MySQL flexible server Entra authenticationaad_auth_onlyuser-assigned managed identity MySQL serverUser.Read.All GroupMember.Read.All Application.Read.All MySQLDirectory Readers MySQLaz mysql flexible-server ad-admin createCREATE AADUSERAADUSER alias 32 charactersmysql --enable-cleartext-pluginmysql2 enableCleartextPluginmysql_clear_passwordhttps://ossrdbms-aad.database.windows.net/.defaultMySQL token 5 to 60 minutesMySQL 5.7 extended support October 1 2026MySQL 8.0 standard support end January 31 2027MySQL 8.4MySQL 9.5 previewdelegatedSubnetResourceId Microsoft.DBforMySQL/flexibleServersprivatelink.mysql.database.azure.comMicrosoft.DBforMySQL/flexibleServers@2024-12-30

Created 21 Oct 2026 · Modified 23 Oct 2026 · 1 version

MySQL flexible server

Entra authentication

  1. Server identity: Entra sign-in requires a user-assigned managed identity on the server with Microsoft Graph User.Read.All, GroupMember.Read.All and Application.Read.All (or Directory Readers). Granting them needs at least Privileged Role Administrator.
  2. One Entra admin per server (setting another replaces it): az mysql flexible-server ad-admin create -g <rg> -s <server> -u <admin UPN or group> -i <object id> --identity <user-assigned identity>. Removing the admin disables every Entra login.
  3. Mode: server parameter aad_auth_only ON = Entra only; OFF = MySQL and Entra.
  4. Users, connected as the admin:
CREATE AADUSER '<managed identity or app display name>';
CREATE AADUSER 'Prod_DB_Readonly';                      -- an Entra group
CREATE AADUSER '<longer than 32 characters>' as 'shortalias';
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO '<managed identity or app display name>'@'%';

Signing in grants nothing by itself: grant privileges. Names are case-sensitive; group members sign in with the group name. The server matches tokens on the principal's object ID, not its name, and a deleted user can still sign in until its token expires (up to 60 minutes).

Tokens: scope https://ossrdbms-aad.database.windows.net/.default (CLI --resource-type oss-rdbms), valid 5–60 minutes, and they must reach the server unhashed: mysql --enable-cleartext-plugin, MySQL Workbench "Enable Cleartext Authentication Plugin", and in Node.js mysql2's enableCleartextPlugin: true (off by default since it's a security setting; safe here only because TLS is required). Microsoft says that from January 2027 tokens for other audiences won't be accepted. A server with Entra enabled can't move to another tenant.

Node.js

import mysql from "mysql2/promise";
import { DefaultAzureCredential } from "@azure/identity";

const credential = new DefaultAzureCredential();
const SCOPE = "https://ossrdbms-aad.database.windows.net/.default";

// mysql2 takes a fixed password, so open connections with a fresh token rather than a long-lived pool.
export async function connect(): Promise<mysql.Connection> {
  return mysql.createConnection({
    host: `${process.env.MYSQL_SERVER}.mysql.database.azure.com`,
    user: process.env.MYSQL_USER ?? "", // the Entra user (UPN) or CREATE AADUSER alias
    password: (await credential.getToken(SCOPE)).token,
    database: "appdb",
    ssl: { rejectUnauthorized: true },
    enableCleartextPlugin: true, // Azure needs the token sent as-is; mysql2 disables cleartext by default
  });
}

export async function main(): Promise<void> {
  const conn = await connect();
  const [rows] = await conn.query("SELECT CURRENT_USER() AS u");
  console.log(rows);
  await conn.end();
}

Because mysql2 takes a fixed password, open short-lived connections (or recreate the pool) well inside the token lifetime.

Bicep

// MySQL flexible server with a user-assigned identity, an Entra admin group and Entra-only sign-in
param location string = resourceGroup().location
param serverName string
param serverIdentityId string // user-assigned identity with Graph User.Read.All, GroupMember.Read.All, Application.Read.All
param adminGroupName string
param adminGroupObjectId string
@secure()
param bootstrapPassword string // required at creation by this API version; unusable once aad_auth_only is ON

resource mysql 'Microsoft.DBforMySQL/flexibleServers@2024-12-30' = {
  name: serverName
  location: location
  sku: {
    name: 'Standard_D2ds_v4'
    tier: 'GeneralPurpose'
  }
  identity: {
    type: 'UserAssigned'
    userAssignedIdentities: {
      '${serverIdentityId}': {}
    }
  }
  properties: {
    version: '8.0.21'
    administratorLogin: 'bootstrapadmin'
    administratorLoginPassword: bootstrapPassword
    storage: {
      storageSizeGB: 64
      autoGrow: 'Enabled'
    }
  }
}

resource entraAdmin 'Microsoft.DBforMySQL/flexibleServers/administrators@2024-12-30' = {
  parent: mysql
  name: 'ActiveDirectory'
  properties: {
    administratorType: 'ActiveDirectory'
    identityResourceId: serverIdentityId
    login: adminGroupName
    sid: adminGroupObjectId
    tenantId: tenant().tenantId
  }
}

resource entraOnly 'Microsoft.DBforMySQL/flexibleServers/configurations@2024-12-30' = {
  parent: mysql
  name: 'aad_auth_only'
  properties: {
    value: 'ON'
    source: 'user-override'
  }
  dependsOn: [entraAdmin]
}

The 2024-12-30 API still requires an administrator login and password at creation; after aad_auth_only is ON that login can't sign in. Keep the password out of parameter files (Key Vault reference or a generated value).

Network

As with PostgreSQL: private access (a subnet delegated to Microsoft.DBforMySQL/flexibleServers and a private DNS zone, network.delegatedSubnetResourceId and privateDnsZoneResourceId) or public access with firewall rules and optional private endpoints (groupId mysqlServer, zone privatelink.mysql.database.azure.com), chosen at creation (reference/postgresql/flexible-server.md for the shared constraints).

Versions

VersionStatusStandard support endsExtended support
5.7 (5.7.44)Retired upstreamSeptember 30, 2026Since October 1, 2026, to March 31, 2029
8.0 (8.0.46)GAJanuary 31, 2027February 1, 2027 to May 31, 2029
8.4 (8.4.9)GA——
9.5Preview (innovation release)——

Servers past standard support are enrolled in extended support automatically and billed per vCore-hour while running; nothing upgrades the major version for you. The 2024-12-30 REST spec's version enum still lists only 5.7 and 8.0.21.

Read this document as markdown — the same bytes an agent receives.