Initial QSfera import

This commit is contained in:
Курнат Андрей
2026-06-07 10:20:04 +03:00
commit 2315f25754
16485 changed files with 4826827 additions and 0 deletions
@@ -0,0 +1,16 @@
load("@rules_go//go:def.bzl", "go_library")
go_library(
name = "errors",
srcs = [
"errors.go",
],
importpath = "github.com/lestrrat-go/jwx/v3/jwt/internal/errors",
visibility = ["//jwt:__subpackages__"],
)
alias(
name = "go_default_library",
actual = ":errors",
visibility = ["//jwt:__subpackages__"],
)
@@ -0,0 +1,185 @@
// Package errors exist to store errors for jwt and openid packages.
//
// It's internal because we don't want to expose _anything_ about these errors
// so users absolutely cannot do anything other than use them as opaque errors.
//
//nolint:revive
package errors
import (
"errors"
"fmt"
)
var (
ErrClaimNotFound = ClaimNotFoundError{}
ErrClaimAssignmentFailed = ClaimAssignmentFailedError{Err: errors.New(`claim assignment failed`)}
ErrUnknownPayloadType = errors.New(`unknown payload type (payload is not JWT?)`)
ErrParse = ParseError{error: errors.New(`jwt.Parse: unknown error`)}
ErrValidateDefault = ValidationError{errors.New(`unknown error`)}
ErrInvalidIssuerDefault = InvalidIssuerError{errors.New(`"iss" not satisfied`)}
ErrTokenExpiredDefault = TokenExpiredError{errors.New(`"exp" not satisfied: token is expired`)}
ErrInvalidIssuedAtDefault = InvalidIssuedAtError{errors.New(`"iat" not satisfied`)}
ErrTokenNotYetValidDefault = TokenNotYetValidError{errors.New(`"nbf" not satisfied: token is not yet valid`)}
ErrInvalidAudienceDefault = InvalidAudienceError{errors.New(`"aud" not satisfied`)}
ErrMissingRequiredClaimDefault = &MissingRequiredClaimError{error: errors.New(`required claim is missing`)}
)
type ClaimNotFoundError struct {
Name string
}
func (e ClaimNotFoundError) Error() string {
// This error message uses "field" instead of "claim" for backwards compatibility,
// but it shuold really be "claim" since it refers to a JWT claim.
return fmt.Sprintf(`field "%s" not found`, e.Name)
}
func (e ClaimNotFoundError) Is(target error) bool {
_, ok := target.(ClaimNotFoundError)
return ok
}
type ClaimAssignmentFailedError struct {
Err error
}
func (e ClaimAssignmentFailedError) Error() string {
// This error message probably should be tweaked, but it is this way
// for backwards compatibility.
return fmt.Sprintf(`failed to assign value to dst: %s`, e.Err.Error())
}
func (e ClaimAssignmentFailedError) Unwrap() error {
return e.Err
}
func (e ClaimAssignmentFailedError) Is(target error) bool {
_, ok := target.(ClaimAssignmentFailedError)
return ok
}
type ParseError struct {
error
}
func (e ParseError) Unwrap() error {
return e.error
}
func (ParseError) Is(err error) bool {
_, ok := err.(ParseError)
return ok
}
func ParseErrorf(prefix, f string, args ...any) error {
return ParseError{fmt.Errorf(prefix+": "+f, args...)}
}
type ValidationError struct {
error
}
func (ValidationError) Is(err error) bool {
_, ok := err.(ValidationError)
return ok
}
func (err ValidationError) Unwrap() error {
return err.error
}
func ValidateErrorf(f string, args ...any) error {
return ValidationError{fmt.Errorf(`jwt.Validate: `+f, args...)}
}
type InvalidIssuerError struct {
error
}
func (err InvalidIssuerError) Is(target error) bool {
_, ok := target.(InvalidIssuerError)
return ok
}
func (err InvalidIssuerError) Unwrap() error {
return err.error
}
func IssuerErrorf(f string, args ...any) error {
return InvalidIssuerError{fmt.Errorf(`"iss" not satisfied: `+f, args...)}
}
type TokenExpiredError struct {
error
}
func (err TokenExpiredError) Is(target error) bool {
_, ok := target.(TokenExpiredError)
return ok
}
func (err TokenExpiredError) Unwrap() error {
return err.error
}
type InvalidIssuedAtError struct {
error
}
func (err InvalidIssuedAtError) Is(target error) bool {
_, ok := target.(InvalidIssuedAtError)
return ok
}
func (err InvalidIssuedAtError) Unwrap() error {
return err.error
}
type TokenNotYetValidError struct {
error
}
func (err TokenNotYetValidError) Is(target error) bool {
_, ok := target.(TokenNotYetValidError)
return ok
}
func (err TokenNotYetValidError) Unwrap() error {
return err.error
}
type InvalidAudienceError struct {
error
}
func (err InvalidAudienceError) Is(target error) bool {
_, ok := target.(InvalidAudienceError)
return ok
}
func (err InvalidAudienceError) Unwrap() error {
return err.error
}
func AudienceErrorf(f string, args ...any) error {
return InvalidAudienceError{fmt.Errorf(`"aud" not satisfied: `+f, args...)}
}
type MissingRequiredClaimError struct {
error
claim string
}
func (err *MissingRequiredClaimError) Is(target error) bool {
err1, ok := target.(*MissingRequiredClaimError)
if !ok {
return false
}
return err1 == ErrMissingRequiredClaimDefault || err1.claim == err.claim
}
func MissingRequiredClaimErrorf(name string) error {
return &MissingRequiredClaimError{claim: name, error: fmt.Errorf(`required claim "%s" is missing`, name)}
}
@@ -0,0 +1,35 @@
load("@rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "types",
srcs = [
"date.go",
"string.go",
],
importpath = "github.com/lestrrat-go/jwx/v3/jwt/internal/types",
visibility = ["//jwt:__subpackages__"],
deps = [
"//internal/json",
"//internal/tokens",
],
)
go_test(
name = "types_test",
srcs = [
"date_test.go",
"string_test.go",
],
deps = [
":types",
"//internal/json",
"//jwt",
"@com_github_stretchr_testify//require",
],
)
alias(
name = "go_default_library",
actual = ":types",
visibility = ["//jwt:__subpackages__"],
)
+192
View File
@@ -0,0 +1,192 @@
package types
import (
"fmt"
"strconv"
"strings"
"time"
"github.com/lestrrat-go/jwx/v3/internal/json"
"github.com/lestrrat-go/jwx/v3/internal/tokens"
)
const (
DefaultPrecision uint32 = 0 // second level
MaxPrecision uint32 = 9 // nanosecond level
)
var Pedantic uint32
var ParsePrecision = DefaultPrecision
var FormatPrecision = DefaultPrecision
// NumericDate represents the date format used in the 'nbf' claim
type NumericDate struct {
time.Time
}
func (n *NumericDate) Get() time.Time {
if n == nil {
return (time.Time{}).UTC()
}
return n.Time
}
func intToTime(v any, t *time.Time) bool {
var n int64
switch x := v.(type) {
case int64:
n = x
case int32:
n = int64(x)
case int16:
n = int64(x)
case int8:
n = int64(x)
case int:
n = int64(x)
default:
return false
}
*t = time.Unix(n, 0)
return true
}
func parseNumericString(x string) (time.Time, error) {
var t time.Time // empty time for empty return value
// Only check for the escape hatch if it's the pedantic
// flag is off
if Pedantic != 1 {
// This is an escape hatch for non-conformant providers
// that gives us RFC3339 instead of epoch time
for _, r := range x {
// 0x30 = '0', 0x39 = '9', 0x2E = tokens.Period
if (r >= 0x30 && r <= 0x39) || r == 0x2E {
continue
}
// if it got here, then it probably isn't epoch time
tv, err := time.Parse(time.RFC3339, x)
if err != nil {
return t, fmt.Errorf(`value is not number of seconds since the epoch, and attempt to parse it as RFC3339 timestamp failed: %w`, err)
}
return tv, nil
}
}
var fractional string
whole := x
if i := strings.IndexRune(x, tokens.Period); i > 0 {
if ParsePrecision > 0 && len(x) > i+1 {
fractional = x[i+1:] // everything after the tokens.Period
if int(ParsePrecision) < len(fractional) {
// Remove insignificant digits
fractional = fractional[:int(ParsePrecision)]
}
// Replace missing fractional diits with zeros
for len(fractional) < int(MaxPrecision) {
fractional = fractional + "0"
}
}
whole = x[:i]
}
n, err := strconv.ParseInt(whole, 10, 64)
if err != nil {
return t, fmt.Errorf(`failed to parse whole value %q: %w`, whole, err)
}
var nsecs int64
if fractional != "" {
v, err := strconv.ParseInt(fractional, 10, 64)
if err != nil {
return t, fmt.Errorf(`failed to parse fractional value %q: %w`, fractional, err)
}
nsecs = v
}
return time.Unix(n, nsecs).UTC(), nil
}
func (n *NumericDate) Accept(v any) error {
var t time.Time
switch x := v.(type) {
case float32:
tv, err := parseNumericString(fmt.Sprintf(`%.9f`, x))
if err != nil {
return fmt.Errorf(`failed to accept float32 %.9f: %w`, x, err)
}
t = tv
case float64:
tv, err := parseNumericString(fmt.Sprintf(`%.9f`, x))
if err != nil {
return fmt.Errorf(`failed to accept float32 %.9f: %w`, x, err)
}
t = tv
case json.Number:
tv, err := parseNumericString(x.String())
if err != nil {
return fmt.Errorf(`failed to accept json.Number %q: %w`, x.String(), err)
}
t = tv
case string:
tv, err := parseNumericString(x)
if err != nil {
return fmt.Errorf(`failed to accept string %q: %w`, x, err)
}
t = tv
case time.Time:
t = x
default:
if !intToTime(v, &t) {
return fmt.Errorf(`invalid type %T`, v)
}
}
n.Time = t.UTC()
return nil
}
func (n NumericDate) String() string {
if FormatPrecision == 0 {
return strconv.FormatInt(n.Unix(), 10)
}
// This is cheating, but it's better (easier) than doing floating point math
// We basically munge with strings after formatting an integer value
// for nanoseconds since epoch
s := strconv.FormatInt(n.UnixNano(), 10)
for len(s) < int(MaxPrecision) {
s = "0" + s
}
slwhole := len(s) - int(MaxPrecision)
s = s[:slwhole] + "." + s[slwhole:slwhole+int(FormatPrecision)]
if s[0] == tokens.Period {
s = "0" + s
}
return s
}
// MarshalJSON translates from internal representation to JSON NumericDate
// See https://tools.ietf.org/html/rfc7519#page-6
func (n *NumericDate) MarshalJSON() ([]byte, error) {
if n.IsZero() {
return json.Marshal(nil)
}
return json.Marshal(n.String())
}
func (n *NumericDate) UnmarshalJSON(data []byte) error {
var v any
if err := json.Unmarshal(data, &v); err != nil {
return fmt.Errorf(`failed to unmarshal date: %w`, err)
}
var n2 NumericDate
if err := n2.Accept(v); err != nil {
return fmt.Errorf(`invalid value for NumericDate: %w`, err)
}
*n = n2
return nil
}
@@ -0,0 +1,43 @@
package types
import (
"fmt"
"github.com/lestrrat-go/jwx/v3/internal/json"
)
type StringList []string
func (l StringList) Get() []string {
return []string(l)
}
func (l *StringList) Accept(v any) error {
switch x := v.(type) {
case string:
*l = StringList([]string{x})
case []string:
*l = StringList(x)
case []any:
list := make(StringList, len(x))
for i, e := range x {
if s, ok := e.(string); ok {
list[i] = s
continue
}
return fmt.Errorf(`invalid list element type %T`, e)
}
*l = list
default:
return fmt.Errorf(`invalid type: %T`, v)
}
return nil
}
func (l *StringList) UnmarshalJSON(data []byte) error {
var v any
if err := json.Unmarshal(data, &v); err != nil {
return fmt.Errorf(`failed to unmarshal data: %w`, err)
}
return l.Accept(v)
}