SEC_E_CERT_EXPIRED (0X80090328) – Three Fixes That Work
This error means a cert in the TLS chain expired. Dead simple. But the fix depends on which cert – client or server. Here's the real fix order.
1. The Server's Leaf Certificate Expired (Most Common)
This is the one you'll see 9 times out of 10. The certificate on the server – IIS, RDP, SQL Server, you name it – has a valid-to date that's passed. The client gets it during the TLS handshake, checks the date, and throws 0X80090328. No negotiation happens.
How to confirm: Run this on the server in an admin PowerShell or cmd:
certutil -store My | find /I "NotAfter"
Look for any dates in the past. Also check the Subject line to match it to the service. If you see expired certs, that's your culprit.
The fix: Renew the cert. If it's a public CA-issued cert (e.g., DigiCert, Let's Encrypt), get a new one from your CA and bind it to the service. For internal AD CS – open the Certificate Authority MMC, issue a new cert from the same template, then bind it. Don't forget to update any load balancer or reverse proxy that terminates TLS.
Real-world trigger: You're connecting to https://intranet.company.local and the internal CA's cert template auto-renewed but the IIS binding didn't pick it up. Or an RDP Gateway cert expired overnight – those are always fun at 8 AM.
2. The Client Certificate Expired (Less Common, But Nasty)
This one bites when you have mutual TLS (mTLS) or client certificate authentication. SQL Server linked servers, EAP-TLS for Wi-Fi, or any app that uses client certs. The error looks identical because it's still the same Schannel error – the client sends an expired cert, server says no.
How to confirm: Check the client's personal store:
certlm.msc
Navigate to Personal -> Certificates. Look for the one the client is sending. Expiration date is in the Details tab. Also check the Event Viewer under Applications and Services Logs -> Microsoft -> Windows -> Schannel -> Operational. Event ID 36888 or 36874 will tell you exactly which cert failed.
The fix: Renew the client cert. If it's from AD CS, request a new one from the server or use autoenrollment. If it's a third-party cert, generate a new CSR, get it signed, and import it. Then update whatever app uses it – SQL Server linked server, IIS client cert mapping, etc.
Pro tip: If you're using certificate services for Wi-Fi (EAP-TLS), the user's cert might auto-renew but the old one stays in their store. Delete the expired one manually after renewal. Otherwise, Windows sometimes picks the dead one.
3. Expired or Missing Intermediate or Root CA Certificate (Annoying)
This is the sneaky one. The server's leaf cert is fine. The client's cert is fine. But the intermediate CA that signed the server's cert – or its root – has expired. Or the client doesn't have the intermediate in its trusted store.
Schannel doesn't tell you which cert in the chain failed. It just says "expired." So you chase the leaf, find it's valid, and waste an hour. Don't.
How to confirm: Use OpenSSL to inspect the chain from the client's perspective. On the client, run:
openssl s_client -connect server.example.com:443 -showcerts
Look for any cert in the output where the Not After date is past. Also check if the full chain was sent – if the server didn't send the intermediate, the client can't build the chain.
The fix:
- If the intermediate CA cert itself expired (rare but happens with old CA rotations) – you need to reissue the server's leaf cert under a current intermediate. That means contacting your CA.
- If the root CA expired (even rarer) – you have bigger problems. Update the trusted root store on the client. For internal CAs, push the updated root via GPO.
- If the intermediate is missing from the chain – the server needs to include it. On IIS, re-export the cert with the full chain and bind it. On other services, use the PFX with the intermediate included.
Real-world trigger: You deployed a new internal CA that signed certs with an intermediate that expired last month. All leaf certs are valid, but the intermediate is dead. Every client now fails until you reissue leaves.
Quick-Reference Summary Table
| Cause | Tell | Fix | Tools |
|---|---|---|---|
| Server leaf cert expired | certutil on server shows past NotAfter | Renew cert, bind to service | certutil, IIS Manager, MMC |
| Client cert expired | Schannel event 36888/36874, certlm shows expired | Renew client cert, delete old one | certlm.msc, Event Viewer |
| Intermediate/root expired or missing | openssl s_client shows chain failure or past date | Reissue leaf under current CA, or install missing intermediate | openssl, CA console, GPO |
Bottom line: When you see 0X80090328, don't panic. Start with the server's leaf cert – that's the 90% bet. If it's clean, check the client cert. If both are fine, dig into the chain. Nine times out of ten you'll find an expired cert in one of those three spots.
Was this solution helpful?