How to Create a Self-Signed Certificate and Upload It to Azure App Registration Using PowerShell
Securing your Azure app with certificate-based authentication is a best practice — especially when building automation with Microsoft Graph, Exchange Online, or Teams. In this post, I'll walk you through how to create a self-signed certificate using PowerShell on your local machine and upload it to an Azure App Registration in Microsoft Entra ID.
Why Use Certificate-Based Authentication?
Certificate-based authentication is more secure than client secrets because:
- Certificates are harder to leak accidentally (no plain-text secret string)
- They support expiry enforcement with a clear renewal cycle
- They work seamlessly with GitHub Actions, Azure Automation, and PowerShell scripts
- They are the recommended approach for unattended/service account automation in M365
Prerequisites
- Windows machine with PowerShell 5.1+ or PowerShell 7+
- Access to Azure Portal with permissions to manage App Registrations
- An existing App Registration in Microsoft Entra ID (or create a new one)
Step 1 — Create the Self-Signed Certificate
Open PowerShell as Administrator and run the following script to generate a self-signed certificate and store it in your local certificate store.
# ─────────────────────────────────────────────────────────────
# STEP 1: Create Self-Signed Certificate
# ─────────────────────────────────────────────────────────────
$certName = "MyAppAuthCert"
$validYears = 2
# Generate the certificate in CurrentUser\My store
$cert = New-SelfSignedCertificate `
-Subject "CN=$certName" `
-CertStoreLocation "Cert:\CurrentUser\My" `
-KeyExportPolicy Exportable `
-KeySpec Signature `
-KeyLength 2048 `
-KeyAlgorithm RSA `
-HashAlgorithm SHA256 `
-NotAfter (Get-Date).AddYears($validYears)
# Confirm creation
Write-Host "✅ Certificate created successfully!" -ForegroundColor Green
Write-Host " Subject : $($cert.Subject)"
Write-Host " Thumbprint : $($cert.Thumbprint)"
Write-Host " Valid Until: $($cert.NotAfter)"
Note: The certificate is stored in
Cert:\CurrentUser\My. You can verify it by opening certmgr.msc → Personal → Certificates.
Step 2 — Export the Public Key (.cer)
The App Registration only needs the public key in .cer format. No password is required for this export.
# ─────────────────────────────────────────────────────────────
# STEP 2: Export Public Key (.cer) for Azure Portal Upload
# ─────────────────────────────────────────────────────────────
$cerPath = "$env:USERPROFILE\Desktop\$certName.cer"
Export-Certificate `
-Cert "Cert:\CurrentUser\My\$($cert.Thumbprint)" `
-FilePath $cerPath
Write-Host "✅ Public key exported!" -ForegroundColor Green
Write-Host " Path: $cerPath"
Step 3 — Export the Private Key (.pfx)
Keep your .pfx file safe — this is used by your PowerShell scripts and automation pipelines to authenticate.
# ─────────────────────────────────────────────────────────────
# STEP 3: Export Private Key (.pfx) for Script Authentication
# ─────────────────────────────────────────────────────────────
$pfxPassword = Read-Host -Prompt "Enter PFX password" -AsSecureString
$pfxPath = "$env:USERPROFILE\Desktop\$certName.pfx"
Export-PfxCertificate `
-Cert "Cert:\CurrentUser\My\$($cert.Thumbprint)" `
-FilePath $pfxPath `
-Password $pfxPassword
Write-Host "✅ Private key (PFX) exported!" -ForegroundColor Green
Write-Host " Path: $pfxPath"
Write-Host "⚠️ Keep this file secure. Do NOT commit it to source control." -ForegroundColor Yellow
⚠️ Security Tip: Store the
.pfxfile in Azure Key Vault or as a GitHub Actions secret (base64-encoded). Never commit it to a repository.
Step 4 — Upload the Certificate to Azure App Registration
- Sign in to the Azure Portal
- Navigate to Microsoft Entra ID → App registrations
- Select your application
- In the left menu, click Certificates & secrets
- Click the Certificates tab → Upload certificate
- Browse and select the
.cerfile exported to your Desktop - Add a Description (e.g.,
MyAppAuthCert-2026) → click Add
You will now see the certificate listed with its Thumbprint, Start date, and Expiry date.
Step 5 — Complete PowerShell Script (All-in-One)
Here is the complete end-to-end script you can save and run directly:
# ═══════════════════════════════════════════════════════════════
# Create Self-Signed Certificate & Export for Azure App Reg
# Author : Your Name
# Version: 1.0
# Date : June 2026
# ═══════════════════════════════════════════════════════════════
# ── Configuration ─────────────────────────────────────────────
$certName = "MyAppAuthCert"
$validYears = 2
$exportPath = "$env:USERPROFILE\Desktop"
Write-Host "`nš Starting Certificate Creation..." -ForegroundColor Cyan
# ── Step 1: Create Self-Signed Certificate ────────────────────
$cert = New-SelfSignedCertificate `
-Subject "CN=$certName" `
-CertStoreLocation "Cert:\CurrentUser\My" `
-KeyExportPolicy Exportable `
-KeySpec Signature `
-KeyLength 2048 `
-KeyAlgorithm RSA `
-HashAlgorithm SHA256 `
-NotAfter (Get-Date).AddYears($validYears)
Write-Host "✅ Certificate created: $($cert.Thumbprint)" -ForegroundColor Green
# ── Step 2: Export Public Key (.cer) ─────────────────────────
$cerPath = "$exportPath\$certName.cer"
Export-Certificate `
-Cert "Cert:\CurrentUser\My\$($cert.Thumbprint)" `
-FilePath $cerPath | Out-Null
Write-Host "✅ Public key exported : $cerPath" -ForegroundColor Green
# ── Step 3: Export Private Key (.pfx) ────────────────────────
$pfxPassword = Read-Host -Prompt "`nEnter a secure password for the PFX file" -AsSecureString
$pfxPath = "$exportPath\$certName.pfx"
Export-PfxCertificate `
-Cert "Cert:\CurrentUser\My\$($cert.Thumbprint)" `
-FilePath $pfxPath `
-Password $pfxPassword | Out-Null
Write-Host "✅ Private key exported: $pfxPath" -ForegroundColor Green
# ── Summary ───────────────────────────────────────────────────
Write-Host "`n════════════════════════════════════════" -ForegroundColor Cyan
Write-Host " Certificate Summary" -ForegroundColor Cyan
Write-Host "════════════════════════════════════════" -ForegroundColor Cyan
Write-Host " Subject : $($cert.Subject)"
Write-Host " Thumbprint : $($cert.Thumbprint)"
Write-Host " Valid From : $($cert.NotBefore)"
Write-Host " Valid Until : $($cert.NotAfter)"
Write-Host " CER Path : $cerPath"
Write-Host " PFX Path : $pfxPath"
Write-Host "════════════════════════════════════════" -ForegroundColor Cyan
Write-Host "`nš Next Step: Upload the .cer file to your Azure App Registration" -ForegroundColor Yellow
Write-Host " Portal → Entra ID → App Registrations → Certificates & Secrets`n"
Step 6 — Authenticate Using the Certificate in PowerShell
Once the certificate is uploaded to the App Registration, use the thumbprint to authenticate in your automation scripts.
Microsoft Graph
# ─────────────────────────────────────────────────────────────
# Authenticate with Microsoft Graph using Certificate
# ─────────────────────────────────────────────────────────────
$tenantId = "<your-tenant-id>"
$clientId = "<your-app-client-id>"
$thumbprint = "<certificate-thumbprint>"
Connect-MgGraph `
-TenantId $tenantId `
-ClientId $clientId `
-CertificateThumbprint $thumbprint
Write-Host "✅ Connected to Microsoft Graph" -ForegroundColor Green
Exchange Online
# ─────────────────────────────────────────────────────────────
# Authenticate with Exchange Online using Certificate
# ─────────────────────────────────────────────────────────────
Connect-ExchangeOnline `
-AppId $clientId `
-Organization "yourtenant.onmicrosoft.com" `
-CertificateThumbprint $thumbprint
Write-Host "✅ Connected to Exchange Online" -ForegroundColor Green
Quick Reference Summary
| Step | Action | Output |
|---|---|---|
| 1 | New-SelfSignedCertificate |
Cert created in local store |
| 2 | Export-Certificate |
.cer public key file |
| 3 | Export-PfxCertificate |
.pfx private key file |
| 4 | Upload .cer in Azure Portal |
App Registration cert added |
| 5 | Use thumbprint in scripts | Cert-based auth working |
Tips & Best Practices
- š Renewal reminder — Set a calendar alert 30 days before expiry (
NotAfterdate) - š Store PFX securely — Use Azure Key Vault or GitHub Actions secrets (base64-encoded)
- š·️ Use descriptive names — Include the year in the cert description (e.g.,
AppAuthCert-2026) - š Document the thumbprint — Save it in your runbook/wiki for reference during troubleshooting
- š« Never use secrets for automation — Cert-based auth is always preferred over client secrets for unattended scripts
Hashtags
#MicrosoftAzure #EntraID #PowerShell #AzureAppRegistration #CertificateAuthentication #M365 #MicrosoftGraph #DevOps #CloudSecurity #AzureAutomation
No comments:
Post a Comment