Skip to content

Migrate from lestrrat-go/jwx/v2 (EOL) to v3 #4383

Description

@reinkrul

As of v2.1.7, github.com/lestrrat-go/jwx/v2 is marked deprecated by the maintainers via Go module deprecation — the v2 series is no longer maintained. See the v2.1.7 release notes. No further bug or security fixes will land on v2.

jwx is a core JWT/JWS/JWK/crypto dependency, so staying on an unmaintained version is a security-relevant liability.

Target: v3 (not v4, for now)

We evaluated jumping straight to v4 (latest major, v4.1.0) but chose v3 (v3.1.1) as the immediate target.

Why not v4 yet — GOEXPERIMENT=jsonv2:

  • v4 hard-depends on the standard library encoding/json/v2 package (15 import sites in v4). Its MIGRATION.md lists GOEXPERIMENT=jsonv2 as a required build prerequisite.
  • In Go 1.26 (our current toolchain: go 1.26.3, Docker golang:1.26.4), json/v2 is still gated behind that experiment flag. Shipping v4 would mean setting GOEXPERIMENT=jsonv2 in the Dockerfile builder, every CI workflow, and local dev — i.e. an experimental Go feature baked into the production build of a crypto/auth-sensitive node. Not acceptable right now.
  • v4 is also two major versions away (v2 -> v3 -> v4); each hop has its own breaking changes.

Why v3 is the right step:

  • Gets us off the EOL v2 now (the actual security goal).
  • Single major-version hop, no experimental build flag, no companion-module split.
  • v3 is actively maintained (v3.1.1, not deprecated).

Revisit v4 later once json/v2 graduates out of GOEXPERIMENT (expected in a near-future Go release). At that point v3 -> v4 is largely mechanical via the jwxmigrate tool. Tracked as a follow-up.

v2 -> v3 breaking changes to handle

  • jwa.RS256 (and all algorithm constants) become function calls jwa.RS256().
  • xxx.Get(name) signature changes to Get(name, &dst) error.
  • Convenience accessors (e.g. token.Subject()) now return (T, bool) instead of T.
  • Error renames (ErrXXX() -> XXXError()); errors are now matchable via errors.Is.
  • JWS iterators removed.
  • Only known algorithm names parse by default (register others via jwa.RegisterXXX).

Scope

  • 84 Go files import github.com/lestrrat-go/jwx/v2, concentrated in crypto/ and auth/api/iam/.
  • jwx/v3 is already present as an indirect dependency in go.mod.

Work

  • Migrate imports v2 -> v3 across crypto/, auth/, test/, etc.
  • Rewrite jwa constants to function-call form and adapt Get/accessor call sites.
  • Drop the jwx/v2 requirement from go.mod once no direct importers remain.
  • Regenerate mocks / generated code as needed.
  • Full test + e2e run.
  • Land on master, v6.2, and v5.4.

Follow-up

  • Migrate v3 -> v4 once encoding/json/v2 is no longer behind GOEXPERIMENT.

Target branches

Apply the migration on:

  • v5.4
  • v6.2
  • master

Assisted by AI

Metadata

Metadata

Assignees

No one assigned

    Labels

    dependenciesPull requests that update a dependency file

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions