tokenstatuslist

package
v0.5.5 Latest Latest
Warning

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

Go to latest
Published: Mar 27, 2026 License: BSD-2-Clause Imports: 14 Imported by: 0

Documentation

Overview

Package tokenstatuslist provides types and errors for Token Status List operations per draft-ietf-oauth-status-list specification.

Package tokenstatuslist provides types and functions for Token Status List operations per draft-ietf-oauth-status-list specification.

The package supports both JWT (Section 5) and CWT (Section 6) formats for Status List Tokens.

Index

Examples

Constants

View Source
const (
	CoseAlgES256 = -7  // ECDSA w/ SHA-256 (P-256 curve)
	CoseAlgES384 = -35 // ECDSA w/ SHA-384 (P-384 curve)
	CoseAlgES512 = -36 // ECDSA w/ SHA-512 (P-521 curve)
)

COSE algorithm identifiers (RFC 8152 Section 8.1) Use these constants with CWTSigningConfig.Algorithm

View Source
const (
	StatusValid     uint8 = 0 // VALID (0x00)
	StatusInvalid   uint8 = 1 // INVALID (0x01)
	StatusSuspended uint8 = 2 // SUSPENDED (0x02)
)

Status values per the specification

View Source
const (
	MediaTypeJWT = "application/statuslist+jwt"
	MediaTypeCWT = "application/statuslist+cwt"
)

Media types for Status List Tokens

View Source
const Bits = 8

Bits is the number of bits per status entry. We hardcode to 8 bits (1 byte per status) which supports status values 0-255.

View Source
const (
	// CWTTypHeader is the typ header value for Status List Token CWTs (Section 6.1)
	CWTTypHeader = "statuslist+cwt"
)

CWT constants per RFC 8392 and draft-ietf-oauth-status-list Section 6

View Source
const JWTTypHeader = "statuslist+jwt"

JWTTypHeader is the typ header value for Status List Token JWTs (Section 5.1)

Variables

View Source
var ErrHistoricalResolutionNotSupported = errors.New("historical resolution not supported: time parameter provided but this server does not maintain historical status lists")

ErrHistoricalResolutionNotSupported is returned when the time parameter is provided but the server does not maintain historical status lists (Section 8.4).

View Source
var ErrInvalidSectionID = errors.New("invalid section ID")

ErrInvalidSectionID is returned when the section ID is invalid.

View Source
var ErrInvalidStatusIndex = errors.New("invalid status index: out of bounds")

ErrInvalidStatusIndex is returned when the status index is out of bounds.

View Source
var ErrInvalidStatusValue = errors.New("invalid status value: must be 0 (VALID), 1 (INVALID), or 2 (SUSPENDED)")

ErrInvalidStatusValue is returned when the status value is not a valid Status Type (0-2 per Section 7.1).

View Source
var ErrInvalidTimeParameter = errors.New("invalid time parameter: must be a Unix timestamp")

ErrInvalidTimeParameter is returned when the time query parameter is not a valid Unix timestamp.

View Source
var ErrSectionNotFound = errors.New("section not found")

ErrSectionNotFound is returned when the requested section does not exist.

View Source
var ErrTokenGenerationFailed = errors.New("failed to generate status list token")

ErrTokenGenerationFailed is returned when the Status List Token JWT generation fails.

Functions

func CompressAndEncode

func CompressAndEncode(statuses []uint8) (string, error)

CompressAndEncode compresses statuses and encodes them as base64url without padding. This is the format used in JWT Status List Tokens (Section 5.1).

Example
package main

import (
	"fmt"

	"github.com/SUNET/vc/pkg/tokenstatuslist"
)

func main() {
	statuses := []uint8{
		tokenstatuslist.StatusValid,
		tokenstatuslist.StatusInvalid,
		tokenstatuslist.StatusSuspended,
	}

	encoded, err := tokenstatuslist.CompressAndEncode(statuses)
	if err != nil {
		fmt.Println("error:", err)
		return
	}

	// Decode and decompress to verify round-trip
	decoded, err := tokenstatuslist.DecodeAndDecompress(encoded)
	if err != nil {
		fmt.Println("error:", err)
		return
	}

	fmt.Println("round-trip match:", decoded[0] == statuses[0] && decoded[1] == statuses[1] && decoded[2] == statuses[2])
	fmt.Println("decoded[0]:", decoded[0])
	fmt.Println("decoded[1]:", decoded[1])
	fmt.Println("decoded[2]:", decoded[2])
}
Output:
round-trip match: true
decoded[0]: 0
decoded[1]: 1
decoded[2]: 2

func CompressStatuses

func CompressStatuses(statuses []uint8) ([]byte, error)

CompressStatuses compresses a status byte array using DEFLATE (zlib) compression as specified in Section 4.1 of the specification.

func DecodeAndDecompress

func DecodeAndDecompress(encoded string) ([]uint8, error)

DecodeAndDecompress decodes a base64url string and decompresses it. This is used to parse JWT Status List Tokens.

Example
package main

import (
	"fmt"

	"github.com/SUNET/vc/pkg/tokenstatuslist"
)

func main() {
	// First encode some statuses
	original := []uint8{0, 1, 2, 0, 1}
	encoded, err := tokenstatuslist.CompressAndEncode(original)
	if err != nil {
		fmt.Println("error:", err)
		return
	}

	// Then decode and decompress
	statuses, err := tokenstatuslist.DecodeAndDecompress(encoded)
	if err != nil {
		fmt.Println("error:", err)
		return
	}

	fmt.Println("length:", len(statuses))
	fmt.Println("statuses:", statuses)
}
Output:
length: 5
statuses: [0 1 2 0 1]

func DecompressStatuses

func DecompressStatuses(compressed []byte) ([]uint8, error)

DecompressStatuses decompresses a zlib-compressed status byte array.

func GenerateCWT

func GenerateCWT(cfg CWTConfig) ([]byte, error)

GenerateCWT creates a signed Status List Token CWT per Section 6.1. Deprecated: Use StatusList.GenerateCWT instead.

func GenerateJWT

func GenerateJWT(cfg JWTConfig) (string, error)

GenerateJWT creates a signed Status List Token JWT per Section 5.1. Deprecated: Use StatusList.GenerateJWT instead.

func GetStatus

func GetStatus(statuses []uint8, index int) (uint8, error)

GetStatus retrieves the status value at the given index from a status list. The index corresponds to the "idx" value in the Referenced Token's status claim.

Example
package main

import (
	"fmt"

	"github.com/SUNET/vc/pkg/tokenstatuslist"
)

func main() {
	statuses := []uint8{0, 1, 2, 0}

	s, err := tokenstatuslist.GetStatus(statuses, 2)
	if err != nil {
		fmt.Println("error:", err)
		return
	}

	fmt.Println("status at index 2:", s)
}
Output:
status at index 2: 2

func GetStatusFromCWT

func GetStatusFromCWT(claims map[int]any, index int) (uint8, error)

GetStatusFromCWT retrieves a status value from parsed CWT claims. The index corresponds to the "idx" value in the Referenced Token's status claim.

func GetStatusFromJWT

func GetStatusFromJWT(claims *JWTClaims, index int) (uint8, error)

GetStatusFromJWT retrieves a status value from a parsed JWT Status List Token. The index corresponds to the "idx" value in the Referenced Token's status claim.

func ParseCWT

func ParseCWT(cwtBytes []byte) (map[int]any, error)

ParseCWT parses a Status List Token CWT and returns the claims. Note: This function does NOT verify the signature. Use VerifyCWT for full validation.

Types

type CWTConfig

type CWTConfig struct {
	TokenConfig

	// SigningKey is the private key for signing (REQUIRED, must be *ecdsa.PrivateKey)
	SigningKey crypto.PrivateKey

	// Algorithm specifies the COSE algorithm (default: ES256)
	Algorithm int
}

CWTConfig holds CWT-specific configuration for generating a Status List Token. Deprecated: Use StatusList.GenerateCWT with CWTSigningConfig instead.

type CWTSigningConfig

type CWTSigningConfig struct {
	// SigningKey is the private key for signing (REQUIRED, must be *ecdsa.PrivateKey)
	SigningKey crypto.PrivateKey

	// Algorithm specifies the COSE algorithm (default: CoseAlgES256)
	// Use CoseAlgES256 (-7), CoseAlgES384 (-35), or CoseAlgES512 (-36)
	Algorithm int
}

CWTSigningConfig holds CWT-specific signing configuration.

type CWTStatusList

type CWTStatusList struct {
	Bits           int    `cbor:"1,keyasint"`
	Lst            []byte `cbor:"2,keyasint"`
	AggregationURI string `cbor:"3,keyasint,omitempty"`
}

CWTStatusList represents the status_list claim in CWT format (Section 6.1). Unlike JWT, CWT uses raw bytes for lst instead of base64url encoding.

