package jws import ( "fmt" "github.com/open-policy-agent/opa/internal/jwx/jwa" ) // Constants for JWS Common parameters const ( AlgorithmKey = "alg" ContentTypeKey = "cty" CriticalKey = "crit" JWKKey = "jwk" JWKSetURLKey = "jku" KeyIDKey = "kid" PrivateParamsKey = "privateParams" TypeKey = "typ" ) // Headers provides a common interface for common header parameters type Headers interface { Get(string) (interface{}, bool) Set(string, interface{}) error GetAlgorithm() jwa.SignatureAlgorithm } // StandardHeaders contains JWS common parameters. type StandardHeaders struct { Algorithm jwa.SignatureAlgorithm `json:"alg,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.1 ContentType string `json:"cty,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.10 Critical []string `json:"crit,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.11 JWK string `json:"jwk,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.3 JWKSetURL string `json:"jku,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.2 KeyID string `json:"kid,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.4 PrivateParams map[string]interface{} `json:"privateParams,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.9 Type string `json:"typ,omitempty"` // https://tools.ietf.org/html/rfc7515#section-4.1.9 } // GetAlgorithm returns algorithm func (h *StandardHeaders) GetAlgorithm() jwa.SignatureAlgorithm { return h.Algorithm } // Get is a general getter function for StandardHeaders structure func (h *StandardHeaders) Get(name string) (interface{}, bool) { switch name { case AlgorithmKey: v := h.Algorithm if v == "" { return nil, false } return v, true case ContentTypeKey: v := h.ContentType if v == "" { return nil, false } return v, true case CriticalKey: v := h.Critical if len(v) == 0 { return nil, false } return v, true case JWKKey: v := h.JWK if v == "" { return nil, false } return v, true case JWKSetURLKey: v := h.JWKSetURL if v == "" { return nil, false } return v, true case KeyIDKey: v := h.KeyID if v == "" { return nil, false } return v, true case PrivateParamsKey: v := h.PrivateParams if len(v) == 0 { return nil, false } return v, true case TypeKey: v := h.Type if v == "" { return nil, false } return v, true default: return nil, false } } // Set is a general setter function for StandardHeaders structure func (h *StandardHeaders) Set(name string, value interface{}) error { switch name { case AlgorithmKey: if err := h.Algorithm.Accept(value); err != nil { return fmt.Errorf("invalid value for %s key: %w", AlgorithmKey, err) } return nil case ContentTypeKey: if v, ok := value.(string); ok { h.ContentType = v return nil } return fmt.Errorf("invalid value for %s key: %T", ContentTypeKey, value) case CriticalKey: if v, ok := value.([]string); ok { h.Critical = v return nil } return fmt.Errorf("invalid value for %s key: %T", CriticalKey, value) case JWKKey: if v, ok := value.(string); ok { h.JWK = v return nil } return fmt.Errorf("invalid value for %s key: %T", JWKKey, value) case JWKSetURLKey: if v, ok := value.(string); ok { h.JWKSetURL = v return nil } return fmt.Errorf("invalid value for %s key: %T", JWKSetURLKey, value) case KeyIDKey: if v, ok := value.(string); ok { h.KeyID = v return nil } return fmt.Errorf("invalid value for %s key: %T", KeyIDKey, value) case PrivateParamsKey: if v, ok := value.(map[string]interface{}); ok { h.PrivateParams = v return nil } return fmt.Errorf("invalid value for %s key: %T", PrivateParamsKey, value) case TypeKey: if v, ok := value.(string); ok { h.Type = v return nil } return fmt.Errorf("invalid value for %s key: %T", TypeKey, value) default: return fmt.Errorf("invalid key: %s", name) } }