Skip to content

fix(clerk_auth): authenticate the DELETE that signs out - #446

Open
dbeattie71 wants to merge 1 commit into
clerk-community:mainfrom
bytefoo:fix/authenticate-delete-requests
Open

fix(clerk_auth): authenticate the DELETE that signs out#446
dbeattie71 wants to merge 1 commit into
clerk-community:mainfrom
bytefoo:fix/authenticate-delete-requests

Conversation

@dbeattie71

Copy link
Copy Markdown

Fixes #445.

_delete cleared the token cache before building the request. _headers attaches Authorization only while the cache still holds a client token, and _queryParams reads sessionId from the same place, so DELETE /v1/client went out identifying neither client nor session.

The back end answers 200 to that without revoking anything, and signOut returns Client.empty regardless, so the caller discards its local state and reports success. Sign-out was a local forget: the session stays active until it expires naturally, and any token minted from it stays valid. Verified against a live instance — a session queried through the Backend API immediately after a successful-looking sign-out still reported status: active, with its original abandon_at a month out.

deleteUser() shares the helper via DELETE /me and is worse off, since requiresSessionId: true also depends on the sessionId cleared on that same line. It reports deleting an account it has not deleted.

The change

final headers = _headers(method: HttpMethod.delete);   // build first
try {
  ...
} finally {
  _tokenCache.clear();                                 // then drop local credentials
}

The finally is deliberate: local credentials must be dropped whether or not the request succeeds, so a sign-out that cannot reach the network still signs the user out of that device.

Tests

  • sign_out_authentication_test.dart — asserts the sign-out DELETE carries the client token. Confirmed failing before the fix (Expected: <true> Actual: <null>).
  • a second case asserting local state is still cleared when the request fails, which pins the finally so a later refactor cannot quietly reintroduce a sign-out that leaves the user signed in offline.

clerk_auth suite green: 647 passing.

Note

Independent of #444, which fixes the identifier-casing bug in attemptSignIn. The two do not overlap and can land in either order.

`_delete` cleared the token cache before building the request. `_headers`
attaches the Authorization header only while the cache still holds a client
token, and `_queryParams` reads `sessionId` from the same place, so the DELETE
went out identifying neither client nor session.

The back end answers 200 to that request without revoking anything, and
`signOut` returns `Client.empty` regardless, so the caller discards its local
state and reports success. Sign-out therefore became a local forget: the
session stays active until it expires naturally, and any token already minted
from it stays valid. Verified against a live instance — a session queried
through the Backend API immediately after a successful-looking sign-out still
reported `status: active`.

`deleteUser` uses the same helper via `DELETE /me` and is worse off, because
`requiresSessionId: true` also reads the cleared `sessionId`. It reports
deleting an account it has not deleted.

Building the headers first fixes both. The clear moves into a `finally` so
local credentials are still dropped when the request fails — a sign-out that
cannot reach the network must still sign the user out of this device.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sign out does not revoke the session: _delete clears the token cache before building the request, so the DELETE is unauthenticated

2 participants