Certificate Authentication link
Learn how to use X.509 certificates for secure, passwordless authentication with Microsoft Entra ID.
Why Use Certificates? link
Advantages Over Client Secrets link
| Feature | Client Secret | Certificate |
|---|
| Security | Medium | High |
| Validity Period | Up to 2 years | Up to 3 years |
| Rotation | Manual | Automated possible |
| Compromise Risk | Higher | Lower |
| Audit Trail | Limited | Better |
When to Use Certificates link
✅ Use certificates for:
- Production service principals
- Long-running automated services
- High-security requirements
- Certificate-based infrastructure
⚠️ Stick with secrets for:
- Quick development/testing
- Short-lived projects
- Simple automation scripts
Getting Started link
Quick Example link
1
2
3
4
5
6
7
8
| # Create profile with certificate
entratool config create
# Select: Certificate
# Path: /path/to/certificate.pfx
# Password: ****
# Generate token
entratool get-token -p cert-profile
|
Certificate Types link
Most common format for certificates with private keys
1
2
3
4
5
6
7
8
| # File extension
certificate.pfx
certificate.p12
# Contains
- X.509 certificate
- Private key
- Optional: Certificate chain
|
Supported by:
- Windows Certificate Store
- macOS Keychain
- File-based storage
Text-based format (not directly supported)
To use PEM certificates, convert to PFX:
1
2
3
4
5
| openssl pkcs12 -export \
-in certificate.pem \
-inkey private-key.pem \
-out certificate.pfx \
-password pass:YourPassword
|
Creating Certificates link
Option 1: Self-Signed Certificate link
For development/testing only:
1
2
3
4
5
6
7
8
9
10
| # Windows (PowerShell)
$cert = New-SelfSignedCertificate `
-Subject "CN=MyApp" `
-CertStoreLocation "Cert:\CurrentUser\My" `
-KeyExportPolicy Exportable `
-KeySpec Signature `
-NotAfter (Get-Date).AddYears(2)
$password = ConvertTo-SecureString -String "YourPassword" -Force -AsPlainText
Export-PfxCertificate -Cert $cert -FilePath "certificate.pfx" -Password $password
|
1
2
3
4
5
6
7
8
9
10
11
| # macOS/Linux
openssl req -x509 -newkey rsa:4096 \
-keyout key.pem -out cert.pem \
-days 730 -nodes \
-subj "/CN=MyApp"
# Convert to PFX
openssl pkcs12 -export \
-in cert.pem -inkey key.pem \
-out certificate.pfx \
-password pass:YourPassword
|
Option 2: Certificate Authority (CA) link
For production:
- Generate Certificate Signing Request (CSR)
- Submit to your organization’s CA
- Receive signed certificate
- Combine with private key into PFX
Registering Certificates in Azure link
Upload Certificate to App Registration link
- Azure Portal → Azure Active Directory → App registrations
- Select your application
- Certificates & secrets → Certificates tab
- Click Upload certificate
- Select your
.cer or .pem file (public key only) - Add description
- Click Add
1
2
3
4
5
6
| # macOS/Linux
openssl pkcs12 -in certificate.pfx -nokeys -out certificate.cer
# Windows (PowerShell)
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("certificate.pfx", "password")
[System.IO.File]::WriteAllBytes("certificate.cer", $cert.Export("Cert"))
|
Configuring Profiles with Certificates link
Interactive Configuration link
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| entratool config create
# Prompts:
Profile name: production-service
Client ID: 12345678-1234-1234-1234-123456789abc
Tenant ID: 87654321-4321-4321-4321-cba987654321
Authentication method:
1. Client Secret
2. Certificate
Select: 2
Certificate path: /path/to/certificate.pfx
Certificate password: ****
Scope: https://graph.microsoft.com/.default
✓ Profile 'production-service' created successfully
|
Profile Structure link
profiles.json:
1
2
3
4
5
6
7
8
9
10
11
12
| {
"profiles": [
{
"name": "production-service",
"clientId": "12345678-1234-1234-1234-123456789abc",
"tenantId": "87654321-4321-4321-4321-cba987654321",
"certificatePath": "/path/to/certificate.pfx",
"useCertificate": true,
"scope": "https://graph.microsoft.com/.default"
}
]
}
|
Certificate password: Stored securely in platform-specific storage
Certificate Storage link
File-Based Storage link
Best practices:
1
2
3
4
5
6
7
8
9
10
11
| # Create secure directory
mkdir -p ~/.entratool/certs
chmod 700 ~/.entratool/certs
# Store certificate with restricted permissions
cp certificate.pfx ~/.entratool/certs/
chmod 600 ~/.entratool/certs/certificate.pfx
# Update profile with path
entratool config edit -p myprofile
# Certificate path: /Users/username/.entratool/certs/certificate.pfx
|
Windows Certificate Store link
Import certificate:
1
2
3
4
5
6
7
| # Import to Current User store
Import-PfxCertificate -FilePath certificate.pfx `
-CertStoreLocation Cert:\CurrentUser\My `
-Password (ConvertTo-SecureString -String "password" -AsPlainText -Force)
# List certificates
Get-ChildItem Cert:\CurrentUser\My
|
Reference by thumbprint in profile:
1
2
3
4
| {
"certificateThumbprint": "ABC123...",
"certificateStoreLocation": "CurrentUser"
}
|
macOS Keychain link
Import certificate:
1
2
3
4
| security import certificate.pfx -k login.keychain -P YourPassword
# List certificates
security find-identity -v -p codesigning
|
Using Certificates link
Generate Token link
1
| entratool get-token -p cert-profile
|
What happens:
- Profile loaded
- Certificate password retrieved from secure storage
- Certificate loaded from path or store
- Token generated using certificate authentication
- No password prompt if cached
Certificate Password Caching link
First use:
1
2
| entratool get-token -p cert-profile
# May prompt for certificate password
|
Subsequent uses:
1
2
| entratool get-token -p cert-profile
# No password prompt (cached securely)
|
Certificate Rotation link
Why Rotate Certificates? link
- Expiring certificates (check expiration dates)
- Security policy requirements
- Compromised certificates
- Annual/periodic rotation policies
Rotation Process link
1. Generate new certificate:
1
| # Generate new certificate (see "Creating Certificates" above)
|
2. Upload to Azure Portal:
- App registrations → Your app → Certificates & secrets
- Upload new certificate
- Don’t delete old certificate yet
3. Test new certificate:
1
2
3
4
5
6
7
| # Create test profile with new certificate
entratool config create
# Name: test-new-cert
# Certificate: /path/to/new-certificate.pfx
# Test token generation
entratool get-token -p test-new-cert
|
4. Update production profile:
1
2
3
4
5
6
7
| entratool config edit -p production-service
# Select: Certificate Path
# Enter: /path/to/new-certificate.pfx
# Enter password: ****
# Test production profile
entratool get-token -p production-service
|
5. Remove old certificate from Azure:
- App registrations → Your app → Certificates & secrets
- Delete old certificate
Automated Rotation Script link
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| #!/bin/bash
set -euo pipefail
PROFILE="production-service"
NEW_CERT="/path/to/new-certificate.pfx"
CERT_PASSWORD="YourPassword"
# Backup current profile
entratool config export -p "$PROFILE" -o "backup-$PROFILE.json"
# Update certificate path (manual edit required for password)
echo "Updating profile with new certificate..."
entratool config edit -p "$PROFILE"
# Manual step: Select Certificate Path, enter new path and password
# Test
echo "Testing new certificate..."
if entratool get-token -p "$PROFILE" --silent > /dev/null; then
echo "✓ Certificate rotation successful"
else
echo "✗ Certificate rotation failed"
exit 1
fi
|
Certificate Validation link
Check Certificate Expiration link
1
2
3
4
5
6
7
| # macOS/Linux
openssl pkcs12 -in certificate.pfx -nodes -passin pass:YourPassword | \
openssl x509 -noout -enddate
# Windows (PowerShell)
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("certificate.pfx", "password")
$cert.NotAfter
|
Verify Certificate Thumbprint link
1
2
3
4
5
6
7
| # macOS/Linux
openssl pkcs12 -in certificate.pfx -nodes -passin pass:YourPassword | \
openssl x509 -noout -fingerprint -sha1
# Windows (PowerShell)
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("certificate.pfx", "password")
$cert.Thumbprint
|
Troubleshooting link
“Certificate not found” link
Cause: Certificate path is incorrect
Solution:
1
2
3
4
5
6
| # Verify file exists
ls -l /path/to/certificate.pfx
# Update profile
entratool config edit -p myprofile
# Select: Certificate Path
|
“Invalid certificate password” link
Cause: Incorrect password or corrupted certificate
Solution:
1
2
3
4
5
6
| # Test certificate manually
openssl pkcs12 -in certificate.pfx -noout -passin pass:YourPassword
# Update password in profile
entratool config edit -p myprofile
# Select: Certificate Password
|
“AADSTS700027: Client assertion contains an invalid signature” link
Cause: Certificate not registered in Azure or expired
Solution:
- Verify certificate is uploaded to app registration
- Check certificate expiration
- Ensure correct certificate (match thumbprints)
“Certificate has expired” link
Cause: Certificate validity period has passed
Solution:
- Generate new certificate
- Upload to Azure Portal
- Update profile with new certificate
Security Best Practices link
- Use strong certificate passwords
- Store certificates with restrictive file permissions (600)
- Rotate certificates annually or per policy
- Use CA-signed certificates for production
- Monitor certificate expiration dates
- Use separate certificates for dev/staging/prod
- Store certificates in git repositories
- Share certificates via email/Slack
- Use weak passwords
- Ignore certificate expiration warnings
- Reuse certificates across environments
Next Steps link