Skip to content

docs: Guidance for higher-level SDKs to consume MSAL mTLS PoP#932

Closed
gladjohn wants to merge 2 commits into
devfrom
gladjohn/sdk-integration-guidance
Closed

docs: Guidance for higher-level SDKs to consume MSAL mTLS PoP#932
gladjohn wants to merge 2 commits into
devfrom
gladjohn/sdk-integration-guidance

Conversation

@gladjohn

Copy link
Copy Markdown
Contributor

Summary

Adds documentation explaining how higher-level SDKs (e.g., azure-identity, azure-sdk-for-python) can integrate with the MSI v2 mTLS Proof-of-Possession API.

Contents

  • Public API surface and return value contract
  • WindowsCertificate object as the bridge between token acquisition and transport
  • Step-by-step integration pattern (credential → auth header → transport → DX)
  • End-user experience goal (zero mTLS awareness)
  • .NET comparison table
  • Minimum 20-line integration example
  • Transport architecture options for azure-core
  • Future OpenSSL 3 CNG Provider path

Related

gladjohn and others added 2 commits June 20, 2026 17:04
…roof

End-to-end mTLS Proof-of-Possession for Managed Identity v2 on Windows
Azure VMs with Credential Guard / KeyGuard.

## Core (msal package)
- msal/windows_certificate.py: Python X509Certificate2 (NCRYPT_KEY_HANDLE wrapper)
- msal/msi_v2.py: Full MSI v2 flow (KeyGuard key, CSR, attestation, issuecredential, mTLS token)
- msal/managed_identity.py: Public API (acquire_token_for_client + mtls_proof_of_possession)

## Separate packages
- msal-schannel-transport/: WinHTTP/SChannel for downstream mTLS (bypasses OpenSSL)
- msal-key-attestation/: MAA attestation wrapper (DLL from NuGet: Microsoft.Azure.Security.KeyGuardAttestation v1.1.5)

## Dev app + docs
- sample/devapp_msi_v2_mtls/app.py: Uses ONLY public MSAL API
- docs/mTLS-PoP-Architecture-Decision.md: Why WinHTTP (OpenSSL CNG gap)

## E2E Results (MSIV2 VM, June 2026)
- Token: mtls_pop ✓ | Binding: cnf.x5t#S256 MATCH ✓ | Downstream: HTTP 200 ✓

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Explains how azure-identity and other SDKs can integrate with the
MSI v2 mTLS Proof-of-Possession API exposed via PR #931.

Covers:
- Public API surface and return value contract
- WindowsCertificate object usage
- Step-by-step integration pattern (credential -> transport)
- End-user DX goal (zero mTLS awareness)
- .NET comparison
- Transport architecture options
- Future OpenSSL 3 CNG Provider path

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 21, 2026 13:33
@gladjohn gladjohn requested a review from a team as a code owner June 21, 2026 13:33
@property
def thumbprint_sha1(self) -> str:
"""SHA-1 thumbprint of the certificate (hex uppercase)."""
return hashlib.sha1(self._cert_der).hexdigest().upper()
return 1

if "error" in result:
print(f" ✗ Error: {result['error']}")

if "error" in result:
print(f" ✗ Error: {result['error']}")
print(f" {result.get('error_description', '')}")
token_type = result.get("token_type", "unknown")
expires_in = result.get("expires_in", 0)

print(f" ✓ access_token: {access_token[:30]}...")
expires_in = result.get("expires_in", 0)

print(f" ✓ access_token: {access_token[:30]}...")
print(f" ✓ token_type: {token_type}")
auth_header = f"{token_type} {access_token}"

print(f" URL: {downstream_url}")
print(f" Authorization: {token_type} <token>")
Comment thread sample/msi_v2_sample.py
thumbprint = result.get("cert_thumbprint_sha256", "")

print("Token acquired successfully!")
print(f" token_type: {token_type}")
Comment thread sample/msi_v2_sample.py

print("Token acquired successfully!")
print(f" token_type: {token_type}")
print(f" expires_in: {expires_in} seconds")
Comment thread sample/msi_v2_sample.py
print("Token acquired successfully!")
print(f" token_type: {token_type}")
print(f" expires_in: {expires_in} seconds")
print(f" thumbprint: {thumbprint[:16]}..." if thumbprint else " thumbprint: (none)")
print(f"\n AKV response: HTTP {response.status_code}")
if response.status_code == 200:
body = response.json()
print(f" Secret retrieved: {E2E_SECRET_NAME}")

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds an end-to-end MSI v2 mTLS Proof-of-Possession (PoP) implementation for Windows (KeyGuard/Credential Guard), plus supporting transport + attestation packages, tests, samples, and SDK integration documentation so higher-level SDKs can consume the feature.

Changes:

  • Introduces the MSI v2 flow (msal.msi_v2) and a Windows-backed certificate handle type (WindowsCertificate) for mTLS PoP.
  • Adds two auxiliary packages: msal-key-attestation (MAA/KeyGuard attestation JWT) and msal-schannel-transport (WinHTTP/SChannel downstream mTLS).
  • Adds comprehensive unit tests, an opt-in Windows E2E test, samples, and integration guidance docs for SDK authors.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
tests/test_msi_v2.py Unit tests for cnf binding verification, IMDS helpers, and cert caching/gating behaviors.
tests/test_e2e_mtls_pop.py Opt-in Windows E2E test: acquire mTLS PoP token and call Key Vault over mTLS via SChannel transport.
sample/msi_v2_sample.py Runnable sample demonstrating MSI v2 token acquisition and header formation.
sample/MSI_V2_GUIDE.md Setup/usage guide for MSI v2 + attestation package usage.
sample/devapp_msi_v2_mtls/app.py Dev app demonstrating full public-API flow and downstream call using SchannelSession.
msal/windows_certificate.py Adds WindowsCertificate object for platform-backed cert + non-exportable key handles.
msal/msi_v2.py Adds the MSI v2 implementation: KeyGuard key mgmt, CSR, IMDS, cert binding, WinHTTP/SChannel token acquisition, and cert cache.
msal/managed_identity.py Adds MSI v2 gating parameters + MsiV2Error and routes into msal.msi_v2.obtain_token.
msal/init.py Exposes MsiV2Error and WindowsCertificate at package level.
msal-schannel-transport/pyproject.toml Defines the downstream WinHTTP/SChannel transport package metadata.
msal-schannel-transport/msal_schannel_transport/session.py Implements SchannelSession and response/error types for downstream mTLS calls.
msal-schannel-transport/msal_schannel_transport/init.py Package exports for msal-schannel-transport.
msal-key-attestation/pyproject.toml Defines the KeyGuard attestation package metadata and dynamic version config.
msal-key-attestation/msal_key_attestation/attestation.py Implements AttestationClientLib.dll bindings + JWT caching and provider factory.
msal-key-attestation/MANIFEST.in sdist manifest for the attestation package.
msal-key-attestation/LICENSE License file for the attestation package.
docs/mTLS-PoP-Architecture-Decision.md Rationale/decision record for WinHTTP/SChannel vs OpenSSL-provider approaches.
docs/MSI_V2_API.md API reference for MSI v2 parameters, return contract, errors, and usage.
docs/Guidance-for-Higher-Level-SDKs-to-Consume-MSAL.md Higher-level SDK integration guide (azure-identity/azure-core patterns).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +57 to +60
# Properties
cert.thumbprint_sha256 # str: base64url SHA-256 thumbprint
cert.pem # str: PEM-encoded public certificate
cert.subject # str: certificate subject
Comment on lines +311 to +320
# Downstream call
session = SchannelSession()
response = session.get(
"https://tokenbinding.vault.azure.net/secrets/boundsecret/?api-version=2015-06-01",
headers={
"Authorization": f"{result['token_type']} {result['access_token']}",
"x-ms-tokenboundauth": "true",
},
client_certificate=result["binding_certificate"],
)
Comment on lines +6 to +10
name = "msal-schannel-transport"
version = "0.1.0"
description = "Windows SChannel/WinHTTP HTTP transport for mTLS with non-exportable keys"
readme = "README.md"
license = {text = "MIT"}
Comment on lines +8 to +11
description = "KeyGuard attestation support for MSAL Python MSI v2 (mTLS PoP). Provides Python bindings for AttestationClientLib.dll (Windows Credential Guard key attestation)."
readme = "README.md"
license = "MIT"
requires-python = ">=3.9"
Comment thread msal/managed_identity.py
Comment on lines +339 to +344
# Auto-discover attestation provider from msal-key-attestation
attestation_token_provider = None
try:
from msal_key_attestation import create_attestation_provider
attestation_token_provider = create_attestation_provider()
except ImportError as exc:
Comment on lines +34 to +40
Repository = "https://github.com/AzureAD/microsoft-authentication-library-for-python"

[tool.setuptools.dynamic]
version = {attr = "msal_key_attestation.__version__"}

[tool.setuptools.packages.find]
exclude = ["tests", "tests.*"]
Comment on lines +166 to +175
# Option A: Use msal-schannel-transport directly
from msal_schannel_transport import SchannelSession

session = SchannelSession()
response = session.get(
url,
headers=headers,
client_certificate=credential._binding_certificate,
)
```
Comment thread msal/msi_v2.py
Comment on lines +5 to +12
"""
MSI v2 (IMDSv2) Managed Identity flow — Windows KeyGuard + SChannel mTLS PoP.

This module implements the MSI v2 token acquisition path using Windows native APIs
via ctypes:
- CNG/NCrypt: create/open a KeyGuard-protected per-boot RSA key (non-exportable)
- Minimal DER/PKCS#10: build a CSR signed with RSA-PSS/SHA256
- IMDS: call getplatformmetadata + issuecredential
@gladjohn gladjohn closed this Jun 21, 2026
@gladjohn gladjohn deleted the gladjohn/sdk-integration-guidance branch June 21, 2026 13:46
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.

3 participants