Ask for the picture the way providers actually offer it

Two assumptions, both mine, and either one was enough for an account to end
up with no picture. It was looked for only in the ID token, which a provider
is free to keep lean while holding the rest at userinfo — PocketID does
exactly that — and the endpoint was never asked. Then the image was fetched
with no credentials, while avatars are commonly behind the provider's own
login.

Userinfo is now asked when something is missing, and believed only when its
sub matches the token whose signature was checked. The access token rides
along with the picture request when, and only when, the picture lives at the
provider.

The third fault was the one that cost the time: it failed silently, so there
was no way to tell which of the two it was. Every outcome is a line in the
log now. And the test provider keeps its picture out of the token and behind
its door, so the check passing is evidence for both new paths.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
marcandClaude Opus 5 committed 2026-08-21 18:55:19 +02:00
1 parent a2b3f91e00
commit 1e2375f190
6 files changed
+152 -19

No files matched your search

+27
View File
@@ -14,6 +14,33 @@ a rebuild is not bit-identical.
---
## 2026-08-21 — Asking for the picture properly
**Images** — web `sha256:4310304d…`, server `sha256:7a486929…`
The server image changed; the web image only because `build.sh` builds both.
**Fixed**
- **The profile picture never arrived**, and two assumptions of mine were why.
The picture was only looked for in the ID token — a provider may keep its token
lean and hold the rest at its `userinfo` endpoint, which is what PocketID does,
and that endpoint was never asked. And the image was then fetched with no
credentials at all, while providers commonly keep avatars behind their own
login. The endpoint is now asked when something is missing (and its answer
trusted only if the `sub` matches the verified token), and the access token
goes with the picture request — but only when the picture lives at the
provider, because a token sent to a third party is a credential given away.
- **And it failed in silence**, which is the part that actually cost the time:
there was no way to see which of those two it was. Every outcome is now one
line in the server log — stored, no claim, refused, not an image, too large,
unreachable.
The test provider now behaves like a lean one: it leaves the picture out of the
token and hands it over only against the access token, so the check passing is
evidence for both new paths.
---
## 2026-08-21 — The face from the provider, and whose business a password is
**Images** — web `sha256:e525b11d…`, server `sha256:95d56c46…`