type JWTClaims

type JWTClaims struct {
	jwt.RegisteredClaims

	// StatusList: REQUIRED. The status_list claim containing the Status List.
	StatusList StatusListClaim `json:"status_list"`

	// TTL: RECOMMENDED. Time to live in seconds - maximum time the token can be cached.
	TTL int64 `json:"ttl,omitempty"`
}

JWTClaims represents the JWT claims for a Status List Token (Section 5.1) The JWT header MUST have typ: statuslist+jwt

func ParseJWT

func ParseJWT(tokenString string, keyFunc jwt.Keyfunc) (*JWTClaims, error)

ParseJWT parses a Status List Token JWT and returns the claims. It validates the token signature using the provided key function.

type JWTConfig

type JWTConfig struct {
	TokenConfig

	// SigningKey is the private key for signing (REQUIRED)
	SigningKey crypto.PrivateKey

	// SigningMethod is the JWT signing method (e.g., jwt.SigningMethodES256) (REQUIRED)
	SigningMethod jwt.SigningMethod
}

JWTConfig holds JWT-specific configuration for generating a Status List Token. Deprecated: Use StatusList.GenerateJWT with JWTSigningConfig instead.

type JWTSigningConfig

type JWTSigningConfig struct {
	// SigningKey is the private key for signing (REQUIRED)
	SigningKey crypto.PrivateKey

	// SigningMethod is the JWT signing method (e.g., jwt.SigningMethodES256) (REQUIRED)
	SigningMethod jwt.SigningMethod
}

JWTSigningConfig holds JWT-specific signing configuration.

type StatusList

type StatusList struct {

	// Issuer is the issuer identifier (REQUIRED for token generation)
	Issuer string

	// Subject is the URI of the Status List Token (REQUIRED, must match uri in Referenced Token)
	Subject string

	// TTL is the time-to-live in seconds for caching, as specified in the draft-ietf-oauth-status-list specification (RECOMMENDED).
	TTL int64

	// ExpiresIn is the duration until the token expires (RECOMMENDED)
	ExpiresIn time.Duration

	// KeyID is the key identifier for the token header (OPTIONAL)
	KeyID string

	// AggregationURI is an optional URI for Status List Aggregation (OPTIONAL)
	AggregationURI string
	// contains filtered or unexported fields
}

StatusList represents a list of status values and provides methods for generating JWT and CWT tokens.

func New

func New(statuses []uint8) *StatusList

New creates a new StatusList with the given statuses.

Example
package main

import (
	"fmt"

	"github.com/SUNET/vc/pkg/tokenstatuslist"
)

func main() {
	statuses := []uint8{
		tokenstatuslist.StatusValid,
		tokenstatuslist.StatusInvalid,
		tokenstatuslist.StatusSuspended,
		tokenstatuslist.StatusValid,
	}
	sl := tokenstatuslist.New(statuses)

	fmt.Println("length:", sl.Len())
}
Output:
length: 4

func NewWithConfig

func NewWithConfig(statuses []uint8, issuer, subject string) *StatusList

NewWithConfig creates a new StatusList with statuses and configuration.

Example
package main

import (
	"fmt"

	"github.com/SUNET/vc/pkg/tokenstatuslist"
)

func main() {
	statuses := []uint8{
		tokenstatuslist.StatusValid,
		tokenstatuslist.StatusInvalid,
	}
	sl := tokenstatuslist.NewWithConfig(statuses, "https://issuer.example.com", "https://issuer.example.com/statuslist/1")

	fmt.Println("length:", sl.Len())
	fmt.Println("issuer:", sl.Issuer)
	fmt.Println("subject:", sl.Subject)
}
Output:
length: 2
issuer: https://issuer.example.com
subject: https://issuer.example.com/statuslist/1

func (*StatusList) Compress

func (sl *StatusList) Compress() ([]byte, error)

Compress compresses the status byte array using DEFLATE (zlib) compression as specified in Section 4.1 of the specification.

func (*StatusList) CompressAndEncode

func (sl *StatusList) CompressAndEncode() (string, error)

CompressAndEncode compresses and encodes as base64url without padding. This is the format used in JWT Status List Tokens (Section 5.1).

func (*StatusList) GenerateCWT

func (sl *StatusList) GenerateCWT(cfg CWTSigningConfig) ([]byte, error)

GenerateCWT creates a signed Status List Token CWT per Section 6.1. The token is a COSE_Sign1 structure containing: - Protected header: alg, typ=statuslist+cwt, kid - Payload: CWT claims (iss, sub, iat, exp, ttl, status_list)

