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 ¶
- Constants
- Variables
- func CompressAndEncode(statuses []uint8) (string, error)
- func CompressStatuses(statuses []uint8) ([]byte, error)
- func DecodeAndDecompress(encoded string) ([]uint8, error)
- func DecompressStatuses(compressed []byte) ([]uint8, error)
- func GenerateCWT(cfg CWTConfig) ([]byte, error)
- func GenerateJWT(cfg JWTConfig) (string, error)
- func GetStatus(statuses []uint8, index int) (uint8, error)
- func GetStatusFromCWT(claims map[int]any, index int) (uint8, error)
- func GetStatusFromJWT(claims *JWTClaims, index int) (uint8, error)
- func ParseCWT(cwtBytes []byte) (map[int]any, error)
- type CWTConfig
- type CWTSigningConfig
- type CWTStatusList
- type JWTClaims
- type JWTConfig
- type JWTSigningConfig
- type StatusList
- func (sl *StatusList) Compress() ([]byte, error)
- func (sl *StatusList) CompressAndEncode() (string, error)
- func (sl *StatusList) GenerateCWT(cfg CWTSigningConfig) ([]byte, error)
- func (sl *StatusList) GenerateJWT(cfg JWTSigningConfig) (string, error)
- func (sl *StatusList) Get(index int) (uint8, error)
- func (sl *StatusList) Len() int
- func (sl *StatusList) Set(index int, status uint8) error
- func (sl *StatusList) Statuses() []uint8
- type StatusListClaim
- type TokenConfig
Examples ¶
Constants ¶
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
const ( StatusValid uint8 = 0 // VALID (0x00) StatusInvalid uint8 = 1 // INVALID (0x01) StatusSuspended uint8 = 2 // SUSPENDED (0x02) )
Status values per the specification
const ( MediaTypeJWT = "application/statuslist+jwt" MediaTypeCWT = "application/statuslist+cwt" )
Media types for Status List Tokens
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.
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
const JWTTypHeader = "statuslist+jwt"
JWTTypHeader is the typ header value for Status List Token JWTs (Section 5.1)
Variables ¶
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).
var ErrInvalidSectionID = errors.New("invalid section ID")
ErrInvalidSectionID is returned when the section ID is invalid.
var ErrInvalidStatusIndex = errors.New("invalid status index: out of bounds")
ErrInvalidStatusIndex is returned when the status index is out of bounds.
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).
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.
var ErrSectionNotFound = errors.New("section not found")
ErrSectionNotFound is returned when the requested section does not exist.
var ErrTokenGenerationFailed = errors.New("failed to generate status list token")
ErrTokenGenerationFailed is returned when the Status List Token JWT generation fails.
Functions ¶
func CompressAndEncode ¶
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 ¶
CompressStatuses compresses a status byte array using DEFLATE (zlib) compression as specified in Section 4.1 of the specification.
func DecodeAndDecompress ¶
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 ¶
DecompressStatuses decompresses a zlib-compressed status byte array.
func GenerateCWT ¶
GenerateCWT creates a signed Status List Token CWT per Section 6.1. Deprecated: Use StatusList.GenerateCWT instead.
func GenerateJWT ¶
GenerateJWT creates a signed Status List Token JWT per Section 5.1. Deprecated: Use StatusList.GenerateJWT instead.
func GetStatus ¶
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 ¶
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 ¶
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.
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
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.