full diff: https://github.com/lestrrat-go/jwx/compare/v3.0.11...v3.0.13 Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
223 lines
6.7 KiB
Go
223 lines
6.7 KiB
Go
package jwsbb
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/lestrrat-go/jwx/v3/internal/base64"
|
|
"github.com/valyala/fastjson"
|
|
)
|
|
|
|
type headerNotFoundError struct {
|
|
key string
|
|
}
|
|
|
|
func (e headerNotFoundError) Error() string {
|
|
return fmt.Sprintf(`jwsbb: header "%s" not found`, e.key)
|
|
}
|
|
|
|
func (e headerNotFoundError) Is(target error) bool {
|
|
switch target.(type) {
|
|
case headerNotFoundError, *headerNotFoundError:
|
|
// If the target is a headerNotFoundError or a pointer to it, we
|
|
// consider it a match
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
// ErrHeaderNotFound returns an error that can be passed to `errors.Is` to check if the error is
|
|
// the result of the field not being found
|
|
func ErrHeaderNotFound() error {
|
|
return headerNotFoundError{}
|
|
}
|
|
|
|
// ErrFieldNotFound is an alias for ErrHeaderNotFound, and is deprecated. It was a misnomer.
|
|
// It will be removed in a future release.
|
|
func ErrFieldNotFound() error {
|
|
return ErrHeaderNotFound()
|
|
}
|
|
|
|
// Header is an object that allows you to access the JWS header in a quick and
|
|
// dirty way. It does not verify anything, it does not know anything about what
|
|
// each header field means, and it does not care about the JWS specification.
|
|
// But when you need to access the JWS header for that one field that you
|
|
// need, this is the object you want to use.
|
|
//
|
|
// As of this writing, HeaderParser cannot be used from concurrent goroutines.
|
|
// You will need to create a new instance for each goroutine that needs to parse a JWS header.
|
|
// Also, in general values obtained from this object should only be used
|
|
// while the Header object is still in scope.
|
|
//
|
|
// This type is experimental and may change or be removed in the future.
|
|
type Header interface {
|
|
// I'm hiding this behind an interface so that users won't accidentally
|
|
// rely on the underlying json handler implementation, nor the concrete
|
|
// type name that jwsbb provides, as we may choose a different one in the future.
|
|
jwsbbHeader()
|
|
}
|
|
|
|
type header struct {
|
|
v *fastjson.Value
|
|
err error
|
|
}
|
|
|
|
func (h *header) jwsbbHeader() {}
|
|
|
|
// HeaderParseCompact parses a JWS header from a compact serialization format.
|
|
// You will need to call HeaderGet* functions to extract the values from the header.
|
|
//
|
|
// This function is experimental and may change or be removed in the future.
|
|
func HeaderParseCompact(buf []byte) Header {
|
|
decoded, err := base64.Decode(buf)
|
|
if err != nil {
|
|
return &header{err: err}
|
|
}
|
|
return HeaderParse(decoded)
|
|
}
|
|
|
|
// HeaderParse parses a JWS header from a byte slice containing the decoded JSON.
|
|
// You will need to call HeaderGet* functions to extract the values from the header.
|
|
//
|
|
// Unlike HeaderParseCompact, this function does not perform any base64 decoding.
|
|
// This function is experimental and may change or be removed in the future.
|
|
func HeaderParse(decoded []byte) Header {
|
|
var p fastjson.Parser
|
|
v, err := p.ParseBytes(decoded)
|
|
if err != nil {
|
|
return &header{err: err}
|
|
}
|
|
return &header{
|
|
v: v,
|
|
}
|
|
}
|
|
|
|
func headerGet(h Header, key string) (*fastjson.Value, error) {
|
|
//nolint:forcetypeassert
|
|
hh := h.(*header) // we _know_ this can't be another type
|
|
if hh.err != nil {
|
|
return nil, hh.err
|
|
}
|
|
|
|
v := hh.v.Get(key)
|
|
if v == nil {
|
|
return nil, headerNotFoundError{key: key}
|
|
}
|
|
return v, nil
|
|
}
|
|
|
|
// HeaderGetString returns the string value for the given key from the JWS header.
|
|
// An error is returned if the JSON was not valid, if the key does not exist,
|
|
// or if the value is not a string.
|
|
//
|
|
// This function is experimental and may change or be removed in the future.
|
|
func HeaderGetString(h Header, key string) (string, error) {
|
|
v, err := headerGet(h, key)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
sb, err := v.StringBytes()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return string(sb), nil
|
|
}
|
|
|
|
// HeaderGetBool returns the boolean value for the given key from the JWS header.
|
|
// An error is returned if the JSON was not valid, if the key does not exist,
|
|
// or if the value is not a boolean.
|
|
//
|
|
// This function is experimental and may change or be removed in the future.
|
|
func HeaderGetBool(h Header, key string) (bool, error) {
|
|
v, err := headerGet(h, key)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return v.Bool()
|
|
}
|
|
|
|
// HeaderGetFloat64 returns the float64 value for the given key from the JWS header.
|
|
// An error is returned if the JSON was not valid, if the key does not exist,
|
|
// or if the value is not a float64.
|
|
//
|
|
// This function is experimental and may change or be removed in the future.
|
|
func HeaderGetFloat64(h Header, key string) (float64, error) {
|
|
v, err := headerGet(h, key)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return v.Float64()
|
|
}
|
|
|
|
// HeaderGetInt returns the int value for the given key from the JWS header.
|
|
// An error is returned if the JSON was not valid, if the key does not exist,
|
|
// or if the value is not an int.
|
|
//
|
|
// This function is experimental and may change or be removed in the future.
|
|
func HeaderGetInt(h Header, key string) (int, error) {
|
|
v, err := headerGet(h, key)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return v.Int()
|
|
}
|
|
|
|
// HeaderGetInt64 returns the int64 value for the given key from the JWS header.
|
|
// An error is returned if the JSON was not valid, if the key does not exist,
|
|
// or if the value is not an int64.
|
|
//
|
|
// This function is experimental and may change or be removed in the future.
|
|
func HeaderGetInt64(h Header, key string) (int64, error) {
|
|
v, err := headerGet(h, key)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return v.Int64()
|
|
}
|
|
|
|
// HeaderGetStringBytes returns the byte slice value for the given key from the JWS header.
|
|
// An error is returned if the JSON was not valid, if the key does not exist,
|
|
// or if the value is not a byte slice.
|
|
//
|
|
// Because of limitations of the underlying library, you cannot use the return value
|
|
// of this function after the parser is garbage collected.
|
|
//
|
|
// This function is experimental and may change or be removed in the future.
|
|
func HeaderGetStringBytes(h Header, key string) ([]byte, error) {
|
|
v, err := headerGet(h, key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return v.StringBytes()
|
|
}
|
|
|
|
// HeaderGetUint returns the uint value for the given key from the JWS header.
|
|
// An error is returned if the JSON was not valid, if the key does not exist,
|
|
// or if the value is not a uint.
|
|
//
|
|
// This function is experimental and may change or be removed in the future.
|
|
func HeaderGetUint(h Header, key string) (uint, error) {
|
|
v, err := headerGet(h, key)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return v.Uint()
|
|
}
|
|
|
|
// HeaderGetUint64 returns the uint64 value for the given key from the JWS header.
|
|
// An error is returned if the JSON was not valid, if the key does not exist,
|
|
// or if the value is not a uint64.
|
|
//
|
|
// This function is experimental and may change or be removed in the future.
|
|
func HeaderGetUint64(h Header, key string) (uint64, error) {
|
|
v, err := headerGet(h, key)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return v.Uint64()
|
|
}
|