Skip to content

New: personal access token management API (fixes #97)#98

Merged
taylortom merged 3 commits into
masterfrom
pat-tokens
Jul 13, 2026
Merged

New: personal access token management API (fixes #97)#98
taylortom merged 3 commits into
masterfrom
pat-tokens

Conversation

@taylortom

Copy link
Copy Markdown
Contributor

Fixes #97

Fixes #14

Fixes #95

Supersedes #96 — this branch includes and extends that scope-forwarding change, so #96 can be closed in favour of this PR.

New

  • name, expiresAt and a masked hint on the authtoken schema.
  • Personal access tokens are minted with an adpt_pat_<fragment>_ prefix and the full value is returned only once; the stored hint lets the owner recognise a token in a listing without exposing it. AuthToken.stripTokenPrefix() strips the prefix before verification, so session tokens (unprefixed) are unaffected.
  • generateTokenHandler forwards name, lifespan and scopes to AuthToken.generate. lifespan: "never" mints a non-expiring token; otherwise expiresAt is persisted from the token's expiry.
  • DELETE /tokens/:_id revokes a single token owned by the current user (ownership-scoped by _id + userId).
  • A super user may now mint a manual token, provided they supply explicit scopes that don't include the super wildcard (*:*); minting without scopes, or with *:*, still returns SUPER_TOKEN_FORBIDDEN.

Fix

  • GET /tokens no longer throws MODIFY_PROTECTED_ATTR (Fix /tokens API endpoint #14): the sanitise call now runs non-strict, so internal fields (e.g. signature) are stripped from the response rather than rejected. The listing also carries _id, is limited to personal (manual) tokens, and returns an empty array when there are none.
  • Revoke-by-id used createObjectId(id), which ignores its argument and mints a new random id, so the query matched nothing. Switched to parseObjectId(id).

Testing

  • Unit tests for resolveTokenScopes (super-lift cases), generateTokenHandler (name/lifespan/scopes forwarded; super no longer rejected outright), revokeTokenHandler (ownership-scoped, id parsed to an ObjectId) and stripTokenPrefix. Full suite (132) passes; standard clean.
  • End-to-end against a running server: super mint with/without scopes and with *:*; prefixed Bearer authentication and scope limiting; sanitised listing with _id; per-token revoke actually removing the record; revoked token rejected; empty listing.

@taylortom
taylortom merged commit 7b20f0f into master Jul 13, 2026
2 checks passed
@taylortom
taylortom deleted the pat-tokens branch July 13, 2026 19:13
github-actions Bot pushed a commit that referenced this pull request Jul 13, 2026
# [2.9.0](v2.8.0...v2.9.0) (2026-07-13)

### New

* personal access token management API (fixes #97) (#98) ([7b20f0f](7b20f0f)), closes [#97](#97) [#98](#98)
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 2.9.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Labels

Projects

1 participant