Skip to main content

Azure PostgreSQL Auth client library for Python

The Azure PostgreSQL Auth client library provides Microsoft Entra ID authentication for Python database drivers connecting to Azure Database for PostgreSQL. It supports psycopg2, psycopg3, and SQLAlchemy with automatic token management and connection pooling.

Source code | Package (PyPI) | Samples

Getting started

Prerequisites

  • Python 3.9 or later
  • An Azure subscription
  • An Azure Database for PostgreSQL Server instance with Entra ID authentication enabled
  • A credential object that implements the TokenCredential interface

Install the package

Install the core package:

pip install azure-postgresql-auth

Install with driver-specific extras:

# For psycopg3 (recommended for new projects)
pip install "azure-postgresql-auth[psycopg3]"

# For psycopg2 (legacy support)
pip install "azure-postgresql-auth[psycopg2]"

# For SQLAlchemy
pip install "azure-postgresql-auth[sqlalchemy]"

# For SQLAlchemy with asyncpg
pip install "azure-postgresql-auth[sqlalchemy,asyncpg]"

Install Azure Identity for credential support:

pip install azure-identity

Note: If using async credentials in azure.identity.aio, you must first install an async transport, such as aiohttp:

pip install aiohttp

Key concepts

Authentication flow

  1. Token Acquisition: Uses Azure Identity credentials to acquire access tokens from Microsoft Entra ID.
  2. Automatic Refresh: Tokens are acquired for each new database connection.
  3. Secure Transport: Tokens are passed as passwords in PostgreSQL connection strings over SSL.
  4. Server Validation: Azure Database for PostgreSQL validates the token and establishes the authenticated connection.
  5. User Mapping: The token's user principal name (UPN) is mapped to a PostgreSQL user for authorization.

Token scopes

The library requests the following OAuth2 scopes:

  • Database scope: https://ossrdbms-aad.database.windows.net/.default (primary)
  • Management scope: https://management.azure.com/.default (fallback for managed identities)

Driver support

  • psycopg3: Modern PostgreSQL driver (recommended for new projects) — sync and async support
  • psycopg2: Legacy PostgreSQL driver — synchronous only
  • SQLAlchemy: ORM/Core interface using event listeners — sync and async engine support

Security features

  • Token-based authentication: No passwords stored or transmitted
  • Automatic expiration: Tokens expire and are refreshed automatically
  • SSL enforcement: All connections require SSL encryption
  • Principle of least privilege: Only database-specific scopes are requested

Examples

Configuration

The samples use environment variables to configure database connections. Copy .env.example into a .env file in the same directory as the sample and update the variables:

POSTGRES_SERVER=<your-server.postgres.database.azure.com>
POSTGRES_DATABASE=<your_database_name>

psycopg2 — Connection pooling

from azure_postgresql_auth.psycopg2 import EntraConnection
from azure.identity import DefaultAzureCredential
from psycopg2 import pool
from functools import partial

credential = DefaultAzureCredential()
connection_factory = partial(EntraConnection, credential=credential)

connection_pool = pool.ThreadedConnectionPool(
    minconn=1,
    maxconn=5,
    host="your-server.postgres.database.azure.com",
    database="your_database",
    connection_factory=connection_factory,
)
conn = connection_pool.getconn()
with conn.cursor() as cur:
    cur.execute("SELECT 1")

psycopg2 — Direct connection

from azure_postgresql_auth.psycopg2 import EntraConnection
from azure.identity import DefaultAzureCredential

with EntraConnection(
    "postgresql://your-server.postgres.database.azure.com:5432/your_database",
    credential=DefaultAzureCredential(),
) as conn:
    with conn.cursor() as cur:
        cur.execute("SELECT 1")

psycopg3 — Synchronous connection

from azure_postgresql_auth.psycopg3 import EntraConnection
from azure.identity import DefaultAzureCredential
from psycopg_pool import ConnectionPool

with ConnectionPool(
    conninfo="postgresql://your-server.postgres.database.azure.com:5432/your_database",
    connection_class=EntraConnection,
    kwargs={"credential": DefaultAzureCredential()},
    min_size=1,
    max_size=5,
) as pg_pool:
    with pg_pool.connection() as conn:
        with conn.cursor() as cur:
            cur.execute("SELECT 1")

psycopg3 — Asynchronous connection

from azure_postgresql_auth.psycopg3 import AsyncEntraConnection
from azure.identity.aio import DefaultAzureCredential
from psycopg_pool import AsyncConnectionPool

async with AsyncConnectionPool(
    conninfo="postgresql://your-server.postgres.database.azure.com:5432/your_database",
    connection_class=AsyncEntraConnection,
    kwargs={"credential": DefaultAzureCredential()},
    min_size=1,
    max_size=5,
) as pg_pool:
    async with pg_pool.connection() as conn:
        async with conn.cursor() as cur:
            await cur.execute("SELECT 1")

SQLAlchemy — Synchronous engine

For more information, see SQLAlchemy's documentation on controlling how parameters are passed to the DBAPI connect function.

from sqlalchemy import create_engine
from azure_postgresql_auth.sqlalchemy import enable_entra_authentication
from azure.identity import DefaultAzureCredential

engine = create_engine(
    "postgresql+psycopg://your-server.postgres.database.azure.com/your_database",
    connect_args={"credential": DefaultAzureCredential()},
)
enable_entra_authentication(engine)

with engine.connect() as conn:
    result = conn.execute(text("SELECT 1"))

SQLAlchemy — Asynchronous engine

from sqlalchemy.ext.asyncio import create_async_engine
from azure_postgresql_auth.sqlalchemy import enable_entra_authentication_async
from azure.identity import DefaultAzureCredential

engine = create_async_engine(
    "postgresql+psycopg://your-server.postgres.database.azure.com/your_database",
    connect_args={"credential": DefaultAzureCredential()},
)
enable_entra_authentication_async(engine)

async with engine.connect() as conn:
    result = await conn.execute(text("SELECT 1"))

SQLAlchemy — Asynchronous asyncpg engine

Use create_asyncpg_engine when the application uses asyncpg and an asynchronous Azure Identity credential. The helper acquires Entra tokens without blocking the event loop whenever the SQLAlchemy pool opens a physical connection.

from azure.identity.aio import DefaultAzureCredential
from azure_postgresql_auth.sqlalchemy import create_asyncpg_engine

credential = DefaultAzureCredential()
engine = create_asyncpg_engine(
    "postgresql+asyncpg://your-server.postgres.database.azure.com/your_database?sslmode=require",
    credential,
)

async with engine.connect() as conn:
    result = await conn.execute(text("SELECT 1"))

await engine.dispose()
await credential.close()

Troubleshooting

Authentication errors

If you get "password authentication failed", ensure your Azure identity has been granted access to the database:

-- Run as a database administrator
CREATE ROLE "your-user@your-domain.com" WITH LOGIN;
GRANT ALL PRIVILEGES ON DATABASE your_database TO "your-user@your-domain.com";

Connection timeouts

Increase the connection timeout for slow networks:

conn = EntraConnection.connect(
    "postgresql://server:5432/db",
    credential=DefaultAzureCredential(),
    connect_timeout=30,
)

Windows async compatibility

On Windows, you may need to set the event loop policy for async usage:

import asyncio
import sys

if sys.platform == "win32":
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

Debug logging

Enable debug logging to troubleshoot authentication issues:

import logging
logging.basicConfig(level=logging.DEBUG)

Next steps

Additional documentation

For more information about Azure Database for PostgreSQL Entra ID authentication, see the Azure documentation.

Samples

Explore sample code for psycopg2, psycopg3, and SQLAlchemy.

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.

When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.

Impressions

Release History

1.1.0 (2026-08-26)

Features Added

  • Added create_asyncpg_engine for SQLAlchemy async engines using asyncpg and asynchronous Microsoft Entra credentials.

Bugs Fixed

  • Fixed SQLAlchemy connection pools failing to create subsequent connections when using Entra authentication.

1.0.2 (2026-04-28)

Bugs Fixed

  • Removed dependency on DefaultAzureCredential in source library
  • Fixed get_entra_conninfo_async and get_entra_token_async closing the credential by using it as a context manager

Other Changes

  • Bumped minimum dependency on azure-core to >=1.31.0

1.0.1 (2025-11-26)

Other Changes

  • Update author to Microsoft

1.0.0 (2025-11-14)

Features Added

  • Initial public release

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

azure_postgresql_auth-1.1.0.tar.gz (24.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

azure_postgresql_auth-1.1.0-py3-none-any.whl (19.3 kB view details)

Uploaded Python 3

File details

Details for the file azure_postgresql_auth-1.1.0.tar.gz.

File metadata

  • Download URL: azure_postgresql_auth-1.1.0.tar.gz
  • Upload date:
  • Size: 24.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: RestSharp/106.13.0.0

File hashes

Hashes for azure_postgresql_auth-1.1.0.tar.gz
Algorithm Hash digest
SHA256 4f66742b9a7a40a8e586558311cbc77f5d7b83e9ac37828ed360f6b664054cca
MD5 22cea1712d9cff13399922660e74a80e
BLAKE2b-256 0fab317881a1a168bdb87dd69233fd7a4aad162ee20c48f4989cf6d82a768990

See more details on using hashes here.

File details

Details for the file azure_postgresql_auth-1.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for azure_postgresql_auth-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f05d9ec601bb74b46f23468a65d1817a69b5a208d41ef1d022200137a5ed7ce4
MD5 a4518c8c8ad93769f2752b01611ebdef
BLAKE2b-256 1379268b9affeae62be6db1e9f79a4521245a8ab0dfdd6f4b526e1fc847ae498

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 files

1.0.2

2 files

1.0.1

2 files

1.0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page