Version: 3.1
Last Updated: January 2026
The Platform Engineering Copilot supports three authentication modes:
| Mode | Use Case | Configuration |
|---|---|---|
| Azure CLI | Local development | UseManagedIdentity: false |
| Managed Identity | Production (ACI/AKS) | UseManagedIdentity: true |
| CAC/PIV | Azure Government | RequireCac: true |
# Azure Government
az cloud set --name AzureUSGovernment
az login
export AZURE_TENANT_ID=$(az account show --query tenantId -o tsv)
# Azure Commercial
az cloud set --name AzureCloud
az login
# Run MCP server
dotnet run --project src/Platform.Engineering.Copilot.Mcp✅ The application automatically uses your Azure CLI credentials.
For Azure deployments (ACI, AKS, App Service):
# Enable Managed Identity
az webapp identity assign \
--name your-app-name \
--resource-group your-rg
# Grant permissions
PRINCIPAL_ID=$(az webapp identity show \
--name your-app-name \
--resource-group your-rg \
--query principalId -o tsv)
az role assignment create \
--assignee $PRINCIPAL_ID \
--role "Reader" \
--scope "/subscriptions/your-subscription-id"Configuration:
{
"Gateway": {
"Azure": {
"UseManagedIdentity": true,
"CloudEnvironment": "AzureGovernment"
}
}
}CAC/PIV enables smart card authentication with On-Behalf-Of (OBO) flow for Azure operations under user identity.
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ Client + CAC │ │ MCP Server │ │ Azure │
│ Reader │ │ │ │ Government │
└───────┬────────┘ └───────┬────────┘ └───────┬────────┘
│ │ │
│ 1. CAC login (MSAL) │ │
│ │ │
│ 2. Bearer token ─────►│ │
│ │ 3. Validate JWT │
│ │ 4. Check amr=mfa/rsa │
│ │ │
│ │ 5. OBO exchange ─────►│
│ │◄───── ARM token ──────│
│ │ │
│◄─── Response ─────────│ 6. Azure ops as user │
MCP Server App:
# Create MCP app
az ad app create \
--display-name "Platform Engineering Copilot MCP" \
--sign-in-audience AzureADMyOrg \
--identifier-uris "api://platform-engineering-copilot"
MCP_APP_ID="<your-mcp-app-id>"
# Create client secret (store in Key Vault!)
az ad app credential reset --id $MCP_APP_ID --append
# Add ARM permission
az ad app permission add \
--id $MCP_APP_ID \
--api "797f4846-ba00-4fd7-ba43-dac1f8f63013" \
--api-permissions "41094075-9dad-400e-a0bd-54e686782033=Scope"
# Grant admin consent
az ad app permission admin-consent --id $MCP_APP_IDClient App:
az ad app create \
--display-name "Platform Engineering Copilot Client" \
--sign-in-audience AzureADMyOrg
CLIENT_APP_ID="<your-client-app-id>"
# Add MCP API permission
az ad app permission add \
--id $CLIENT_APP_ID \
--api $MCP_APP_ID \
--api-permissions <access_as_user-scope-id>=Scopeappsettings.json:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.us/",
"TenantId": "<your-tenant-id>",
"ClientId": "<mcp-app-id>",
"ClientSecret": "<store-in-keyvault>",
"Audience": "api://platform-engineering-copilot",
"RequireMfa": true,
"RequireCac": true,
"EnableUserTokenPassthrough": true
},
"Gateway": {
"Azure": {
"CloudEnvironment": "AzureGovernment",
"UseManagedIdentity": false,
"EnableUserTokenPassthrough": true
}
}
}Docker environment variables:
AZURE_AD_TENANT_ID=<your-tenant-id>
AZURE_AD_CLIENT_ID=<mcp-app-id>
AZURE_AD_CLIENT_SECRET=<secret>
AZURE_AD_REQUIRE_CAC=true
AZURE_AD_REQUIRE_MFA=true
AZURE_AD_ENABLE_USER_TOKEN_PASSTHROUGH=true# Get token via MSAL with CAC
TOKEN="<jwt-from-cac-login>"
# Test MCP endpoint
curl -X POST http://localhost:5100/invoke \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"method": "tools/list", "params": {}}'Expected logs:
[INF] ✅ JWT validated for user: john.doe@domain.mil
[INF] ✅ CAC/PIV authentication verified
[INF] 🔑 Created On-Behalf-Of credential
var app = PublicClientApplicationBuilder
.Create("<client-app-id>")
.WithAuthority(AzureCloudInstance.AzureUsGovernment, "<tenant-id>")
.Build();
var result = await app
.AcquireTokenInteractive(new[] { "api://platform-engineering-copilot/access_as_user" })
.ExecuteAsync();
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", result.AccessToken);| Property | Type | Default | Description |
|---|---|---|---|
Instance |
string | https://login.microsoftonline.us/ |
Azure AD instance |
TenantId |
string | - | Azure AD tenant ID |
ClientId |
string | - | MCP app registration ID |
ClientSecret |
string | - | MCP app secret (use Key Vault) |
Audience |
string | - | Expected audience in JWT |
RequireMfa |
bool | false |
Require MFA in token |
RequireCac |
bool | false |
Require CAC/PIV auth |
EnableUserTokenPassthrough |
bool | false |
Use OBO for Azure ops |
ValidIssuers |
string[] | [] |
Additional valid issuers |
| Property | Type | Default | Description |
|---|---|---|---|
CloudEnvironment |
string | AzureGovernment |
AzureGovernment or AzurePublicCloud |
UseManagedIdentity |
bool | false |
Use managed identity |
EnableUserTokenPassthrough |
bool | false |
Use user token for Azure |
SubscriptionId |
string | - | Default subscription |
TenantId |
string | - | Azure tenant ID |
| Error | Solution |
|---|---|
| "CAC/PIV authentication required" | Verify user logged in with CAC. Check amr claim contains mfa, rsa, or smartcard |
| "The audience is invalid" | Ensure client scope is api://platform-engineering-copilot/access_as_user |
| "AADSTS65001: Consent not granted" | Run az ad app permission admin-consent --id <mcp-app-id> |
| "No subscriptions found" | Run az login and verify permissions |
Decode your JWT at jwt.ms and check:
aud: Should matchAudienceconfigiss: Should be inValidIssuersamr: For CAC, should containmfaandrsa
Enable debug logging in appsettings.json:
{
"Logging": {
"LogLevel": {
"Platform.Engineering.Copilot.Mcp.Middleware": "Debug"
}
}
}- Store secrets in Azure Key Vault
- Enable HTTPS with valid certificate
- Configure Azure AD Conditional Access
- Enable Azure AD sign-in logs
- Set up monitoring alerts
- Conduct security review
- DEPLOYMENT.md - Deployment guide
- ARCHITECTURE.md - System architecture
- Azure Government Docs
- On-Behalf-Of Flow