Certificate-based authentication is the phishing-resistant method most organisations reach for when they want smart cards or PIV credentials to sign in to Microsoft Entra ID directly, with no password and no federation server in the path. It is genuinely strong — right up until the day you need to un-trust a certificate. Revocation is the entire security promise of a PKI: when a device is lost or someone leaves, you revoke their certificate and it stops working. This post is about the one configuration gap that quietly breaks that promise, why the portal gives you no warning at all, and a read-only PowerShell audit that finds it before an auditor — or an attacker — does.
The problem: you revoked the certificate, and it still authenticates
Here is the scenario, and it is uncomfortably common in organisations that adopted CBA early. You stood up certificate-based authentication properly. You uploaded your issuing CA to the Entra trust store, you configured the authentication methods policy, you issued smart-card certificates to your privileged users, and phishing-resistant sign-in worked on the first try. Everyone moved on.
Months later, a contractor with a privileged smart-card certificate leaves under less-than-ideal circumstances. Your PKI team does exactly the right thing: they revoke the contractor's certificate on the issuing CA, the CA publishes an updated certificate revocation list (CRL), and the revoked serial number is now sitting in that CRL for the whole world to see. Job done, as far as anyone can tell.
Except the contractor's certificate still signs in to Entra ID. Not for an hour while a cache clears — indefinitely, right up until the certificate's own expiry date, which could be a year away. Conditional Access still waves it through as phishing-resistant MFA. The sign-in logs show a clean, successful certificate authentication. Nothing anywhere is red.
The reason nobody catches this is that the portal shows you a healthy, working configuration. CBA is enabled. The CA is present in the trust store. Users are signing in. The single missing field — the CRL distribution point URL on that CA — is not surfaced anywhere as a warning, because an empty CRL URL is a legitimate (if dangerous) configuration that Microsoft deliberately allows.
That middle line is the whole story. The issuing CA that actually signs your user certificates has no CRL URL, "Require CRL validation" is switched off, and Entra is therefore accepting every certificate that CA has ever issued — revoked or not — without ever looking at a revocation list. To a casual glance the blade looks fine. You have to know to look at that one field on that one CA.
Why it happens: the trust store, the CRL, and one optional field
Three terms first, because the rest of this leans on them. A certificate authority (CA) in the Entra CBA trust store is the issuer Entra will trust to have signed a user's certificate. A CRL distribution point (CDP) is the internet-facing URL where that CA publishes its certificate revocation list. And the certificate revocation list (CRL) itself is the signed, periodically-republished list of serial numbers the CA has revoked before their natural expiry.
When a user presents a certificate, Entra builds the chain up to a trusted CA in your store, and — if that CA has a CRL URL configured — downloads and caches the CRL to check whether the presented certificate's serial number is on it. If it is, authentication is rejected with AADSTS500171 ("Certificate has been revoked"). If the CA has no CRL URL, that entire step is skipped. There is no revocation list to consult, so there is nothing to reject against.
Microsoft deliberately makes the CRL URL optional so you can bring a CA online quickly, or troubleshoot, without a working CRL. The documentation is blunt about the trade-off: "You can upload a CA without a CRL endpoint, and certificate-based authentication doesn't fail if an issuing CA doesn't specify a CRL." Helpful during setup; a silent hole in production.
There are a few more mechanics worth knowing, because they explain why this fails so quietly and why the fix has to happen in the right place:
- One CRL endpoint per CA, HTTP or HTTPS, and Microsoft recommends plain HTTP to avoid the circular dependency of validating a certificate over a connection that itself needs certificate validation. There is no OCSP support — Entra downloads and caches the CRL rather than doing a per-connection OCSP lookup.
- Revocation is not instant even when it works. Because Entra caches the CRL until its Next Update time, a freshly revoked certificate is not detected until the cache refreshes. Delta CRLs shorten that window; without them, revocation only takes effect when the base CRL's validity period rolls over.
- The identity of the CA matters. Entra builds the chain using the Subject Key Identifier (SKI), and matches a CA to its CRL by pairing the CA's issuer SKI with the CRL's Authority Key Identifier. That SKI is exactly what the audit below keys on.
There is a second, quieter risk in the same policy: the authentication binding. CBA can treat a presented certificate as either single-factor or multi-factor, controlled by x509CertificateAuthenticationDefaultMode in the authentication methods policy (the values are x509CertificateSingleFactor and x509CertificateMultiFactor). If the default mode is multi-factor and there are no granular rules narrowing that down, every certificate from every trusted CA satisfies MFA on its own — including a soft certificate on an unmanaged device, not just a hardware-backed smart card. That is not necessarily wrong, but it is a decision you want to have made deliberately, not inherited by default. The audit reports it so you can eyeball it.
How to verify: check one CA's CRL field before you trust any script
Before running anything tenant-wide, confirm the mechanism on a single CA so you know what "broken" actually looks like in your environment. You can do this entirely read-only with one Graph call. The example below pulls the legacy trust store and shows the raw certificate authorities; look specifically at certificateRevocationListUrl on the CA that issues your user certificates.
# Least-privilege read scope for the legacy trust store Connect-MgGraph -Scopes "Organization.Read.All" $org = Get-MgOrganization Get-MgOrganizationCertificateBasedAuthConfiguration -OrganizationId $org.Id | Select-Object -ExpandProperty CertificateAuthorities | Format-List Issuer, IsRootAuthority, CertificateRevocationListUrl, IssuerSki Issuer : CN=Contoso Issuing CA 1 IsRootAuthority : False CertificateRevocationListUrl : IssuerSki : 1A2B3C4D5E6F70819200A1B2C3D4E5F600112233
That empty CertificateRevocationListUrl on a non-root, certificate-issuing CA is the finding. Compare it against the sample in Microsoft's own documentation for the newer PKI store, which literally shows a CA object with "certificateRevocationListUrl": null — proof that this is a real, shippable state and not a hypothetical. If your issuing CA looks like the line above, revocation is not being enforced for anything it signed.
To view the same data in the portal instead: Entra admin center › Protection › Authentication methods › Certificate-based authentication, then open the Configure tab and inspect each certificate authority's CRL settings and the Require CRL validation toggle.
The fix: Get-CbaTrustStoreReport.ps1
Checking one CA by hand is fine for confirming the mechanism. It does not scale to a tenant with multiple issuing CAs, two trust stores, and a policy you last touched eighteen months ago. The companion script reads all of it in one pass and tells you exactly which CAs have no revocation checking, whether "Require CRL validation" is on to catch them, and what the default authentication binding is.
Download Get-CbaTrustStoreReport.ps1 from the Imran76Awan/Daily-Tasks repository on GitHub — no sign-in required. It is read-only and cannot change anything in your tenant — but always validate any script in your own environment before you rely on it.
The script connects with three least-privilege, read-only scopes and never asks for anything higher:
| Surface read | Least-privilege scope | What it tells you |
|---|---|---|
| Legacy trust store organization/certificateBasedAuthConfiguration | Organization.Read.All | Each CA's CRL URL, delta CRL URL, root flag, issuer SKI |
| PKI trust store directory/publicKeyInfrastructure | PublicKeyInfrastructure.Read.All | Same fields for CAs in the newer scalable store |
| CBA policy authenticationMethodsPolicy (X509Certificate) | Policy.Read.AuthenticationMethod | Default single/multi-factor mode, rules, Require CRL validation, exempted CAs |
It supports app-only certificate authentication for scheduled or unattended runs (-TenantId -ClientId -CertificateThumbprint) and an interactive -UseDeviceCode fallback for ad-hoc checks. It fails loud: if any Graph query errors out — a permission problem, throttling, anything — it sets an error flag, prints the failure, and exits 1 rather than printing a reassuring "0 findings" on data it never actually retrieved. Here is a first run against a tenant with the misconfiguration from the top of this post:
Connecting to Microsoft Graph (read-only scopes)... Connected. Tenant: ████████-████-████-████-████████████ Legacy trust store CAs found : 2 PKI trust store CAs found : 0 ====================================================================== ENTRA CBA TRUST STORE REPORT - 31 Jul 2026 09:14 ====================================================================== Total trusted CAs : 2 CBA policy state : enabled Default auth mode : x509CertificateMultiFactor Strong-auth rules defined : 0 Require CRL validation : disabled CAs exempted from CRL check: 0 ====================================================================== CERTIFICATE AUTHORITIES ====================================================================== Surface : Legacy Root authority : True Issuer : CN=Contoso Root CA Issuer SKI : 9F8E7D6C5B4A39281706F5E4D3C2B1A099887766 CRL URL : http://pki.contoso.com/root.crl Delta CRL URL : <none> STATUS : OK Surface : Legacy Root authority : False Issuer : CN=Contoso Issuing CA 1 Issuer SKI : 1A2B3C4D5E6F70819200A1B2C3D4E5F600112233 CRL URL : <none> Delta CRL URL : <none> STATUS : FINDING: NO CRL - revocation NOT checked ====================================================================== SUMMARY ====================================================================== CAs with no revocation checking (findings): 1 ADVISORY: "Require CRL validation" is NOT enabled - a CA with no CRL will silently skip revocation. ADVISORY: default mode is multi-factor with no granular rules - every trusted certificate satisfies MFA. Confirm this is intended. RESULT: 1 finding(s) detected.
The classification logic is deliberately conservative. A CA is only counted as a hard finding when it has no CRL URL and "Require CRL validation" is not enabled and the CA is not on the exemption list — because in that specific combination, and only that combination, a revoked certificate genuinely sails through. If you have turned on Require CRL validation, a CA with no CRL is reported as "blocked by Require-CRL" instead of a finding, because Entra will now fail those certificates closed rather than open. The advisories about the authentication binding are informational and do not, on their own, change the exit code.
Add -TestCrlReachability and the script will also perform a read-only HTTP GET against each configured CRL URL, so you catch the other failure mode: a CRL URL that is set but returns a 403 or times out, which surfaces at sign-in as AADSTS500173 ("Unable to download a Certificate Revocation List"). A configured-but-unreachable CRL is just as broken as a missing one, only louder — it fails users closed instead of open.
Proof it worked: re-run after configuring the CRL
The remediation here is a PKI and policy change, not a script change, and it happens in two places. First, the PKI team ensures the issuing CA actually publishes its CRL to an internet-facing HTTP endpoint, and that URL is set as the CA's certificateRevocationListUrl in the Entra trust store. Second — and this is the belt-and-braces step — an Authentication Policy Administrator turns on Require CRL validation so that any future CA added without a CRL fails closed instead of open. With both done, the same audit run comes back clean:
Connecting to Microsoft Graph (read-only scopes)... Connected. Tenant: ████████-████-████-████-████████████ Legacy trust store CAs found : 2 PKI trust store CAs found : 0 ====================================================================== ENTRA CBA TRUST STORE REPORT - 31 Jul 2026 15:02 ====================================================================== Total trusted CAs : 2 CBA policy state : enabled Default auth mode : x509CertificateMultiFactor Strong-auth rules defined : 0 Require CRL validation : enabled CAs exempted from CRL check: 0 Surface : Legacy Root authority : False Issuer : CN=Contoso Issuing CA 1 Issuer SKI : 1A2B3C4D5E6F70819200A1B2C3D4E5F600112233 CRL URL : http://pki.contoso.com/issuing1.crl Delta CRL URL : http://pki.contoso.com/issuing1+.crl CRL reachable : HTTP 200 STATUS : OK ====================================================================== SUMMARY ====================================================================== CAs with no revocation checking (findings): 0 CAs with an unreachable CRL URL : 0 RESULT: No revocation-config findings detected.
The exit code is the part worth wiring into automation. The script returns 0 for clean, 2 for findings, and 1 for an error, so a scheduled run in Azure Automation or a Task Scheduler job can alert only when there is genuinely something to fix — and, crucially, will never report clean off the back of a query it could not actually complete.
If you run CBA, this is a ten-minute check that is well worth doing this week. A missing CRL distribution point is the kind of gap that stays invisible for exactly as long as nobody revokes a certificate in anger — and then becomes the first question in the post-incident review.
References
- Understand Microsoft Entra CBA certificate revocation list — Microsoft Learn
- certificateAuthority resource type (certificateRevocationListUrl, isRootAuthority, issuerSki) — Microsoft Graph
- x509CertificateCRLValidationConfiguration (Require CRL validation) — Microsoft Graph
- x509CertificateAuthenticationModeConfiguration (single vs multi-factor binding) — Microsoft Graph
- Get-MgOrganizationCertificateBasedAuthConfiguration — Microsoft Graph PowerShell
- Daniel Bradley (Microsoft MVP): Use Certificate-Based Authentication in Entra with Cloud PKI — ourcloudnetwork.com
Have you actually checked the CRL field on your issuing CA, or are you assuming revocation works because CBA sign-in works? Run the audit, look at that one field, and see what turns up — I'd genuinely like to hear how many tenants find an issuing CA with an empty CRL URL sitting in production.