Keep your Microsoft 365 automation running — and know exactly what to do when it breaks. Part 3 of 3.
By now you've created a certificate and configured Entra (Part 1) and converted your scripts to certificate authentication (Part 2). This final part covers the two things that keep it healthy long-term: rotating the certificate before it expires (without downtime), and troubleshooting — including how to respond if a private key is exposed.
A certificate that expires unnoticed will silently take down every script that depends on it. The whole point of rotation is to replace it early, with an overlap period where both the old and new certificates are valid, so nothing ever stops working.
A Sensible Rotation Standard
| Item | Recommended |
| Certificate lifetime | 24 months |
| Rotation planning starts | 60 days before expiration |
| Target completion | 30 days before expiration |
| Overlap period | Keep the old certificate active until every script tests successfully on the new one |
| Emergency rotation | Immediately after suspected private-key exposure or system compromise |
Part A — Rotate the Certificate (No Downtime)
Step 1: Inventory what you have
Get-ChildItem Cert:\CurrentUser\My |
Where-Object Subject -like "*M365-Automation*" |
Select-Object Subject, Thumbprint, NotAfter, HasPrivateKey |
Sort-Object NotAfter
Record the certificate you're replacing and confirm which scripts reference its thumbprint.
Step 2: Create the replacement
Use the same process from Part 1, but give it a name that clearly identifies the new cycle or year.
$CertName = "M365-Automation-2028"
$NewCert = New-SelfSignedCertificate `
-Subject "CN=$CertName" `
-CertStoreLocation "Cert:\CurrentUser\My" `
-KeySpec Signature `
-KeyExportPolicy Exportable `
-KeyLength 2048 `
-KeyAlgorithm RSA `
-HashAlgorithm SHA256 `
-NotAfter (Get-Date).AddMonths(24)
Export-Certificate -Cert $NewCert -FilePath "C:\mycertificates\$CertName.cer"
$PfxPassword = Read-Host "Enter a strong PFX password" -AsSecureString
Export-PfxCertificate -Cert $NewCert -FilePath "C:\mycertificates\$CertName.pfx" -Password $PfxPassword
$NewCert | Select-Object Subject, Thumbprint, NotAfter, HasPrivateKey
Step 3: Upload the new CER — but keep the old one
In the Microsoft Entra admin center, open your automation app under Certificates & secrets → Certificates and upload the new .cer. Confirm it appears with the correct thumbprint and expiration. Do not remove the old certificate yet — both can be uploaded at once, which is what lets you migrate with zero downtime.
Step 4: Test the new thumbprint without touching production
$AppId = "00000000-0000-0000-0000-000000000000"
$TenantId = "00000000-0000-0000-0000-000000000000"
$NewThumbprint = "PASTE_NEW_CERTIFICATE_THUMBPRINT_HERE"
Connect-MgGraph -ClientId $AppId -TenantId $TenantId -CertificateThumbprint $NewThumbprint
Get-MgContext
Disconnect-MgGraph
Step 5: Update and test each script
- Replace the old thumbprint with the new one in each script.
- Save with a version comment or change record.
- Run it manually first (if safe), then run it the same way production does — e.g. from Task Scheduler, under the correct run account.
- Confirm the output and logs show success.
Step 6: Remove the old certificate — only after validation
Once every script has run successfully on the new thumbprint and no scheduled task references the old one:
# Remove the old certificate locally ONLY after full validation
$OldThumbprint = "PASTE_OLD_CERTIFICATE_THUMBPRINT_HERE"
Get-ChildItem Cert:\CurrentUser\My | Where-Object Thumbprint -eq $OldThumbprint | Remove-Item
Then remove the old certificate from the Entra app registration, securely archive or delete old PFX backups, and update your inventory/rotation tracker.
Rollback (if the new certificate fails)
While the old certificate is still valid, you can temporarily restore the old thumbprint in the script. Re-check the certificate store location, private-key availability, and the Entra upload status. Never delete the old certificate until a full test cycle succeeds on the new one.
Part B — Troubleshoot Authentication Failures
Quick triage
Start by answering these — they point you at the cause fast:
- Did this script ever work on this computer?
- Did the failure start right after a rotation?
- Is the script running as the same Windows account that owns the certificate?
- Does the thumbprint in the script match the one in Entra?
- Is the certificate expired, and does it have a private key?
- Were API permissions or admin consent changed?
Confirm the certificate exists and is usable
$Thumbprint = "PASTE_CERTIFICATE_THUMBPRINT_HERE"
Get-ChildItem Cert:\CurrentUser\My |
Where-Object Thumbprint -eq $Thumbprint |
Select-Object Subject, Thumbprint, NotBefore, NotAfter, HasPrivateKey
You want exactly one result, HasPrivateKey = True, and a NotAfter in the future.
Strip hidden characters from a copied thumbprint
Thumbprints copied from a portal sometimes carry invisible characters or spaces. Normalize before testing:
$Thumbprint = "PASTE_CERTIFICATE_THUMBPRINT_HERE"
$Thumbprint = ($Thumbprint -replace '[^a-fA-F0-9]', '').ToUpper()
$Thumbprint
Confirm the account the script runs as
whoami
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
A CurrentUser certificate created under one account is not visible to another. If a scheduled task fails but a manual run works, this is the usual reason.
Troubleshooting matrix
| Symptom | Likely cause | Resolution |
| Certificate not found | Wrong store or user profile | Import the PFX into the store for the script-running account. |
HasPrivateKey = False | Only the CER was imported locally | Import the PFX, not just the CER. |
| Fails right after rotation | Script uses old thumbprint, or Entra is missing the new certificate | Update the script thumbprint and upload the new CER to Entra. |
| Connects but "access denied" | Missing permission or RBAC role | Add the required API permission, grant admin consent, and configure workload-specific roles. |
| Works manually, not in Task Scheduler | Task runs as a different account | Install the certificate under the task account, or use LocalMachine with key permissions. |
| Certificate expired | NotAfter is in the past | Create and upload a replacement (Part A). |
Part C — If a Certificate Is Compromised
Treat a PFX exposure or unauthorized access to the private key as a security incident. If an attacker has the private key and knows the App ID and Tenant ID, and the certificate is still trusted by Entra, they can authenticate as the app.
Immediate containment
- Stop the affected scheduled tasks / automation jobs.
- Remove the compromised certificate from the Entra app registration.
- Delete the local certificate from affected systems (if safe), and secure or delete exposed PFX files.
- Create a replacement certificate on a trusted machine, upload the new CER, and update scripts.
- Review Entra sign-in logs and script logs for unauthorized activity.
Evidence to preserve
- Affected script names and paths; the certificate thumbprint and expiration.
- Every system where the PFX or private key existed.
- Entra sign-in logs for the application / service principal.
- Scheduled-task history and PowerShell transcript logs, and file timestamps on the exposed files.
Escalate immediately if…
- You find unknown or unauthorized app-only sign-ins.
- A PFX file left your controlled systems.
- The affected app has broad write permissions, or touches mailboxes, SharePoint data, user objects, or security configuration.
- You cannot confirm whether the private key was actually exposed.
Series Wrap-Up
That completes the three-part path to secure Microsoft 365 automation: create the certificate and configure Entra, replace client secrets and connect, and rotate, renew, and troubleshoot. The result: automation that authenticates with a certificate, carries no secrets, and has a clear plan for both renewal and incidents.
Want your Microsoft 365 automation set up, secured, and maintained for you? Explore our Managed IT Services and Microsoft 365 Services, or read our related guides on MFA and Conditional Access.
References