- Add Legal Office of the Master seal (SVG design with Maltese Cross, scales of justice, legal scroll) - Create legal-office-manifest-template.json for Legal Office credentials - Update SEAL_MAPPING.md and DESIGN_GUIDE.md with Legal Office seal documentation - Complete Azure CDN infrastructure deployment: - Resource group, storage account, and container created - 17 PNG seal files uploaded to Azure Blob Storage - All manifest templates updated with Azure URLs - Configuration files generated (azure-cdn-config.env) - Add comprehensive Azure CDN setup scripts and documentation - Fix manifest URL generation to prevent double slashes - Verify all seals accessible via HTTPS
13 KiB
Microsoft Entra VerifiedID Integration
This document describes the integration with Microsoft Entra VerifiedID for verifiable credential issuance and verification.
Overview
The Order integrates with Microsoft Entra VerifiedID to:
- Issue verifiable credentials through Microsoft's managed service
- Verify verifiable credentials issued by Microsoft Entra VerifiedID
- Bridge eIDAS verification with Microsoft Entra VerifiedID credential issuance
- Integrate with Azure Logic Apps for workflow orchestration
Architecture
┌─────────────┐ ┌──────────────┐ ┌─────────────────────┐
│ Client │────▶│ Identity │────▶│ Entra VerifiedID │
│ │ │ Service │ │ API │
└─────────────┘ └──────────────┘ └─────────────────────┘
│
│
▼
┌──────────────┐
│ eIDAS Bridge │
│ │
│ 1. Verify │
│ 2. Issue VC │
└──────────────┘
│
▼
┌──────────────┐
│ Logic Apps │
│ (Optional) │
└──────────────┘
Setup
1. Microsoft Entra VerifiedID Configuration
-
Create Azure AD App Registration
- Go to Azure Portal → Azure Active Directory → App registrations
- Create a new registration
- Note the Application (client) ID and Directory (tenant) ID
-
Configure API Permissions
- Add permission:
Verifiable Credentials Service - VerifiableCredential.Create.All - Add permission:
Verifiable Credentials Service - VerifiableCredential.Verify.All - Grant admin consent
- Add permission:
-
Create Client Secret
- Go to Certificates & secrets
- Create a new client secret
- Note the secret value (it's only shown once)
-
Create Credential Manifest
- Go to Azure Portal → Verified ID
- Create a new credential manifest
- Note the Manifest ID
2. Environment Variables
Add the following to your .env file:
# Microsoft Entra VerifiedID
ENTRA_TENANT_ID=your-tenant-id
ENTRA_CLIENT_ID=your-client-id
ENTRA_CLIENT_SECRET=your-client-secret
ENTRA_CREDENTIAL_MANIFEST_ID=your-manifest-id
# eIDAS (for bridge functionality)
EIDAS_PROVIDER_URL=https://your-eidas-provider.com
EIDAS_API_KEY=your-eidas-api-key
# Azure Logic Apps (optional)
AZURE_LOGIC_APPS_WORKFLOW_URL=https://your-logic-app.azurewebsites.net
AZURE_LOGIC_APPS_ACCESS_KEY=your-access-key
AZURE_LOGIC_APPS_MANAGED_IDENTITY_CLIENT_ID=your-managed-identity-client-id
API Endpoints
Issue Credential via Entra VerifiedID
POST /vc/issue/entra
Request body:
{
"claims": {
"email": "user@example.com",
"name": "John Doe",
"role": "member"
},
"pin": "1234",
"callbackUrl": "https://your-app.com/callback"
}
Response:
{
"requestId": "abc123",
"url": "https://verifiedid.did.msidentity.com/...",
"qrCode": "data:image/png;base64,...",
"expiry": 3600
}
Verify Credential via Entra VerifiedID
POST /vc/verify/entra
Request body:
{
"credential": {
"id": "vc:123",
"type": ["VerifiableCredential", "IdentityCredential"],
"issuer": "did:web:...",
"credentialSubject": { ... },
"proof": { ... }
}
}
Response:
{
"verified": true
}
eIDAS Verification with Entra Issuance
POST /eidas/verify-and-issue
This endpoint:
- Verifies the eIDAS signature
- Issues a verifiable credential via Microsoft Entra VerifiedID
- Optionally triggers Azure Logic Apps workflow
Request body:
{
"document": "base64-encoded-document",
"userId": "user-123",
"userEmail": "user@example.com",
"pin": "1234"
}
Response:
{
"verified": true,
"credentialRequest": {
"requestId": "abc123",
"url": "https://verifiedid.did.msidentity.com/...",
"qrCode": "data:image/png;base64,..."
}
}
Usage Examples
TypeScript Client
import { EntraVerifiedIDClient } from '@the-order/auth';
const client = new EntraVerifiedIDClient({
tenantId: process.env.ENTRA_TENANT_ID!,
clientId: process.env.ENTRA_CLIENT_ID!,
clientSecret: process.env.ENTRA_CLIENT_SECRET!,
credentialManifestId: process.env.ENTRA_CREDENTIAL_MANIFEST_ID!,
});
// Issue credential
const credential = await client.issueCredential({
claims: {
email: 'user@example.com',
name: 'John Doe',
},
pin: '1234',
});
// Verify credential
const verified = await client.verifyCredential(credential);
eIDAS Bridge
import { EIDASToEntraBridge } from '@the-order/auth';
const bridge = new EIDASToEntraBridge({
entraVerifiedID: {
tenantId: process.env.ENTRA_TENANT_ID!,
clientId: process.env.ENTRA_CLIENT_ID!,
clientSecret: process.env.ENTRA_CLIENT_SECRET!,
credentialManifestId: process.env.ENTRA_CREDENTIAL_MANIFEST_ID!,
},
eidas: {
providerUrl: process.env.EIDAS_PROVIDER_URL!,
apiKey: process.env.EIDAS_API_KEY!,
},
});
// Verify eIDAS and issue credential
const result = await bridge.verifyAndIssue(
document,
userId,
userEmail,
pin
);
Azure Logic Apps Integration
The integration supports optional Azure Logic Apps workflows for:
- Document processing
- eIDAS verification workflows
- VC issuance workflows
Logic App Workflow Example
{
"definition": {
"triggers": {
"eidas-verification": {
"type": "Request",
"inputs": {
"schema": {
"type": "object",
"properties": {
"documentId": { "type": "string" },
"userId": { "type": "string" },
"eidasProviderUrl": { "type": "string" }
}
}
}
}
},
"actions": {
"process-eidas": {
"type": "Http",
"inputs": {
"method": "POST",
"uri": "@{triggerBody()['eidasProviderUrl']}/verify",
"body": {
"documentId": "@{triggerBody()['documentId']}"
}
}
}
}
}
}
Security Considerations
- Client Secrets: Store securely in Azure Key Vault or similar
- Access Tokens: Automatically cached and refreshed
- PIN Protection: Optional PIN for credential issuance
- Certificate Validation: Full certificate chain validation for eIDAS
- Managed Identity: Use Azure Managed Identity when possible instead of client secrets
Troubleshooting
Common Issues
-
"Failed to get access token"
- Check tenant ID, client ID, and client secret
- Verify API permissions are granted
- Check that admin consent is provided
-
"Credential manifest ID is required"
- Ensure
ENTRA_CREDENTIAL_MANIFEST_IDis set - Verify the manifest exists in Azure Portal
- Ensure
-
"eIDAS verification failed"
- Check eIDAS provider URL and API key
- Verify network connectivity to eIDAS provider
- Check certificate validity
Enhanced Features
Retry Logic
The integration includes automatic retry logic for transient failures:
- Configurable retries: Default 3 retries with exponential backoff
- Retryable errors: 429 (rate limit), 500, 502, 503, 504
- Backoff strategy: Exponential backoff with configurable delays
import { EnhancedEntraVerifiedIDClient } from '@the-order/auth';
const client = new EnhancedEntraVerifiedIDClient(config, {
maxRetries: 3,
initialDelayMs: 1000,
maxDelayMs: 10000,
backoffMultiplier: 2,
});
Multi-Manifest Support
Support for multiple credential manifests:
# Environment variable (JSON format)
ENTRA_MANIFESTS='{"default":"manifest-id-1","diplomatic":"manifest-id-2","judicial":"manifest-id-3"}'
// Issue credential with specific manifest
await client.issueCredential({
claims: { ... },
manifestName: 'diplomatic', // Uses diplomatic manifest
});
Webhook/Callback Handling
Automatic webhook processing for issuance status updates:
POST /vc/entra/webhook
The webhook endpoint:
- Receives status updates from Entra VerifiedID
- Updates credential status in database
- Publishes events for downstream processing
- Records metrics for monitoring
GET /vc/entra/status/:requestId
Manual status check endpoint (polling fallback).
Rate Limiting
Entra-specific rate limiting to prevent API quota exhaustion:
# Environment variables
ENTRA_RATE_LIMIT_ISSUANCE=10 # Per minute
ENTRA_RATE_LIMIT_VERIFICATION=20 # Per minute
ENTRA_RATE_LIMIT_STATUS_CHECK=30 # Per minute
ENTRA_RATE_LIMIT_GLOBAL=50 # Per minute
Rate limits are applied automatically to all Entra endpoints.
Monitoring & Metrics
Comprehensive Prometheus metrics:
entra_api_requests_total- Total API requests by operation and statusentra_api_request_duration_seconds- Request duration histogramentra_credentials_issued_total- Credentials issued by manifest and statusentra_issuance_duration_seconds- Issuance duration histogramentra_credentials_verified_total- Verification resultsentra_webhooks_received_total- Webhook events receivedentra_active_requests- Currently active requests gauge
Access metrics at /metrics endpoint.
Automated Setup Script
Use the automated setup script for Azure configuration:
./scripts/deploy/setup-entra-automated.sh
The script:
- Creates Azure AD App Registration
- Configures API permissions
- Creates client secrets
- Stores secrets in Azure Key Vault
- Generates environment file template
Testing
Unit Tests
cd packages/auth
pnpm test entra-verifiedid.test.ts
Integration Tests
Integration tests verify:
- Token management and caching
- Credential issuance flow
- Retry logic on failures
- Multi-manifest support
- Webhook processing
End-to-End Testing
- Set up test environment variables
- Create test credential manifest in Azure
- Run E2E test suite:
pnpm test:e2e entra
Deployment
Automated Deployment
-
Run setup script:
./scripts/deploy/setup-entra-automated.sh -
Update environment variables in all environments
-
Configure webhook URLs in Entra VerifiedID:
- Production:
https://api.theorder.org/vc/entra/webhook - Staging:
https://api-staging.theorder.org/vc/entra/webhook
- Production:
-
Verify integration:
curl -X POST https://api.theorder.org/vc/issue/entra \ -H "Content-Type: application/json" \ -d '{"claims": {"email": "test@example.com"}}'
Manual Deployment
Follow the manual steps in docs/deployment/DEPLOYMENT_STEPS_SUMMARY.md Phase 3.
Best Practices
- Use Enhanced Client: Always use
EnhancedEntraVerifiedIDClientfor production - Monitor Metrics: Set up alerts on error rates and latency
- Configure Rate Limits: Adjust based on your Entra API quota
- Webhook Security: Validate webhook signatures if Entra provides them
- Multi-Manifest: Use manifest names for different credential types
- Error Handling: Implement proper error handling and logging
- Retry Configuration: Tune retry settings based on your needs
Credential Images
Image Format Support
Yes, SVG files can be used! The integration includes automatic SVG-to-PNG conversion for Entra VerifiedID compatibility.
Officially Supported Formats
- PNG (Recommended) ✅
- JPG/JPEG ✅
- BMP ✅
- SVG (with automatic conversion) ✅
Using SVG Files
-
Automatic Conversion (Recommended):
import { prepareCredentialImage } from '@the-order/auth'; const image = await prepareCredentialImage(svgData, 'svg'); // Automatically converts to PNG -
Manual Conversion:
./scripts/tools/convert-svg-to-png.sh logo.svg logo.png 200 200 -
Prepare All Images:
./scripts/tools/prepare-credential-images.sh
See ENTRA_CREDENTIAL_IMAGES.md for detailed image guide.