func (*StatusList) GenerateJWT

func (sl *StatusList) GenerateJWT(cfg JWTSigningConfig) (string, error)

GenerateJWT creates a signed Status List Token JWT per Section 5.1. The token includes: - Header: typ=statuslist+jwt, alg, kid - Claims: sub, iss, iat, exp (optional), ttl (optional), status_list

func (*StatusList) Get

func (sl *StatusList) Get(index int) (uint8, error)

Get retrieves the status value at the given index. The index corresponds to the "idx" value in the Referenced Token's status claim.

Example
package main

import (
	"fmt"

	"github.com/SUNET/vc/pkg/tokenstatuslist"
)

func main() {
	statuses := []uint8{
		tokenstatuslist.StatusValid,
		tokenstatuslist.StatusInvalid,
		tokenstatuslist.StatusSuspended,
	}
	sl := tokenstatuslist.New(statuses)

	s0, _ := sl.Get(0)
	s1, _ := sl.Get(1)
	s2, _ := sl.Get(2)

	fmt.Println("index 0:", s0)
	fmt.Println("index 1:", s1)
	fmt.Println("index 2:", s2)
}
Output:
index 0: 0
index 1: 1
index 2: 2

func (*StatusList) Len

func (sl *StatusList) Len() int

Len returns the number of statuses in the list.

Example
package main

import (
	"fmt"

	"github.com/SUNET/vc/pkg/tokenstatuslist"
)

func main() {
	sl := tokenstatuslist.New([]uint8{0, 0, 0, 0, 0})
	fmt.Println("length:", sl.Len())
}
Output:
length: 5

func (*StatusList) Set

func (sl *StatusList) Set(index int, status uint8) error

Set updates the status value at the given index.

Example
package main

import (
	"fmt"

	"github.com/SUNET/vc/pkg/tokenstatuslist"
)

func main() {
	statuses := []uint8{
		tokenstatuslist.StatusValid,
		tokenstatuslist.StatusValid,
	}
	sl := tokenstatuslist.New(statuses)

	before, _ := sl.Get(1)
	fmt.Println("before:", before)

	_ = sl.Set(1, tokenstatuslist.StatusSuspended)
	after, _ := sl.Get(1)
	fmt.Println("after:", after)
}
Output:
before: 0
after: 2

func (*StatusList) Statuses

func (sl *StatusList) Statuses() []uint8

Statuses returns a copy of the status values.

type StatusListClaim

type StatusListClaim struct {
	// Bits: REQUIRED. Integer specifying the number of bits per Referenced Token
	// in the compressed byte array (lst). The allowed values for bits are 1, 2, 4 and 8.
	Bits int `json:"bits" cbor:"1,keyasint" validate:"required,oneof=1 2 4 8"`

	// Lst: REQUIRED. String that contains the status values for all the Referenced Tokens
	// it conveys statuses for. The value MUST be the base64url-encoded (for JWT) or
	// raw bytes (for CWT) compressed byte array as specified in Section 4.1.
	Lst string `json:"lst" cbor:"2,keyasint" validate:"required"`

	// AggregationURI: OPTIONAL. String that contains a URI to retrieve the
	// Status List Aggregation for this type of Referenced Token or Issuer.
	// See Section 9 for further details.
	AggregationURI string `json:"aggregation_uri,omitempty" cbor:"3,keyasint,omitempty"`
}

StatusListClaim represents the status_list claim in the Status List Token (Section 4.2) This structure is used in both JWT and CWT formats for serialization.

type TokenConfig

type TokenConfig struct {
	// Subject is the URI of the Status List Token (REQUIRED, must match uri in Referenced Token)
	Subject string

	// Issuer is the issuer identifier (REQUIRED)
	Issuer string

	// Statuses is the byte array of status values (REQUIRED)
	Statuses []uint8

	// TTL is the time to live in seconds (RECOMMENDED)
	TTL int64

	// ExpiresIn is the duration until the token expires (RECOMMENDED)
	ExpiresIn time.Duration

	// KeyID is the key identifier for the token header (OPTIONAL)
	KeyID string

	// AggregationURI is an optional URI for Status List Aggregation (OPTIONAL)
	AggregationURI string
}

TokenConfig holds configuration for generating a Status List Token (JWT or CWT). Deprecated: Use StatusList fields directly instead.

Jump to

Keyboard shortcuts

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