jwt

package
v1.2.12 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 3, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

README

jwt

jwt strictly parses, signs, and verifies a bounded signed JWT subset for Go and TinyGo. Verification requires an explicit algorithm allowlist and a resolver that returns a key bound to the same algorithm. alg=none, unsupported critical headers, duplicate JSON members, non-canonical Base64url, ambiguous JWKS matches, and oversized input are rejected.

Supported algorithms are HS256 and RS256, in both directions. ES256, EdDSA, and JWE are not supported.

It is a JWS implementation

A JWT is claims serialized as a JWS, so the three-segment header.payload.signature form is JWS Compact Serialization (RFC 7515) by definition. That is what this package implements — Token.signingInput is the JWS Signing Input of section 2, under that name — and there is no separate JWS layer to add.

The scope is the JWT subset of JWS only. Sign takes claims, not bytes, so JSON Serialization, detached payloads, multiple signatures, and non-JSON payloads are all absent. If a caller ever needs to sign something that is not a claim set, the honest change is to extract an internal core holding the signing input, the compact serialization, and the algorithm dispatch, leaving this package as the claims layer on top. Renaming it to jws would be the wrong fix: the package is offset from JWS in both directions, doing more than JWS (it validates iss, aud, exp, nbf, iat) and less (no arbitrary payloads).

Provenance and divergence

This package came from github.com/shibukawa/popcornwave/contrib/jwt, which implements the verifier half for resource servers. One change was made here:

  • RS256 signing. Upstream Sign accepted HS256 only and rejected every other algorithm outright, while RS256 verification already existed. This copy widens the guard to the same set verifySignature accepts.

Nothing else was altered. jwks.go and verify.go are carried unchanged even though a client that only mints tokens never calls them; the linker drops what is unused, so keeping the package whole costs maintenance clarity rather than binary size.

internal/authn carries the upstream bounded Base64url and JSON validation helpers. http.go was not copied: this package never referenced it, and it would pull net, net/http, and net/url into a TinyGo build for nothing.

Signing with RS256

This package holds no RSA code. A signer supplies it, which is what keeps jwt free of build tags and cgo:

signer, err := google.NewRSASigner(credentials) // implements jwt.Signer
token, err := jwt.Sign(jwt.Header{KeyID: keyID}, claims, signer)

cloud/google provides such a signer over internal/rsasign, which uses crypto/rsa on host Go and the OS crypto library on TinyGo builds.

Documentation

Overview

Package jwt strictly parses, signs, and verifies a bounded signed JWT subset.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrMalformed            = errors.New("jwt: malformed token")
	ErrLimitExceeded        = errors.New("jwt: limit exceeded")
	ErrUnsupportedAlgorithm = errors.New("jwt: unsupported algorithm")
	ErrInvalidSignature     = errors.New("jwt: invalid signature")
	ErrInvalidClaims        = errors.New("jwt: invalid claims")
	ErrKeyNotFound          = errors.New("jwt: verification key not found")
	ErrAmbiguousKey         = errors.New("jwt: ambiguous verification key")
	ErrInvalidOptions       = errors.New("jwt: invalid options")
)

Functions

func Sign

func Sign(header Header, claims Claims, signer Signer) (string, error)
Example
package main

import (
	"fmt"

	"github.com/shibukawa/tinygodriver/jwt"
)

func main() {
	signer, err := jwt.NewHMACSigner([]byte("01234567890123456789012345678901"))
	if err != nil {
		panic(err)
	}
	raw, err := jwt.Sign(jwt.Header{}, jwt.Claims{Issuer: "issuer"}, signer)
	if err != nil {
		panic(err)
	}
	token, err := jwt.Parse(raw, jwt.ParseOptions{})
	if err != nil {
		panic(err)
	}
	fmt.Println(token.Header.Algorithm)
}
Output:
HS256

Types

type Claims

type Claims struct {
	Issuer    string
	Subject   string
	Audience  []string
	ExpiresAt *int64
	NotBefore *int64
	IssuedAt  *int64
	ID        string
	Raw       map[string]json.RawMessage
}

func ParseAndVerify

func ParseAndVerify(compact string, resolver KeyResolver, parseOptions ParseOptions, verifyOptions VerifyOptions) (Claims, error)

func Verify

func Verify(token *Token, resolver KeyResolver, options VerifyOptions) (Claims, error)

func (Claims) MarshalJSON

func (c Claims) MarshalJSON() ([]byte, error)

func (Claims) String

func (c Claims) String(name string) (string, bool)

func (Claims) Value

func (c Claims) Value(name string) (json.RawMessage, bool)

type HMACSigner

type HMACSigner struct {
	// contains filtered or unexported fields
}

func NewHMACSigner

func NewHMACSigner(key []byte) (*HMACSigner, error)

func (*HMACSigner) Algorithm

func (*HMACSigner) Algorithm() string

func (*HMACSigner) Sign

func (s *HMACSigner) Sign(signingInput []byte) ([]byte, error)
type Header struct {
	Algorithm string          `json:"alg"`
	Type      string          `json:"typ,omitempty"`
	KeyID     string          `json:"kid,omitempty"`
	Critical  []string        `json:"crit,omitempty"`
	Raw       json.RawMessage `json:"-"`
}

type JWKS

type JWKS struct {
	// contains filtered or unexported fields
}

func ParseJWKS

func ParseJWKS(data []byte, options JWKSOptions) (*JWKS, error)

func (*JWKS) ResolveKey

func (set *JWKS) ResolveKey(header Header) (VerificationKey, error)

type JWKSOptions

type JWKSOptions struct {
	MaxBytes int
	MaxKeys  int
}

type KeyResolver

type KeyResolver interface {
	ResolveKey(header Header) (VerificationKey, error)
}

type KeyResolverFunc

type KeyResolverFunc func(header Header) (VerificationKey, error)

func (KeyResolverFunc) ResolveKey

func (resolve KeyResolverFunc) ResolveKey(header Header) (VerificationKey, error)

type ParseOptions

type ParseOptions struct {
	MaxTokenBytes   int
	MaxSegmentBytes int
	MaxJSONDepth    int
	MaxJSONMembers  int
}

type Signer

type Signer interface {
	Algorithm() string
	Sign(signingInput []byte) ([]byte, error)
}

type Token

type Token struct {
	Header    Header
	Claims    Claims
	Signature []byte
	// contains filtered or unexported fields
}

func Parse

func Parse(compact string, options ParseOptions) (*Token, error)

type VerificationKey

type VerificationKey struct {
	Algorithm string
	HMAC      []byte
	RSA       *rsa.PublicKey
}

type VerifyOptions

type VerifyOptions struct {
	AllowedAlgorithms      []string
	Issuer                 string
	Audience               string
	TokenType              string
	AllowMissingExpiration bool
	AllowFutureIssuedAt    bool
	Clock                  func() time.Time
	Leeway                 time.Duration
}

Directories

Path Synopsis
internal
authn
Package authn contains the bounded parsing primitives the jwt package shares.
Package authn contains the bounded parsing primitives the jwt package shares.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL