Skip to content

test(jwt): stale guides on rotation and the blind index, unpinned claim checks, and no known-answer tests #480

Description

@Jaro-c

The remaining findings of the 2026-09-25 review of auth/jwt, auth/credential, auth/apikey and auth/field. No behaviour changes; each is a guide that says the wrong thing or a control nothing pins.

  1. docs/secure-login.md section 5 still replaces the refresh hash unconditionally and claims the second presentation of a replayed token "finds no matching hash". Two requests carrying the same token that read the row before either writes both rotate and both get a pair; docs: fix the recipes that lose credentials #427 fixed the same block in docs/jwt.md only.
  2. The auth/field package doc still says an index hit proves the plaintext, the claim docs: fix the recipes that lose credentials #427 removed from docs/field.md, and shows a read path that decrypts without re-checking.
  3. docs/configuration.md describes the credential binding as purpose || 0x00 || subject || 0x00 || token, the construction the code itself calls the bug it replaced with length prefixes; docs/errors.md has no row for jwt.ErrTokenOversized or jwt.ErrNotInitialised.
  4. docs/key-management.md says the refresh secret gives "cryptographic separation", which is true of auth/field only: apikey.Hash, jwt.HashRefreshToken and totp.HashRecoveryCode key HMAC with the raw secret and produce one digest for one string.
  5. Controls that could be deleted with the suite green: WithExpirationRequired and WithIssuedAt on both verifiers (the no-exp test's fixture used jti as its jti, which fix(jwt): make issuance and verification agree #443's shape check refuses first, so the test stayed green for the wrong reason); the zero-value guard in jwt.VerifyRefreshTokenHash (its test used a hash no key produces) and in apikey.Hash (no test); the dash, variant and hex checks of isUUIDv7; ParseID's lowercase-hex rule and prefix check (the uppercase fuzz seed uppercases the prefix too, so it never reaches the hex rule); the refresh-token issuance cap from fix(jwt): make issuance and verification agree #443; the leeway on the refresh path; the empty-audience check in validateConfig, unreachable through New.
  6. Both jwt fuzz targets have no oracle: FuzzVerifyAccessToken discards the result and FuzzIsUUIDv7 checks nothing, although its seed set already holds the variant-c input the variant mutant accepts.
  7. No known-answer test pins any stored format: the HKDF labels, the credential field order, the apikey hash input and the refresh-hash digest can all change with the suite green, and every stored ciphertext or hash then stops matching after an upgrade.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions