Filed from the objectui seat as the server-side half of objectui#4467's measurement (defence-in-depth companion to the console-side fix ruled there — option A, the data lane adopting set-auth-token rotation). Contract question — objectstack lane; this seat lands no code here.
The mechanism (measured, better-auth 1.6.26)
- A client authenticates with
Authorization: Bearer <token>; better-auth's bearer plugin before-hook overwrites the request's session cookie with the bearer token (dist/plugins/bearer/index.mjs: setRequestCookie(headers, authCookies.sessionToken.name, decodedToken)).
POST /api/v1/auth/admin/impersonate-user succeeds (200), sets the impersonation session cookie, emits the impersonated token via set-auth-token, and records admin_session.
- Every subsequent bearer-authenticated request resolves to the admin's session — the bearer beats the cookie the impersonation just set. The framework's own data routes resolve identity through the same path (
runtime/src/security/resolve-session-principal.ts:51, http-dispatcher.ts:940), so writes during "impersonation" are attributed to the ADMIN.
Net: for any bearer client (the console after every normal sign-in), impersonation returns success and does nothing — the worst shape, a 200 no-op on a security-relevant endpoint.
The defence-in-depth ask (whichever fits the auth contract)
- Reject a bearer-authenticated
impersonate-user unless the caller can adopt the rotation (or always: force clients through the rotation they must honor), OR
- invalidate/rotate the caller's bearer as part of impersonation, so the impersonated session is the only one that resolves afterwards.
Either makes "impersonation succeeded but did not take effect" structurally impossible server-side, independent of client lane discipline. The console-side fix (objectui#4467 option A) closes the live gap for this client; this card is about the class.
Also relevant: stop-impersonating resolves the admin via the admin_session COOKIE only — in cookie-blocked deployments (the exact context bearer() exists for) the exit path cannot work; worth deciding whether the endpoint should also honor a bearer-carried recovery.
Refs: objectui#4467 (measurement + console ruling), objectui#4304 (duplicate, closed).
Filed unassigned for the objectstack triage/decision lane.
Generated by Claude Code
Filed from the objectui seat as the server-side half of objectui#4467's measurement (defence-in-depth companion to the console-side fix ruled there — option A, the data lane adopting
set-auth-tokenrotation). Contract question — objectstack lane; this seat lands no code here.The mechanism (measured, better-auth 1.6.26)
Authorization: Bearer <token>; better-auth's bearer plugin before-hook overwrites the request's session cookie with the bearer token (dist/plugins/bearer/index.mjs:setRequestCookie(headers, authCookies.sessionToken.name, decodedToken)).POST /api/v1/auth/admin/impersonate-usersucceeds (200), sets the impersonation session cookie, emits the impersonated token viaset-auth-token, and recordsadmin_session.runtime/src/security/resolve-session-principal.ts:51,http-dispatcher.ts:940), so writes during "impersonation" are attributed to the ADMIN.Net: for any bearer client (the console after every normal sign-in), impersonation returns success and does nothing — the worst shape, a 200 no-op on a security-relevant endpoint.
The defence-in-depth ask (whichever fits the auth contract)
impersonate-userunless the caller can adopt the rotation (or always: force clients through the rotation they must honor), OREither makes "impersonation succeeded but did not take effect" structurally impossible server-side, independent of client lane discipline. The console-side fix (objectui#4467 option A) closes the live gap for this client; this card is about the class.
Also relevant:
stop-impersonatingresolves the admin via theadmin_sessionCOOKIE only — in cookie-blocked deployments (the exact context bearer() exists for) the exit path cannot work; worth deciding whether the endpoint should also honor a bearer-carried recovery.Refs: objectui#4467 (measurement + console ruling), objectui#4304 (duplicate, closed).
Filed unassigned for the objectstack triage/decision lane.
Generated by Claude Code