3 Commits

Author SHA1 Message Date
ac25aa2ee5
ajwt: fix Audience type, digestFor panic, validator bugs, fetcher staleness
- Add Audience type (RFC 7519 §4.1.3): unmarshals string or []string,
  marshals to string for single value and array for multiple
- Fix digestFor panic: return ([]byte, error) instead of panicking on
  unsupported hash; plumb error through Sign and verifyWith callers
- Fix headerJSON marshal error: propagate instead of discarding in
  NewJWSFromClaims and JWS.Sign (all three key-type branches)
- Fix MaxAge/IgnoreAuthTime interaction: IgnoreAuthTime: true now
  correctly skips auth_time checks even when MaxAge > 0
- Fix "unchecked" warnings for Jti/Nonce/Azp: invert to opt-in —
  these fields are only validated when the Validator has them set
- Fix MultiValidator.Aud for Audience type: checks if any token
  audience value is in the allowed list (set intersection)
- Fix stale now in JWKsFetcher slow path: recapture time.Now() after
  acquiring the mutex so stale-window checks use a current timestamp
- Remove RespectHeaders no-op field from JWKsFetcher
- Simplify RSA exponent decode: use big.Int.IsInt64() instead of
  platform-dependent int size check
2026-03-13 12:04:15 -06:00
52ffecb5b3
ajwt: rename encode/fetch functions, add Signer.ToJWKs/ToJWKsJSON
Renames:
- EncodePublicJWK → ToJWK (package-level, single key)
- MarshalPublicJWKs → ToJWKs (package-level, raw JSON bytes)
- FetchJWKs → FetchJWKsURL
- FetchJWKsFromOIDC → FetchOIDCURL
- FetchJWKsFromOAuth2 → FetchOAuth2URL

New:
- ToJWKsJSON([]PublicJWK) (JWKsJSON, error) — package-level, struct form
- Issuer.ToJWKsJSON() (JWKsJSON, error)
- Signer.ToJWKs() ([]byte, error)
- Signer.ToJWKsJSON() (JWKsJSON, error)
2026-03-13 11:33:04 -06:00
2f946d28b5
ajwt: redesign API — immutable Issuer, Signer, JWKsFetcher
Key changes from previous design:

- Issuer is now immutable after construction (no mutex, no SetKeys)
- New(keys []PublicJWK) — no issURL or Validator baked in
- Verify returns (nil, err) on any failure; UnsafeVerify returns (*JWS, err)
  even on sig failure so callers can inspect kid/iss for multi-issuer routing
- VerifyAndValidate takes ClaimsValidator per-call instead of baking it into
  the Issuer; soft errors in errs, hard errors in err, nil sentinel discarded
- ClaimsValidator interface implemented by *Validator and *MultiValidator
- MultiValidator: []string for iss, aud, azp (multi-tenant)
- Signer: round-robin across NamedSigner keys via atomic.Uint64; auto-KID
  from RFC 7638 thumbprint; Issuer() returns *Issuer with signer's public keys
- JWKsFetcher: lazy, no background goroutine; Issuer(ctx) checks freshness
  per call and creates new *Issuer on cache miss; KeepOnError + StaleAge for
  serving stale keys on fetch failure
- pub.go: add EncodePublicJWK and MarshalPublicJWKs (encode counterparts)
- Remove NewWithJWKs, NewWithOIDC, NewWithOAuth2 constructors from Issuer
2026-03-13 11:23:50 -06:00