Source File
types.go
Belonging Package
github.com/golang-jwt/jwt/v4
package jwt
import (
)
// TimePrecision sets the precision of times and dates within this library.
// This has an influence on the precision of times when comparing expiry or
// other related time fields. Furthermore, it is also the precision of times
// when serializing.
//
// For backwards compatibility the default precision is set to seconds, so that
// no fractional timestamps are generated.
var TimePrecision = time.Second
// MarshalSingleStringAsArray modifies the behaviour of the ClaimStrings type, especially
// its MarshalJSON function.
//
// If it is set to true (the default), it will always serialize the type as an
// array of strings, even if it just contains one element, defaulting to the behaviour
// of the underlying []string. If it is set to false, it will serialize to a single
// string, if it contains one element. Otherwise, it will serialize to an array of strings.
var MarshalSingleStringAsArray = true
// NumericDate represents a JSON numeric date value, as referenced at
// https://datatracker.ietf.org/doc/html/rfc7519#section-2.
type NumericDate struct {
time.Time
}
// NewNumericDate constructs a new *NumericDate from a standard library time.Time struct.
// It will truncate the timestamp according to the precision specified in TimePrecision.
func ( time.Time) *NumericDate {
return &NumericDate{.Truncate(TimePrecision)}
}
// newNumericDateFromSeconds creates a new *NumericDate out of a float64 representing a
// UNIX epoch with the float fraction representing non-integer seconds.
func newNumericDateFromSeconds( float64) *NumericDate {
, := math.Modf()
return NewNumericDate(time.Unix(int64(), int64(*1e9)))
}
// MarshalJSON is an implementation of the json.RawMessage interface and serializes the UNIX epoch
// represented in NumericDate to a byte array, using the precision specified in TimePrecision.
func ( NumericDate) () ( []byte, error) {
var int
if TimePrecision < time.Second {
= int(math.Log10(float64(time.Second) / float64(TimePrecision)))
}
:= .Truncate(TimePrecision)
// For very large timestamps, UnixNano would overflow an int64, but this
// function requires nanosecond level precision, so we have to use the
// following technique to get round the issue:
// 1. Take the normal unix timestamp to form the whole number part of the
// output,
// 2. Take the result of the Nanosecond function, which retuns the offset
// within the second of the particular unix time instance, to form the
// decimal part of the output
// 3. Concatenate them to produce the final result
:= strconv.FormatInt(.Unix(), 10)
:= strconv.FormatFloat(float64(.Nanosecond())/float64(time.Second), 'f', , 64)
:= append([]byte(), []byte()[1:]...)
return , nil
}
// UnmarshalJSON is an implementation of the json.RawMessage interface and deserializses a
// NumericDate from a JSON representation, i.e. a json.Number. This number represents an UNIX epoch
// with either integer or non-integer seconds.
func ( *NumericDate) ( []byte) ( error) {
var (
json.Number
float64
)
if = json.Unmarshal(, &); != nil {
return fmt.Errorf("could not parse NumericData: %w", )
}
if , = .Float64(); != nil {
return fmt.Errorf("could not convert json number value to float: %w", )
}
:= newNumericDateFromSeconds()
* = *
return nil
}
// ClaimStrings is basically just a slice of strings, but it can be either serialized from a string array or just a string.
// This type is necessary, since the "aud" claim can either be a single string or an array.
type ClaimStrings []string
func ( *ClaimStrings) ( []byte) ( error) {
var interface{}
if = json.Unmarshal(, &); != nil {
return
}
var []string
switch v := .(type) {
case string:
= append(, )
case []string:
= ClaimStrings()
case []interface{}:
for , := range {
, := .(string)
if ! {
return &json.UnsupportedTypeError{Type: reflect.TypeOf()}
}
= append(, )
}
case nil:
return nil
default:
return &json.UnsupportedTypeError{Type: reflect.TypeOf()}
}
* =
return
}
func ( ClaimStrings) () ( []byte, error) {
// This handles a special case in the JWT RFC. If the string array, e.g. used by the "aud" field,
// only contains one element, it MAY be serialized as a single string. This may or may not be
// desired based on the ecosystem of other JWT library used, so we make it configurable by the
// variable MarshalSingleStringAsArray.
if len() == 1 && !MarshalSingleStringAsArray {
return json.Marshal([0])
}
return json.Marshal([]string())
}
![]() |
The pages are generated with Golds v0.6.7. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |