POST /logout read the token from the Authorization header only, while the
jwt guard also accepts the token and auth_token cookies. A session carried
by a cookie (golem15.sociallogin's token_cookie sets an httpOnly one that
the browser cannot turn into a bearer header) was answered 401, nothing was
revoked and the cookie kept authenticating jwt.auth routes until the access
token expired (golem15.user.jwt.ttl, 60 minutes). Logout never cleared a
cookie either, and it and EndRequestSession kept the jwt_blacklist row only
until the access token's exp, so once the sweep removed the row POST
/refresh revived the logged-out token for the rest of its refresh window.
classes.EndSession, which Logout now runs, revokes every session token the
request carries (the bearer header, the token and auth_token cookies) that
verifies, an expired one too while it could still be refreshed, until the
later of exp and iat plus refresh_ttl, plus a minute, as bouncer.Refresh
and the admin logout do. The answer, a 401 included, expires the
auth.cookie token cookie and any other session cookie the request carries,
with that cookie's path, domain, SameSite and Secure. EndRequestSession is
its best-effort form. Response bodies are unchanged; an expired but still
refreshable token now logs out with 200 instead of 401.
- TestRequestUser: bearer, token and auth_token cookies in guard order;
expired, foreign, blacklisted, revoked by tokens_valid_after and
deactivated tokens are anonymous; only infrastructure failures error
- TestEndRequestSession (no database): jti blacklisted until the token
expires, forget cookie with the configured Domain and Path, best effort
- TestAvatarURL: thumbnail, broken-image and storage-failure fallbacks,
gravatar with the size, the user payload's avatar_url unchanged
- TestDeactivatingEvent: one event per newly deactivated user inside the
bulk action's transaction, a listener error rolls the action back