Files
zeekay 899abd0f1d hanzoai/jwt: shared JWT sign/verify/JWKS for the Hanzo platform
One canonical Claims + User, one Signer (RS256/RS512/ES256/384/512/MLDSA65,
default RS256), one Parser/Verifier (cert + JWKS paths), one JWKS builder —
imported by iam2 (mints), cloud + gateway (validate), collapsing three
hand-synced JWT-validator copies into one. Clean leaf (go-jose + golang-jwt +
luxfi/crypto/mldsa only; zero hanzoai/* imports, no cycle). Ported the ML-DSA-65
signing method + Claims shape from hanzoai/iam v1 with field parity on every
validated field (owner/scope/project/azp/aud/iss/sub/email). 9/9 tests green
incl RS256+MLDSA65 round-trip, JWKS, and audience/issuer/expiry/wrong-key
rejection.
2026-07-14 22:01:37 -07:00

23 lines
805 B
Go

// Copyright 2026 Hanzo AI, Inc. All rights reserved.
package jwt
import gojwt "github.com/golang-jwt/jwt/v5"
// Sign mints a signed JWT for claims using key. The algorithm is taken from the
// key (Key.CryptoAlgorithm → Method), and the key id (Key.Name) is stamped into
// the `kid` header so a verifier can select the matching public key from the
// published JWKS. This is the one mint path shared by every issuer: claims are
// serialized exactly as declared, so the wire shape is identical everywhere.
func Sign(key Key, claims *Claims) (string, error) {
signingKey, err := key.signingKey()
if err != nil {
return "", err
}
token := gojwt.NewWithClaims(Method(key.CryptoAlgorithm), claims)
if key.Name != "" {
token.Header["kid"] = key.Name
}
return token.SignedString(signingKey)
}