When validation fails
All domains, identifiers, and log values in these examples are fictional.
At 09:12 on a Tuesday, the printing company's support team receives a message: "Continue with your photo account just brings me back to the sign-in page." By 09:30 there are forty more. Behind each one is a sign-in whose ID token the printer rejected, and the printer did what Validating an ID token required of it. It signed nobody in.
Rejecting was right, but it is only the start. Somebody now has to work out what kind of failure this is, tell the people affected something useful without helping an attacker, and repair the cause without turning the repair into a new weakness.
Sorting the failures
Failed validations fall into four broad kinds. A single failure rarely reveals which kind it is. The pattern usually does.
| Kind | What the pattern looks like | Common causes |
|---|---|---|
| Configuration mismatch | Every sign-in fails at the same check, starting at a release or a change at the provider. | An issuer with a trailing slash, a test client ID in production, an algorithm the provider has moved to that the list lacks, a key set address from the wrong environment. |
| Clock problems | Time checks fail: tokens look expired on arrival, or issued in the future. Often only some servers are affected. | A server whose clock has drifted, or a virtual machine resumed with a stale clock. |
| Key set unavailable | A token names a key the printer does not hold, and fetching the set fails or times out. | A network or firewall change, an outage at the provider, a rotation the printer could not follow. |
| Attacks and replays | Scattered failures at the signature, audience, or nonce checks, with no change on either side. | A forged or altered token, a token issued to another client, a token from another attempt. |
Tuesday's failures were all at the audience check, and they began at 09:10, two minutes after a release. That pattern points at configuration, and so it proved. The release had upgraded the printer's OpenID Connect library, and the new version read the expected audience from a setting with a new name. With its old setting ignored, the library had no expected audience at all. As Validating an ID token asked of it, the library rejected every token rather than skip the check, while the photo service, correctly, kept sending photo-printer.
The other kinds leave their own traces. Clock faults come and go with the server that handled each request, and the gap between the token's times and the server's clock is about the same each time. Key set failures arrive alongside errors from the fetch itself. They also call for a decision made in advance. If a token names a key the printer already holds, from a set it fetched recently, the printer can keep validating with that copy while the provider recovers. If the key is unknown and the set cannot be fetched, the printer has no way to verify the token, so the sign-in fails.
The fourth kind is the one the checks exist for, and it looks different: a handful of failures rather than a wave, often from one network or against one account, at exactly the checks an attacker would have to beat. A signature that fails with a key the printer knows, a genuine token addressed to another client, or a nonce from some other attempt deserves a closer look even when it is rare.
What the person sees
From the person's side, all four kinds look the same, and they should. The printer shows the page that Authentication errors described for any failed sign-in, with one addition, a reference:
We couldn't sign you in with your photo account.
Try again, or sign in another way.
Reference: signin-5f2c
Trying again starts a new attempt with a fresh state, nonce, and PKCE verifier. The failed attempt was claimed when the callback arrived, so nothing from it can be reused. The printer does not retry by itself. An automatic retry can bounce a browser between the printer and the photo service, and when the cause is configuration, every retry fails the same way.
The page does not say which check failed. "Nonce mismatch" or "invalid audience" means nothing to someone ordering a calendar, and to someone testing forged tokens it reports how far each one got. The page shows nothing from the rejected token either. A name or email address inside a token that failed validation is unverified text, possibly written by an attacker, so "Welcome back, Robin" has no place here. The reference lets a person who contacts support be matched to the printer's records without anyone reading out a token.
When the fault is the printer's own, as on Tuesday, everyone sees the same page until the fix is deployed. A short notice on the sign-in page saying that sign-in with the photo service is having problems saves people from trying again and again.
What the logs record
Authentication errors set out the basics: the stage, the failed check, the expected issuer, and a correlation ID, and never the code or the tokens. A validation failure needs a few more fields to be diagnosable. One of Tuesday's entries:
{
"time": "2026-10-06T09:12:04Z",
"event": "sign_in.id_token_rejected",
"message": "Sign-in rejected: the ID token failed the audience check",
"stage": "id_token_validation",
"check": "audience",
"expected_issuer": "https://auth.photos.example",
"expected_audience": null,
"kid": "photos-rs-2026-09",
"alg": "RS256",
"token_age_seconds": 2,
"server": "web-3",
"correlation_id": "signin-5f2c"
}
The stage and check say where validation stopped. The expected values show what the printer compared against, and on Tuesday they were the whole answer: anyone reading this entry could see that the printer had no expected audience at all. The kid and alg come from the token's header and separate key problems from others. token_age_seconds, the server's time minus the token's iat, exposes a drifting clock, since a negative age means a token from the future. The server name shows whether failures follow one machine. The correlation ID is the reference the person saw, and it ties this entry to the callback and the token request before it.
What the entry leaves out matters as much. It never holds the ID token, the access token from the same response, the authorization code, or the state and nonce values. Logs are read by more people and kept longer than most of what the printer stores, and the access token beside the ID token is a working credential. Your name and email address stay out too. When a value from the rejected token would genuinely help, such as the issuer it named when the issuer check failed, the printer records it shortened and marked as unverified, because anyone can write anything into a token that has not passed.
Entries like this are most useful in aggregate. Counting failures by check, server, and provider each hour turns Tuesday into a single line on a graph that jumps two minutes after the release. A rise in signature or nonce failures with no release behind it is the signal that someone is trying tokens they should not have.
Fixes that make things worse
A sign-in outage invites quick fixes, and the quickest ones switch off the check that failed instead of correcting what it compared against:
| Tempting fix | What it actually does | Fix instead |
|---|---|---|
| Turn off the audience check | Accepts ID tokens the photo service issued to any client, including the collage app. | Set the expected audience to photo-printer. |
| Accept whatever algorithm the header names | Brings back unsigned tokens and the HMAC confusion attack. | Confirm the provider's change, then add that one algorithm. |
| Widen the clock tolerance to an hour | Accepts expired tokens for an hour and widens the window for replays. | Repair the server's time synchronization. |
| Finish sign-ins whose pending attempt cannot be found | Removes what state and the nonce protect against: forged callbacks, injected codes, and replayed tokens. | Find out why the attempt is missing. |
| Use a key from the token when the key set is unreachable | Lets anyone sign a token with a key of their own and pass. | Use the cached set, retry with limits, and fail the sign-in otherwise. |
The missing-attempt row usually traces back to a cookie. Request correlation and CSRF followed a team whose callback stopped receiving its session cookie after a SameSite change. Without the attempt the cookie leads to, there is no state to match and no nonce to compare. The repair is the one that lesson gave for the cookie, not a callback that finishes without its attempt or searches every attempt for one that fits.
The most dangerous fix rarely looks like a decision at all. It is an error handler that records the failure and carries on, or a fallback that, when the ID token will not validate, asks the UserInfo endpoint who the access token belongs to. Authentication errors ruled out that fallback for a response with no ID token, and it is no safer for one whose ID token failed.
Look back at Tuesday's fault and the configuration mismatches at the start of this lesson. The issuer, the client ID, the key set address, and the algorithm list were values the printer simply had. The next group of lessons starts with where they come from: Provider discovery follows the printer as it reads the photo service's published configuration and decides how far to trust it.