Repository navigation
jwt v0.3.0
The Go 1.27 release. Every change below follows from
that toolchain bump, either because
Go 1.27 is now required to build the package at all,
or because it made something the
package already did possible to do faster or more
directly. Nothing about what verifies or
what gets signed changed on purpose:
testdata/golden.json is byte-for-byte identical to
v0.2.0.
Upgrading
Two things to check before you take it:
- Bump your own
godirective to 1.27 or newer
first.go.modnow requires it, for
encoding/json/v2and the standard libraryuuid
package. A consumer on an older
toolchain gets a build error, not a warning. - If anything parses or length-checks
SignPair's
generatedjti, expect 36
characters (a UUID) instead of 22 (base64url). Set
PairOptions.GenerateIDto keep the
old format if you need to; the doc comment on the
field shows the four-line replacement.
A token already signed under the old format still
verifies, sincejtiis opaque to
everything but whoever reads it.
Nothing else needs a code change. The
Marshal/Unmarshal and Claims/Merge behavior a
caller can observe from outside the package is
unchanged, and the two new generic methods
are additive.
Faster, from the same two changes
Verify's allocation count dropped for two
independent reasons: token parsing moved from
bytes.Split to bytes.CutLast/bytes.Cut (no more
[][3]byte allocation, no re-join of
header and payload for signature verification), and
the default Marshal/Unmarshal moved
to encoding/json/v2, with an option set chosen to
reproduce encoding/json's (v1) output
exactly rather than to change it.
| Before (Go 1.26.5) | Now (Go 1.27.0) | |
|---|---|---|
Verify |
18 allocs, 1376 B | 12 allocs, 968 B |
Sign (map) |
23 allocs, 1441 B | 27 allocs, 1441 B |
Sign (struct) |
21 allocs, 1520 B | 23 allocs,1520 B |
Sign's allocation count moved the other way, and
that one is not this package's doing:
Go 1.27's own encoding/json is now implemented in
terms of encoding/json/v2 with a
compatibility layer, and that layer costs more for a
map- or struct-shaped marshal than Go
1.26's implementation did. Moving Marshal's own call
site directly onto
encoding/json/v2 recovered the speed but not the
allocation count. All figures measured
windows/arm64; see CHANGELOG.md and
book/14-performance.md for the fuller breakdown.
Fixed
An EC JWK is parsed with
ecdsa.ParseUncompressedPublicKey rather than by
assigning X
and Y. Go 1.26 deprecated both fields, so the old
code was a lint failure under this
toolchain, and the replacement does more than silence
the warning: crypto/ecdsa rejects a
point that is not on the curve. A malformed or hostile
JWKS entry that used to become an
*ecdsa.PublicKey and fail later, unpredictably, now
fails at the point it is read.
New
(*VerifiedToken).ClaimsAs[T]and
(*UnverifiedToken).ClaimsAs[T], the generic form
ofClaims(dest any):user, err := verifiedToken.ClaimsAs[UserClaims]()in place of
declaring a variable and passing its address.VerifyAs[T], combiningVerifyand
ClaimsAs[T]for the common case where nothing
else about the*VerifiedTokenis needed:claims, verifiedToken, err := jwt.VerifyAs[UserClaims](alg, key, token).SignPair's defaultjtiis a version 7 UUID
from the standard library, time-ordered
and friendlier to a blocklist or any other index
keyed onjti, in place of 22 characters
of base64url randomness. See Upgrading above.
Also in this release
go fix's Go 1.27 modernizers, applied and reviewed:errors.AsType[E]in place of the
var target E; errors.As(err, &target)pattern,sync.WaitGroup.Goin place of manual
Add/Done/go func(), range-over-integer in place of counted loops. None change
behavior.- CI moved to Go 1.27,
actions/setup-go/actions/checkoutto v7 (Node 24, off the
deprecated Node 20 both v6 still ran on), and the pinnedgolangci-lintversion to
v2.13. The last one is not routine: v2.12's release binary was built with Go 1.26.2, and
a golangci-lint binary refuses to run at all once a module'sgodirective exceeds the
Go version it was itself built with.go.modmoving togo 1.27made that pin a hard
CI failure, not a lint diff. go.modstill has no requirements, and it is not going to get any.
Full detail, including everything not listed here, is in CHANGELOG.md.