Skip to content

feat(mssql): bundle MSAL4J for Azure AD auth; fix encrypt= default (#1611)#1753

Merged
dimitri merged 1 commit into
mainfrom
fix/mssql-azure-ad-msal4j
Jul 3, 2026
Merged

feat(mssql): bundle MSAL4J for Azure AD auth; fix encrypt= default (#1611)#1753
dimitri merged 1 commit into
mainfrom
fix/mssql-azure-ad-msal4j

Conversation

@dimitri

@dimitri dimitri commented Jul 3, 2026

Copy link
Copy Markdown
Owner

Problem

Azure SQL connections require Azure AD authentication, but the pgloader v4 JAR was missing MSAL4J — the library that mssql-jdbc delegates to for ActiveDirectoryPassword, ActiveDirectoryServicePrincipal, and related modes (reported in #1611).

A second issue: the native mssql:// URI always emitted ;encrypt=false in the synthesised JDBC URL, even when the user passed encrypt=true via the query string. This silently forced unencrypted connections to Azure SQL.

Changes

deps.edn — add com.microsoft.azure/msal4j 1.14.1, the version mssql-jdbc 12.6.1 declares as an optional dependency. Enables:

  • ActiveDirectoryPassword — Azure AD username + password
  • ActiveDirectoryServicePrincipal — client-id + secret, for automation/CI

ActiveDirectoryManagedIdentity works without MSAL4J (Azure IMDS). ActiveDirectoryInteractive opens a browser and is fundamentally incompatible with a CLI tool — it remains unsupported.

ast.clj — suppress the ;encrypt=false default in the synthesised JDBC URL when the query string already contains encrypt=. Previously, mssql://host/db?encrypt=true produced ...;encrypt=false;encrypt=true, relying on last-value-wins behaviour that isn't guaranteed across driver versions.

ast_test.clj — three new test cases: encrypt= suppression, authentication= passthrough, MSAL4J classpath assertion.

docs/ref/mssql.rst — new Azure SQL / Azure Active Directory Authentication section with working examples for all three supported modes and an explicit note that ActiveDirectoryInteractive cannot be used.

Usage (after this PR)

-- Azure AD username + password
FROM "jdbc:sqlserver://myserver.database.windows.net:1433;databaseName=mydb;authentication=ActiveDirectoryPassword;user=user@tenant.onmicrosoft.com;password=secret;encrypt=true"

-- Service principal (CI/automation)
FROM "jdbc:sqlserver://myserver.database.windows.net:1433;databaseName=mydb;authentication=ActiveDirectoryServicePrincipal;AADSecurePrincipalId=<client-id>;AADSecurePrincipalSecret=<client-secret>;encrypt=true"

-- Managed identity (Azure VM / App Service)
FROM "jdbc:sqlserver://myserver.database.windows.net:1433;databaseName=mydb;authentication=ActiveDirectoryManagedIdentity;encrypt=true"

Closes #1611.

deps.edn:
  Add com.microsoft.azure/msal4j 1.14.1 (the version mssql-jdbc 12.6.1
  declares as optional). This enables non-interactive Azure AD auth modes
  that the JDBC driver delegates to MSAL4J:
    - ActiveDirectoryPassword      (username + password via Azure AD)
    - ActiveDirectoryServicePrincipal (client-id + secret, for automation)
  ActiveDirectoryManagedIdentity works without MSAL4J (token from the
  Azure IMDS endpoint). ActiveDirectoryInteractive opens a browser and
  is fundamentally incompatible with a CLI tool — it remains unsupported.

ast.clj:
  The native mssql:// URI was unconditionally emitting ;encrypt=false in
  the synthesised JDBC URL, even when the caller passed encrypt=true via
  the query string. This caused Azure SQL connections to silently use
  an unencrypted channel because the driver picks the FIRST occurrence of
  a duplicate parameter on some versions.
  Fix: suppress the ;encrypt=false default when the query string already
  contains encrypt=.

ast_test.clj:
  - Assert encrypt=false is suppressed when encrypt=true is in the query
  - Assert authentication= and encrypt= pass through without duplication
  - Assert com.microsoft.aad.msal4j is loadable from the classpath

docs/ref/mssql.rst:
  New 'Azure SQL / Azure Active Directory Authentication' section with
  working examples for ActiveDirectoryPassword, ActiveDirectoryServicePrincipal,
  and ActiveDirectoryManagedIdentity, plus an explicit note that
  ActiveDirectoryInteractive cannot be used with pgloader.

Closes #1611.
@dimitri dimitri merged commit a054678 into main Jul 3, 2026
37 checks passed
@dimitri dimitri deleted the fix/mssql-azure-ad-msal4j branch July 3, 2026 21:21
dimitri added a commit that referenced this pull request Jul 6, 2026
…orkloadIdentity auth (#1755)

Closes #1754

mssql-jdbc 12.6.1 supports ActiveDirectoryDefault, ActiveDirectoryAzCli,
and ActiveDirectoryWorkloadIdentity but delegates them to the azure-identity
library (com.azure:azure-identity), which was not previously bundled.  Users
hitting these modes got:

  java.lang.NoClassDefFoundError: com/azure/identity/DefaultAzureCredentialBuilder

Add azure-identity 1.11.1 (the version mssql-jdbc 12.6.1 was certified
against) to deps.edn so all non-browser-dependent Entra ID auth modes work
out of the box.  The SLF4J version conflict flagged by downstream workarounds
(miljodir/DataEngineerPersona#6) does not affect the uberjar: Maven resolves
to the newer slf4j-api already present via logback-classic.

Also update docs/ref/mssql.rst:
- Add ActiveDirectoryDefault (developer az login workflow, WSL2-safe),
  ActiveDirectoryAzCli, ActiveDirectoryWorkloadIdentity with examples
- Deprecation note on ActiveDirectoryPassword (blocked by MFA enforcement
  in most modern Entra tenants, returns AADSTS50076)
- Correct the ActiveDirectoryInteractive note: it works on native Windows /
  macOS / Linux desktops but fails in WSL2 (linux_xdg_open_failed) and
  headless environments; ActiveDirectoryDefault is the practical alternative
- Quick-reference table of all auth modes and their use cases

Add classpath assertion test for DefaultAzureCredentialBuilder, mirroring
the existing MSAL4J test added in #1753.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to connect to Azure SQLServer with Pgloader

1 participant