Skip to content

Token revocation: model the OAuth endpoints, or bring revokeToken to every SDK #276

Closed

Description

@jeremy

Kotlin gained HeyClient.revokeToken in #270: DELETE /oauth/tokens, unsigned, following no redirect. It is hand-written, like the token exchange and refresh in Go, Rust and TypeScript, because the OAuth endpoints sit outside the API the Smithy model describes (scripts/drift-check-reverse filters ^/oauth).

That leaves two questions:

  1. Should the OAuth server be modelled? If /oauth/authorizations, /oauth/tokens (POST and DELETE) were in the spec, the hard rules (generated methods, route table, conformance in every SDK) would cover them, instead of each SDK carrying its own copy. The cost is that the model has to express what makes these requests unlike the API's: form bodies, no .json suffix, unsigned, no redirect, and no refresh on a 401.
  2. Until then, revocation exists only in Kotlin. Go, Rust, Swift and TypeScript have no way to revoke a token on sign-out. A shared conformance case would pin the contract Kotlin already tests: the token goes in the form body, never the query; no Authorization or DPoP header; a 3xx is the answer and is never followed; a 401 is not refreshed; 200 {} for an unknown token; invalid_client for another app's token.

Either answer works. The second can go ahead without the first, and the first would replace it.

Activity

  1. jeremy commented on Oct 22, 2026

    @jeremy
    MemberAuthor

    Decision: model the OAuth endpoints in the spec, so token exchange, refresh and revocation are generated in every SDK rather than hand-written per SDK. The model has to carry what sets these requests apart from the API's: form bodies, no .json suffix, unsigned, no redirect followed, and no refresh on a 401. Kotlin's hand-written revokeToken is the behavioural reference until it is replaced.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions