mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 12:54:38 +03:00
This reverts commit bba7c23957.
This commit is contained in:
4
vendor/github.com/golang-jwt/jwt/v4/MIGRATION_GUIDE.md
generated
vendored
4
vendor/github.com/golang-jwt/jwt/v4/MIGRATION_GUIDE.md
generated
vendored
@@ -1,6 +1,6 @@
|
||||
## Migration Guide (v4.0.0)
|
||||
|
||||
Starting from [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0), the import path will be:
|
||||
Starting from [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0]), the import path will be:
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
|
||||
@@ -19,4 +19,4 @@ go mod tidy
|
||||
|
||||
## Older releases (before v3.2.0)
|
||||
|
||||
The original migration guide for older releases can be found at https://github.com/dgrijalva/jwt-go/blob/master/MIGRATION_GUIDE.md.
|
||||
The original migration guide for older releases can be found at https://github.com/dgrijalva/jwt-go/blob/master/MIGRATION_GUIDE.md.
|
||||
39
vendor/github.com/golang-jwt/jwt/v4/README.md
generated
vendored
39
vendor/github.com/golang-jwt/jwt/v4/README.md
generated
vendored
@@ -1,12 +1,12 @@
|
||||
# jwt-go
|
||||
|
||||
[](https://github.com/golang-jwt/jwt/actions/workflows/build.yml)
|
||||
[](https://pkg.go.dev/github.com/golang-jwt/jwt/v4)
|
||||
[](https://pkg.go.dev/github.com/golang-jwt/jwt)
|
||||
|
||||
A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](https://datatracker.ietf.org/doc/html/rfc7519).
|
||||
|
||||
Starting with [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0) this project adds Go module support, but maintains backwards compatibility with older `v3.x.y` tags and upstream `github.com/dgrijalva/jwt-go`.
|
||||
See the [`MIGRATION_GUIDE.md`](./MIGRATION_GUIDE.md) for more information.
|
||||
Starting with [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0) this project adds Go module support, but maintains backwards compataibility with older `v3.x.y` tags and upstream `github.com/dgrijalva/jwt-go`.
|
||||
See the `MIGRATION_GUIDE.md` for more information.
|
||||
|
||||
> After the original author of the library suggested migrating the maintenance of `jwt-go`, a dedicated team of open source maintainers decided to clone the existing library into this repository. See [dgrijalva/jwt-go#462](https://github.com/dgrijalva/jwt-go/issues/462) for a detailed discussion on this topic.
|
||||
|
||||
@@ -36,23 +36,9 @@ The part in the middle is the interesting bit. It's called the Claims and conta
|
||||
|
||||
This library supports the parsing and verification as well as the generation and signing of JWTs. Current supported signing algorithms are HMAC SHA, RSA, RSA-PSS, and ECDSA, though hooks are present for adding your own.
|
||||
|
||||
## Installation Guidelines
|
||||
|
||||
1. To install the jwt package, you first need to have [Go](https://go.dev/doc/install) installed, then you can use the command below to add `jwt-go` as a dependency in your Go program.
|
||||
|
||||
```sh
|
||||
go get -u github.com/golang-jwt/jwt/v4
|
||||
```
|
||||
|
||||
2. Import it in your code:
|
||||
|
||||
```go
|
||||
import "github.com/golang-jwt/jwt/v4"
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
See [the project documentation](https://pkg.go.dev/github.com/golang-jwt/jwt/v4) for examples of usage:
|
||||
See [the project documentation](https://pkg.go.dev/github.com/golang-jwt/jwt) for examples of usage:
|
||||
|
||||
* [Simple example of parsing and validating a token](https://pkg.go.dev/github.com/golang-jwt/jwt#example-Parse-Hmac)
|
||||
* [Simple example of building and signing a token](https://pkg.go.dev/github.com/golang-jwt/jwt#example-New-Hmac)
|
||||
@@ -60,21 +46,13 @@ See [the project documentation](https://pkg.go.dev/github.com/golang-jwt/jwt/v4)
|
||||
|
||||
## Extensions
|
||||
|
||||
This library publishes all the necessary components for adding your own signing methods or key functions. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod` or provide a `jwt.Keyfunc`.
|
||||
This library publishes all the necessary components for adding your own signing methods. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod`.
|
||||
|
||||
A common use case would be integrating with different 3rd party signature providers, like key management services from various cloud providers or Hardware Security Modules (HSMs) or to implement additional standards.
|
||||
|
||||
| Extension | Purpose | Repo |
|
||||
| --------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
|
||||
| GCP | Integrates with multiple Google Cloud Platform signing tools (AppEngine, IAM API, Cloud KMS) | https://github.com/someone1/gcp-jwt-go |
|
||||
| AWS | Integrates with AWS Key Management Service, KMS | https://github.com/matelang/jwt-go-aws-kms |
|
||||
| JWKS | Provides support for JWKS ([RFC 7517](https://datatracker.ietf.org/doc/html/rfc7517)) as a `jwt.Keyfunc` | https://github.com/MicahParks/keyfunc |
|
||||
|
||||
*Disclaimer*: Unless otherwise specified, these integrations are maintained by third parties and should not be considered as a primary offer by any of the mentioned cloud providers
|
||||
Here's an example of an extension that integrates with multiple Google Cloud Platform signing tools (AppEngine, IAM API, Cloud KMS): https://github.com/someone1/gcp-jwt-go
|
||||
|
||||
## Compliance
|
||||
|
||||
This library was last reviewed to comply with [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519) dated May 2015 with a few notable differences:
|
||||
This library was last reviewed to comply with [RTF 7519](https://datatracker.ietf.org/doc/html/rfc7519) dated May 2015 with a few notable differences:
|
||||
|
||||
* In order to protect against accidental use of [Unsecured JWTs](https://datatracker.ietf.org/doc/html/rfc7519#section-6), tokens using `alg=none` will only be accepted if the constant `jwt.UnsafeAllowNoneSignatureType` is provided as the key.
|
||||
|
||||
@@ -113,7 +91,6 @@ Each signing method expects a different object type for its signing keys. See th
|
||||
* The [HMAC signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodHMAC) (`HS256`,`HS384`,`HS512`) expect `[]byte` values for signing and validation
|
||||
* The [RSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodRSA) (`RS256`,`RS384`,`RS512`) expect `*rsa.PrivateKey` for signing and `*rsa.PublicKey` for validation
|
||||
* The [ECDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodECDSA) (`ES256`,`ES384`,`ES512`) expect `*ecdsa.PrivateKey` for signing and `*ecdsa.PublicKey` for validation
|
||||
* The [EdDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodEd25519) (`Ed25519`) expect `ed25519.PrivateKey` for signing and `ed25519.PublicKey` for validation
|
||||
|
||||
### JWT and OAuth
|
||||
|
||||
@@ -134,5 +111,3 @@ This library uses descriptive error messages whenever possible. If you are not g
|
||||
Documentation can be found [on pkg.go.dev](https://pkg.go.dev/github.com/golang-jwt/jwt).
|
||||
|
||||
The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in the documentation.
|
||||
|
||||
[golang-jwt](https://github.com/orgs/golang-jwt) incorporates a modified version of the JWT logo, which is distributed under the terms of the [MIT License](https://github.com/jsonwebtoken/jsonwebtoken.github.io/blob/master/LICENSE.txt).
|
||||
|
||||
19
vendor/github.com/golang-jwt/jwt/v4/SECURITY.md
generated
vendored
19
vendor/github.com/golang-jwt/jwt/v4/SECURITY.md
generated
vendored
@@ -1,19 +0,0 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
As of February 2022 (and until this document is updated), the latest version `v4` is supported.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you think you found a vulnerability, and even if you are not sure, please report it to jwt-go-security@googlegroups.com or one of the other [golang-jwt maintainers](https://github.com/orgs/golang-jwt/people). Please try be explicit, describe steps to reproduce the security issue with code example(s).
|
||||
|
||||
You will receive a response within a timely manner. If the issue is confirmed, we will do our best to release a patch as soon as possible given the complexity of the problem.
|
||||
|
||||
## Public Discussions
|
||||
|
||||
Please avoid publicly discussing a potential security vulnerability.
|
||||
|
||||
Let's take this offline and find a solution first, this limits the potential impact as much as possible.
|
||||
|
||||
We appreciate your help!
|
||||
190
vendor/github.com/golang-jwt/jwt/v4/claims.go
generated
vendored
190
vendor/github.com/golang-jwt/jwt/v4/claims.go
generated
vendored
@@ -12,122 +12,9 @@ type Claims interface {
|
||||
Valid() error
|
||||
}
|
||||
|
||||
// RegisteredClaims are a structured version of the JWT Claims Set,
|
||||
// restricted to Registered Claim Names, as referenced at
|
||||
// https://datatracker.ietf.org/doc/html/rfc7519#section-4.1
|
||||
//
|
||||
// This type can be used on its own, but then additional private and
|
||||
// public claims embedded in the JWT will not be parsed. The typical usecase
|
||||
// therefore is to embedded this in a user-defined claim type.
|
||||
//
|
||||
// See examples for how to use this with your own claim types.
|
||||
type RegisteredClaims struct {
|
||||
// the `iss` (Issuer) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1
|
||||
Issuer string `json:"iss,omitempty"`
|
||||
|
||||
// the `sub` (Subject) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.2
|
||||
Subject string `json:"sub,omitempty"`
|
||||
|
||||
// the `aud` (Audience) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3
|
||||
Audience ClaimStrings `json:"aud,omitempty"`
|
||||
|
||||
// the `exp` (Expiration Time) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4
|
||||
ExpiresAt *NumericDate `json:"exp,omitempty"`
|
||||
|
||||
// the `nbf` (Not Before) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5
|
||||
NotBefore *NumericDate `json:"nbf,omitempty"`
|
||||
|
||||
// the `iat` (Issued At) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6
|
||||
IssuedAt *NumericDate `json:"iat,omitempty"`
|
||||
|
||||
// the `jti` (JWT ID) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.7
|
||||
ID string `json:"jti,omitempty"`
|
||||
}
|
||||
|
||||
// Valid validates time based claims "exp, iat, nbf".
|
||||
// There is no accounting for clock skew.
|
||||
// As well, if any of the above claims are not in the token, it will still
|
||||
// be considered a valid claim.
|
||||
func (c RegisteredClaims) Valid() error {
|
||||
vErr := new(ValidationError)
|
||||
now := TimeFunc()
|
||||
|
||||
// The claims below are optional, by default, so if they are set to the
|
||||
// default value in Go, let's not fail the verification for them.
|
||||
if !c.VerifyExpiresAt(now, false) {
|
||||
delta := now.Sub(c.ExpiresAt.Time)
|
||||
vErr.Inner = fmt.Errorf("%s by %s", ErrTokenExpired, delta)
|
||||
vErr.Errors |= ValidationErrorExpired
|
||||
}
|
||||
|
||||
if !c.VerifyIssuedAt(now, false) {
|
||||
vErr.Inner = ErrTokenUsedBeforeIssued
|
||||
vErr.Errors |= ValidationErrorIssuedAt
|
||||
}
|
||||
|
||||
if !c.VerifyNotBefore(now, false) {
|
||||
vErr.Inner = ErrTokenNotValidYet
|
||||
vErr.Errors |= ValidationErrorNotValidYet
|
||||
}
|
||||
|
||||
if vErr.valid() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return vErr
|
||||
}
|
||||
|
||||
// VerifyAudience compares the aud claim against cmp.
|
||||
// If required is false, this method will return true if the value matches or is unset
|
||||
func (c *RegisteredClaims) VerifyAudience(cmp string, req bool) bool {
|
||||
return verifyAud(c.Audience, cmp, req)
|
||||
}
|
||||
|
||||
// VerifyExpiresAt compares the exp claim against cmp (cmp < exp).
|
||||
// If req is false, it will return true, if exp is unset.
|
||||
func (c *RegisteredClaims) VerifyExpiresAt(cmp time.Time, req bool) bool {
|
||||
if c.ExpiresAt == nil {
|
||||
return verifyExp(nil, cmp, req)
|
||||
}
|
||||
|
||||
return verifyExp(&c.ExpiresAt.Time, cmp, req)
|
||||
}
|
||||
|
||||
// VerifyIssuedAt compares the iat claim against cmp (cmp >= iat).
|
||||
// If req is false, it will return true, if iat is unset.
|
||||
func (c *RegisteredClaims) VerifyIssuedAt(cmp time.Time, req bool) bool {
|
||||
if c.IssuedAt == nil {
|
||||
return verifyIat(nil, cmp, req)
|
||||
}
|
||||
|
||||
return verifyIat(&c.IssuedAt.Time, cmp, req)
|
||||
}
|
||||
|
||||
// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf).
|
||||
// If req is false, it will return true, if nbf is unset.
|
||||
func (c *RegisteredClaims) VerifyNotBefore(cmp time.Time, req bool) bool {
|
||||
if c.NotBefore == nil {
|
||||
return verifyNbf(nil, cmp, req)
|
||||
}
|
||||
|
||||
return verifyNbf(&c.NotBefore.Time, cmp, req)
|
||||
}
|
||||
|
||||
// VerifyIssuer compares the iss claim against cmp.
|
||||
// If required is false, this method will return true if the value matches or is unset
|
||||
func (c *RegisteredClaims) VerifyIssuer(cmp string, req bool) bool {
|
||||
return verifyIss(c.Issuer, cmp, req)
|
||||
}
|
||||
|
||||
// StandardClaims are a structured version of the JWT Claims Set, as referenced at
|
||||
// https://datatracker.ietf.org/doc/html/rfc7519#section-4. They do not follow the
|
||||
// specification exactly, since they were based on an earlier draft of the
|
||||
// specification and not updated. The main difference is that they only
|
||||
// support integer-based date fields and singular audiences. This might lead to
|
||||
// incompatibilities with other JWT implementations. The use of this is discouraged, instead
|
||||
// the newer RegisteredClaims struct should be used.
|
||||
//
|
||||
// Deprecated: Use RegisteredClaims instead for a forward-compatible way to access registered claims in a struct.
|
||||
// StandardClaims are a structured version of the Claims Section, as referenced at
|
||||
// https://tools.ietf.org/html/rfc7519#section-4.1
|
||||
// See examples for how to use this with your own claim types
|
||||
type StandardClaims struct {
|
||||
Audience string `json:"aud,omitempty"`
|
||||
ExpiresAt int64 `json:"exp,omitempty"`
|
||||
@@ -149,17 +36,17 @@ func (c StandardClaims) Valid() error {
|
||||
// default value in Go, let's not fail the verification for them.
|
||||
if !c.VerifyExpiresAt(now, false) {
|
||||
delta := time.Unix(now, 0).Sub(time.Unix(c.ExpiresAt, 0))
|
||||
vErr.Inner = fmt.Errorf("%s by %s", ErrTokenExpired, delta)
|
||||
vErr.Inner = fmt.Errorf("token is expired by %v", delta)
|
||||
vErr.Errors |= ValidationErrorExpired
|
||||
}
|
||||
|
||||
if !c.VerifyIssuedAt(now, false) {
|
||||
vErr.Inner = ErrTokenUsedBeforeIssued
|
||||
vErr.Inner = fmt.Errorf("Token used before issued")
|
||||
vErr.Errors |= ValidationErrorIssuedAt
|
||||
}
|
||||
|
||||
if !c.VerifyNotBefore(now, false) {
|
||||
vErr.Inner = ErrTokenNotValidYet
|
||||
vErr.Inner = fmt.Errorf("token is not valid yet")
|
||||
vErr.Errors |= ValidationErrorNotValidYet
|
||||
}
|
||||
|
||||
@@ -176,37 +63,16 @@ func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool {
|
||||
return verifyAud([]string{c.Audience}, cmp, req)
|
||||
}
|
||||
|
||||
// VerifyExpiresAt compares the exp claim against cmp (cmp < exp).
|
||||
// If req is false, it will return true, if exp is unset.
|
||||
// VerifyExpiresAt compares the exp claim against cmp.
|
||||
// If required is false, this method will return true if the value matches or is unset
|
||||
func (c *StandardClaims) VerifyExpiresAt(cmp int64, req bool) bool {
|
||||
if c.ExpiresAt == 0 {
|
||||
return verifyExp(nil, time.Unix(cmp, 0), req)
|
||||
}
|
||||
|
||||
t := time.Unix(c.ExpiresAt, 0)
|
||||
return verifyExp(&t, time.Unix(cmp, 0), req)
|
||||
return verifyExp(c.ExpiresAt, cmp, req)
|
||||
}
|
||||
|
||||
// VerifyIssuedAt compares the iat claim against cmp (cmp >= iat).
|
||||
// If req is false, it will return true, if iat is unset.
|
||||
// VerifyIssuedAt compares the iat claim against cmp.
|
||||
// If required is false, this method will return true if the value matches or is unset
|
||||
func (c *StandardClaims) VerifyIssuedAt(cmp int64, req bool) bool {
|
||||
if c.IssuedAt == 0 {
|
||||
return verifyIat(nil, time.Unix(cmp, 0), req)
|
||||
}
|
||||
|
||||
t := time.Unix(c.IssuedAt, 0)
|
||||
return verifyIat(&t, time.Unix(cmp, 0), req)
|
||||
}
|
||||
|
||||
// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf).
|
||||
// If req is false, it will return true, if nbf is unset.
|
||||
func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool {
|
||||
if c.NotBefore == 0 {
|
||||
return verifyNbf(nil, time.Unix(cmp, 0), req)
|
||||
}
|
||||
|
||||
t := time.Unix(c.NotBefore, 0)
|
||||
return verifyNbf(&t, time.Unix(cmp, 0), req)
|
||||
return verifyIat(c.IssuedAt, cmp, req)
|
||||
}
|
||||
|
||||
// VerifyIssuer compares the iss claim against cmp.
|
||||
@@ -215,6 +81,12 @@ func (c *StandardClaims) VerifyIssuer(cmp string, req bool) bool {
|
||||
return verifyIss(c.Issuer, cmp, req)
|
||||
}
|
||||
|
||||
// VerifyNotBefore compares the nbf claim against cmp.
|
||||
// If required is false, this method will return true if the value matches or is unset
|
||||
func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool {
|
||||
return verifyNbf(c.NotBefore, cmp, req)
|
||||
}
|
||||
|
||||
// ----- helpers
|
||||
|
||||
func verifyAud(aud []string, cmp string, required bool) bool {
|
||||
@@ -240,25 +112,18 @@ func verifyAud(aud []string, cmp string, required bool) bool {
|
||||
return result
|
||||
}
|
||||
|
||||
func verifyExp(exp *time.Time, now time.Time, required bool) bool {
|
||||
if exp == nil {
|
||||
func verifyExp(exp int64, now int64, required bool) bool {
|
||||
if exp == 0 {
|
||||
return !required
|
||||
}
|
||||
return now.Before(*exp)
|
||||
return now <= exp
|
||||
}
|
||||
|
||||
func verifyIat(iat *time.Time, now time.Time, required bool) bool {
|
||||
if iat == nil {
|
||||
func verifyIat(iat int64, now int64, required bool) bool {
|
||||
if iat == 0 {
|
||||
return !required
|
||||
}
|
||||
return now.After(*iat) || now.Equal(*iat)
|
||||
}
|
||||
|
||||
func verifyNbf(nbf *time.Time, now time.Time, required bool) bool {
|
||||
if nbf == nil {
|
||||
return !required
|
||||
}
|
||||
return now.After(*nbf) || now.Equal(*nbf)
|
||||
return now >= iat
|
||||
}
|
||||
|
||||
func verifyIss(iss string, cmp string, required bool) bool {
|
||||
@@ -271,3 +136,10 @@ func verifyIss(iss string, cmp string, required bool) bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func verifyNbf(nbf int64, now int64, required bool) bool {
|
||||
if nbf == 0 {
|
||||
return !required
|
||||
}
|
||||
return now >= nbf
|
||||
}
|
||||
|
||||
16
vendor/github.com/golang-jwt/jwt/v4/ed25519.go
generated
vendored
16
vendor/github.com/golang-jwt/jwt/v4/ed25519.go
generated
vendored
@@ -3,9 +3,7 @@ package jwt
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"crypto"
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -64,22 +62,20 @@ func (m *SigningMethodEd25519) Verify(signingString, signature string, key inter
|
||||
// Sign implements token signing for the SigningMethod.
|
||||
// For this signing method, key must be an ed25519.PrivateKey
|
||||
func (m *SigningMethodEd25519) Sign(signingString string, key interface{}) (string, error) {
|
||||
var ed25519Key crypto.Signer
|
||||
var ed25519Key ed25519.PrivateKey
|
||||
var ok bool
|
||||
|
||||
if ed25519Key, ok = key.(crypto.Signer); !ok {
|
||||
if ed25519Key, ok = key.(ed25519.PrivateKey); !ok {
|
||||
return "", ErrInvalidKeyType
|
||||
}
|
||||
|
||||
if _, ok := ed25519Key.Public().(ed25519.PublicKey); !ok {
|
||||
// ed25519.Sign panics if private key not equal to ed25519.PrivateKeySize
|
||||
// this allows to avoid recover usage
|
||||
if len(ed25519Key) != ed25519.PrivateKeySize {
|
||||
return "", ErrInvalidKey
|
||||
}
|
||||
|
||||
// Sign the string and return the encoded result
|
||||
// ed25519 performs a two-pass hash as part of its algorithm. Therefore, we need to pass a non-prehashed message into the Sign function, as indicated by crypto.Hash(0)
|
||||
sig, err := ed25519Key.Sign(rand.Reader, []byte(signingString), crypto.Hash(0))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
sig := ed25519.Sign(ed25519Key, []byte(signingString))
|
||||
return EncodeSegment(sig), nil
|
||||
}
|
||||
|
||||
53
vendor/github.com/golang-jwt/jwt/v4/errors.go
generated
vendored
53
vendor/github.com/golang-jwt/jwt/v4/errors.go
generated
vendored
@@ -9,18 +9,6 @@ var (
|
||||
ErrInvalidKey = errors.New("key is invalid")
|
||||
ErrInvalidKeyType = errors.New("key is of invalid type")
|
||||
ErrHashUnavailable = errors.New("the requested hash function is unavailable")
|
||||
|
||||
ErrTokenMalformed = errors.New("token is malformed")
|
||||
ErrTokenUnverifiable = errors.New("token is unverifiable")
|
||||
ErrTokenSignatureInvalid = errors.New("token signature is invalid")
|
||||
|
||||
ErrTokenInvalidAudience = errors.New("token has invalid audience")
|
||||
ErrTokenExpired = errors.New("token is expired")
|
||||
ErrTokenUsedBeforeIssued = errors.New("token used before issued")
|
||||
ErrTokenInvalidIssuer = errors.New("token has invalid issuer")
|
||||
ErrTokenNotValidYet = errors.New("token is not valid yet")
|
||||
ErrTokenInvalidId = errors.New("token has invalid id")
|
||||
ErrTokenInvalidClaims = errors.New("token has invalid claims")
|
||||
)
|
||||
|
||||
// The errors that might occur when parsing and validating a token
|
||||
@@ -65,48 +53,7 @@ func (e ValidationError) Error() string {
|
||||
}
|
||||
}
|
||||
|
||||
// Unwrap gives errors.Is and errors.As access to the inner error.
|
||||
func (e *ValidationError) Unwrap() error {
|
||||
return e.Inner
|
||||
}
|
||||
|
||||
// No errors
|
||||
func (e *ValidationError) valid() bool {
|
||||
return e.Errors == 0
|
||||
}
|
||||
|
||||
// Is checks if this ValidationError is of the supplied error. We are first checking for the exact error message
|
||||
// by comparing the inner error message. If that fails, we compare using the error flags. This way we can use
|
||||
// custom error messages (mainly for backwards compatability) and still leverage errors.Is using the global error variables.
|
||||
func (e *ValidationError) Is(err error) bool {
|
||||
// Check, if our inner error is a direct match
|
||||
if errors.Is(errors.Unwrap(e), err) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Otherwise, we need to match using our error flags
|
||||
switch err {
|
||||
case ErrTokenMalformed:
|
||||
return e.Errors&ValidationErrorMalformed != 0
|
||||
case ErrTokenUnverifiable:
|
||||
return e.Errors&ValidationErrorUnverifiable != 0
|
||||
case ErrTokenSignatureInvalid:
|
||||
return e.Errors&ValidationErrorSignatureInvalid != 0
|
||||
case ErrTokenInvalidAudience:
|
||||
return e.Errors&ValidationErrorAudience != 0
|
||||
case ErrTokenExpired:
|
||||
return e.Errors&ValidationErrorExpired != 0
|
||||
case ErrTokenUsedBeforeIssued:
|
||||
return e.Errors&ValidationErrorIssuedAt != 0
|
||||
case ErrTokenInvalidIssuer:
|
||||
return e.Errors&ValidationErrorIssuer != 0
|
||||
case ErrTokenNotValidYet:
|
||||
return e.Errors&ValidationErrorNotValidYet != 0
|
||||
case ErrTokenInvalidId:
|
||||
return e.Errors&ValidationErrorId != 0
|
||||
case ErrTokenInvalidClaims:
|
||||
return e.Errors&ValidationErrorClaimsInvalid != 0
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
95
vendor/github.com/golang-jwt/jwt/v4/map_claims.go
generated
vendored
95
vendor/github.com/golang-jwt/jwt/v4/map_claims.go
generated
vendored
@@ -3,7 +3,6 @@ package jwt
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
// "fmt"
|
||||
)
|
||||
|
||||
@@ -32,81 +31,37 @@ func (m MapClaims) VerifyAudience(cmp string, req bool) bool {
|
||||
return verifyAud(aud, cmp, req)
|
||||
}
|
||||
|
||||
// VerifyExpiresAt compares the exp claim against cmp (cmp <= exp).
|
||||
// If req is false, it will return true, if exp is unset.
|
||||
// VerifyExpiresAt compares the exp claim against cmp.
|
||||
// If required is false, this method will return true if the value matches or is unset
|
||||
func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool {
|
||||
cmpTime := time.Unix(cmp, 0)
|
||||
|
||||
v, ok := m["exp"]
|
||||
exp, ok := m["exp"]
|
||||
if !ok {
|
||||
return !req
|
||||
}
|
||||
|
||||
switch exp := v.(type) {
|
||||
switch expType := exp.(type) {
|
||||
case float64:
|
||||
if exp == 0 {
|
||||
return verifyExp(nil, cmpTime, req)
|
||||
}
|
||||
|
||||
return verifyExp(&newNumericDateFromSeconds(exp).Time, cmpTime, req)
|
||||
return verifyExp(int64(expType), cmp, req)
|
||||
case json.Number:
|
||||
v, _ := exp.Float64()
|
||||
|
||||
return verifyExp(&newNumericDateFromSeconds(v).Time, cmpTime, req)
|
||||
v, _ := expType.Int64()
|
||||
return verifyExp(v, cmp, req)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// VerifyIssuedAt compares the exp claim against cmp (cmp >= iat).
|
||||
// If req is false, it will return true, if iat is unset.
|
||||
// VerifyIssuedAt compares the iat claim against cmp.
|
||||
// If required is false, this method will return true if the value matches or is unset
|
||||
func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool {
|
||||
cmpTime := time.Unix(cmp, 0)
|
||||
|
||||
v, ok := m["iat"]
|
||||
iat, ok := m["iat"]
|
||||
if !ok {
|
||||
return !req
|
||||
}
|
||||
|
||||
switch iat := v.(type) {
|
||||
switch iatType := iat.(type) {
|
||||
case float64:
|
||||
if iat == 0 {
|
||||
return verifyIat(nil, cmpTime, req)
|
||||
}
|
||||
|
||||
return verifyIat(&newNumericDateFromSeconds(iat).Time, cmpTime, req)
|
||||
return verifyIat(int64(iatType), cmp, req)
|
||||
case json.Number:
|
||||
v, _ := iat.Float64()
|
||||
|
||||
return verifyIat(&newNumericDateFromSeconds(v).Time, cmpTime, req)
|
||||
v, _ := iatType.Int64()
|
||||
return verifyIat(v, cmp, req)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf).
|
||||
// If req is false, it will return true, if nbf is unset.
|
||||
func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool {
|
||||
cmpTime := time.Unix(cmp, 0)
|
||||
|
||||
v, ok := m["nbf"]
|
||||
if !ok {
|
||||
return !req
|
||||
}
|
||||
|
||||
switch nbf := v.(type) {
|
||||
case float64:
|
||||
if nbf == 0 {
|
||||
return verifyNbf(nil, cmpTime, req)
|
||||
}
|
||||
|
||||
return verifyNbf(&newNumericDateFromSeconds(nbf).Time, cmpTime, req)
|
||||
case json.Number:
|
||||
v, _ := nbf.Float64()
|
||||
|
||||
return verifyNbf(&newNumericDateFromSeconds(v).Time, cmpTime, req)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -117,7 +72,24 @@ func (m MapClaims) VerifyIssuer(cmp string, req bool) bool {
|
||||
return verifyIss(iss, cmp, req)
|
||||
}
|
||||
|
||||
// Valid validates time based claims "exp, iat, nbf".
|
||||
// VerifyNotBefore compares the nbf claim against cmp.
|
||||
// If required is false, this method will return true if the value matches or is unset
|
||||
func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool {
|
||||
nbf, ok := m["nbf"]
|
||||
if !ok {
|
||||
return !req
|
||||
}
|
||||
switch nbfType := nbf.(type) {
|
||||
case float64:
|
||||
return verifyNbf(int64(nbfType), cmp, req)
|
||||
case json.Number:
|
||||
v, _ := nbfType.Int64()
|
||||
return verifyNbf(v, cmp, req)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Valid calidates time based claims "exp, iat, nbf".
|
||||
// There is no accounting for clock skew.
|
||||
// As well, if any of the above claims are not in the token, it will still
|
||||
// be considered a valid claim.
|
||||
@@ -126,19 +98,16 @@ func (m MapClaims) Valid() error {
|
||||
now := TimeFunc().Unix()
|
||||
|
||||
if !m.VerifyExpiresAt(now, false) {
|
||||
// TODO(oxisto): this should be replaced with ErrTokenExpired
|
||||
vErr.Inner = errors.New("Token is expired")
|
||||
vErr.Errors |= ValidationErrorExpired
|
||||
}
|
||||
|
||||
if !m.VerifyIssuedAt(now, false) {
|
||||
// TODO(oxisto): this should be replaced with ErrTokenUsedBeforeIssued
|
||||
vErr.Inner = errors.New("Token used before issued")
|
||||
vErr.Errors |= ValidationErrorIssuedAt
|
||||
}
|
||||
|
||||
if !m.VerifyNotBefore(now, false) {
|
||||
// TODO(oxisto): this should be replaced with ErrTokenNotValidYet
|
||||
vErr.Inner = errors.New("Token is not valid yet")
|
||||
vErr.Errors |= ValidationErrorNotValidYet
|
||||
}
|
||||
|
||||
32
vendor/github.com/golang-jwt/jwt/v4/parser.go
generated
vendored
32
vendor/github.com/golang-jwt/jwt/v4/parser.go
generated
vendored
@@ -8,36 +8,14 @@ import (
|
||||
)
|
||||
|
||||
type Parser struct {
|
||||
// If populated, only these methods will be considered valid.
|
||||
//
|
||||
// Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead.
|
||||
ValidMethods []string
|
||||
|
||||
// Use JSON Number format in JSON decoder.
|
||||
//
|
||||
// Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead.
|
||||
UseJSONNumber bool
|
||||
|
||||
// Skip claims validation during token parsing.
|
||||
//
|
||||
// Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead.
|
||||
SkipClaimsValidation bool
|
||||
ValidMethods []string // If populated, only these methods will be considered valid
|
||||
UseJSONNumber bool // Use JSON Number format in JSON decoder
|
||||
SkipClaimsValidation bool // Skip claims validation during token parsing
|
||||
}
|
||||
|
||||
// NewParser creates a new Parser with the specified options
|
||||
func NewParser(options ...ParserOption) *Parser {
|
||||
p := &Parser{}
|
||||
|
||||
// loop through our parsing options and apply them
|
||||
for _, option := range options {
|
||||
option(p)
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
// Parse parses, validates, verifies the signature and returns the parsed token.
|
||||
// Parse parses, validates, and returns a token.
|
||||
// keyFunc will receive the parsed token and should return the key for validating.
|
||||
// If everything is kosher, err will be nil
|
||||
func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
|
||||
return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc)
|
||||
}
|
||||
|
||||
29
vendor/github.com/golang-jwt/jwt/v4/parser_option.go
generated
vendored
29
vendor/github.com/golang-jwt/jwt/v4/parser_option.go
generated
vendored
@@ -1,29 +0,0 @@
|
||||
package jwt
|
||||
|
||||
// ParserOption is used to implement functional-style options that modify the behavior of the parser. To add
|
||||
// new options, just create a function (ideally beginning with With or Without) that returns an anonymous function that
|
||||
// takes a *Parser type as input and manipulates its configuration accordingly.
|
||||
type ParserOption func(*Parser)
|
||||
|
||||
// WithValidMethods is an option to supply algorithm methods that the parser will check. Only those methods will be considered valid.
|
||||
// It is heavily encouraged to use this option in order to prevent attacks such as https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/.
|
||||
func WithValidMethods(methods []string) ParserOption {
|
||||
return func(p *Parser) {
|
||||
p.ValidMethods = methods
|
||||
}
|
||||
}
|
||||
|
||||
// WithJSONNumber is an option to configure the underlying JSON parser with UseNumber
|
||||
func WithJSONNumber() ParserOption {
|
||||
return func(p *Parser) {
|
||||
p.UseJSONNumber = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithoutClaimsValidation is an option to disable claims validation. This option should only be used if you exactly know
|
||||
// what you are doing.
|
||||
func WithoutClaimsValidation() ParserOption {
|
||||
return func(p *Parser) {
|
||||
p.SkipClaimsValidation = true
|
||||
}
|
||||
}
|
||||
1
vendor/github.com/golang-jwt/jwt/v4/rsa_pss.go
generated
vendored
1
vendor/github.com/golang-jwt/jwt/v4/rsa_pss.go
generated
vendored
@@ -1,4 +1,3 @@
|
||||
//go:build go1.4
|
||||
// +build go1.4
|
||||
|
||||
package jwt
|
||||
|
||||
11
vendor/github.com/golang-jwt/jwt/v4/signing_method.go
generated
vendored
11
vendor/github.com/golang-jwt/jwt/v4/signing_method.go
generated
vendored
@@ -33,14 +33,3 @@ func GetSigningMethod(alg string) (method SigningMethod) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetAlgorithms returns a list of registered "alg" names
|
||||
func GetAlgorithms() (algs []string) {
|
||||
signingMethodLock.RLock()
|
||||
defer signingMethodLock.RUnlock()
|
||||
|
||||
for alg := range signingMethods {
|
||||
algs = append(algs, alg)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
63
vendor/github.com/golang-jwt/jwt/v4/token.go
generated
vendored
63
vendor/github.com/golang-jwt/jwt/v4/token.go
generated
vendored
@@ -7,13 +7,6 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// DecodePaddingAllowed will switch the codec used for decoding JWTs respectively. Note that the JWS RFC7515
|
||||
// states that the tokens will utilize a Base64url encoding with no padding. Unfortunately, some implementations
|
||||
// of JWT are producing non-standard tokens, and thus require support for decoding. Note that this is a global
|
||||
// variable, and updating it will change the behavior on a package level, and is also NOT go-routine safe.
|
||||
// To use the non-recommended decoding, set this boolean to `true` prior to using this package.
|
||||
var DecodePaddingAllowed bool
|
||||
|
||||
// TimeFunc provides the current time when parsing token to validate "exp" claim (expiration time).
|
||||
// You can override it to use another time value. This is useful for testing or if your
|
||||
// server uses a different time zone than your tokens.
|
||||
@@ -36,12 +29,11 @@ type Token struct {
|
||||
Valid bool // Is the token valid? Populated when you Parse/Verify a token
|
||||
}
|
||||
|
||||
// New creates a new Token with the specified signing method and an empty map of claims.
|
||||
// New creates a new Token. Takes a signing method
|
||||
func New(method SigningMethod) *Token {
|
||||
return NewWithClaims(method, MapClaims{})
|
||||
}
|
||||
|
||||
// NewWithClaims creates a new Token with the specified signing method and claims.
|
||||
func NewWithClaims(method SigningMethod, claims Claims) *Token {
|
||||
return &Token{
|
||||
Header: map[string]interface{}{
|
||||
@@ -53,8 +45,7 @@ func NewWithClaims(method SigningMethod, claims Claims) *Token {
|
||||
}
|
||||
}
|
||||
|
||||
// SignedString creates and returns a complete, signed JWT.
|
||||
// The token is signed using the SigningMethod specified in the token.
|
||||
// SignedString retrieves the complete, signed token
|
||||
func (t *Token) SignedString(key interface{}) (string, error) {
|
||||
var sig, sstr string
|
||||
var err error
|
||||
@@ -73,34 +64,33 @@ func (t *Token) SignedString(key interface{}) (string, error) {
|
||||
// the SignedString.
|
||||
func (t *Token) SigningString() (string, error) {
|
||||
var err error
|
||||
var jsonValue []byte
|
||||
parts := make([]string, 2)
|
||||
for i := range parts {
|
||||
var jsonValue []byte
|
||||
if i == 0 {
|
||||
if jsonValue, err = json.Marshal(t.Header); err != nil {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
if jsonValue, err = json.Marshal(t.Claims); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
if jsonValue, err = json.Marshal(t.Header); err != nil {
|
||||
return "", err
|
||||
parts[i] = EncodeSegment(jsonValue)
|
||||
}
|
||||
header := EncodeSegment(jsonValue)
|
||||
|
||||
if jsonValue, err = json.Marshal(t.Claims); err != nil {
|
||||
return "", err
|
||||
}
|
||||
claim := EncodeSegment(jsonValue)
|
||||
|
||||
return strings.Join([]string{header, claim}, "."), nil
|
||||
return strings.Join(parts, "."), nil
|
||||
}
|
||||
|
||||
// Parse parses, validates, verifies the signature and returns the parsed token.
|
||||
// keyFunc will receive the parsed token and should return the cryptographic key
|
||||
// for verifying the signature.
|
||||
// The caller is strongly encouraged to set the WithValidMethods option to
|
||||
// validate the 'alg' claim in the token matches the expected algorithm.
|
||||
// For more details about the importance of validating the 'alg' claim,
|
||||
// see https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/
|
||||
func Parse(tokenString string, keyFunc Keyfunc, options ...ParserOption) (*Token, error) {
|
||||
return NewParser(options...).Parse(tokenString, keyFunc)
|
||||
// Parse parses, validates, and returns a token.
|
||||
// keyFunc will receive the parsed token and should return the key for validating.
|
||||
// If everything is kosher, err will be nil
|
||||
func Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
|
||||
return new(Parser).Parse(tokenString, keyFunc)
|
||||
}
|
||||
|
||||
func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc, options ...ParserOption) (*Token, error) {
|
||||
return NewParser(options...).ParseWithClaims(tokenString, claims, keyFunc)
|
||||
func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) {
|
||||
return new(Parser).ParseWithClaims(tokenString, claims, keyFunc)
|
||||
}
|
||||
|
||||
// EncodeSegment encodes a JWT specific base64url encoding with padding stripped
|
||||
@@ -116,12 +106,5 @@ func EncodeSegment(seg []byte) string {
|
||||
// Deprecated: In a future release, we will demote this function to a non-exported function, since it
|
||||
// should only be used internally
|
||||
func DecodeSegment(seg string) ([]byte, error) {
|
||||
if DecodePaddingAllowed {
|
||||
if l := len(seg) % 4; l > 0 {
|
||||
seg += strings.Repeat("=", 4-l)
|
||||
}
|
||||
return base64.URLEncoding.DecodeString(seg)
|
||||
}
|
||||
|
||||
return base64.RawURLEncoding.DecodeString(seg)
|
||||
}
|
||||
|
||||
145
vendor/github.com/golang-jwt/jwt/v4/types.go
generated
vendored
145
vendor/github.com/golang-jwt/jwt/v4/types.go
generated
vendored
@@ -1,145 +0,0 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 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 NewNumericDate(t time.Time) *NumericDate {
|
||||
return &NumericDate{t.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(f float64) *NumericDate {
|
||||
round, frac := math.Modf(f)
|
||||
return NewNumericDate(time.Unix(int64(round), int64(frac*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 (date NumericDate) MarshalJSON() (b []byte, err error) {
|
||||
var prec int
|
||||
if TimePrecision < time.Second {
|
||||
prec = int(math.Log10(float64(time.Second) / float64(TimePrecision)))
|
||||
}
|
||||
truncatedDate := date.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
|
||||
seconds := strconv.FormatInt(truncatedDate.Unix(), 10)
|
||||
nanosecondsOffset := strconv.FormatFloat(float64(truncatedDate.Nanosecond())/float64(time.Second), 'f', prec, 64)
|
||||
|
||||
output := append([]byte(seconds), []byte(nanosecondsOffset)[1:]...)
|
||||
|
||||
return output, 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 (date *NumericDate) UnmarshalJSON(b []byte) (err error) {
|
||||
var (
|
||||
number json.Number
|
||||
f float64
|
||||
)
|
||||
|
||||
if err = json.Unmarshal(b, &number); err != nil {
|
||||
return fmt.Errorf("could not parse NumericData: %w", err)
|
||||
}
|
||||
|
||||
if f, err = number.Float64(); err != nil {
|
||||
return fmt.Errorf("could not convert json number value to float: %w", err)
|
||||
}
|
||||
|
||||
n := newNumericDateFromSeconds(f)
|
||||
*date = *n
|
||||
|
||||
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 (s *ClaimStrings) UnmarshalJSON(data []byte) (err error) {
|
||||
var value interface{}
|
||||
|
||||
if err = json.Unmarshal(data, &value); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var aud []string
|
||||
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
aud = append(aud, v)
|
||||
case []string:
|
||||
aud = ClaimStrings(v)
|
||||
case []interface{}:
|
||||
for _, vv := range v {
|
||||
vs, ok := vv.(string)
|
||||
if !ok {
|
||||
return &json.UnsupportedTypeError{Type: reflect.TypeOf(vv)}
|
||||
}
|
||||
aud = append(aud, vs)
|
||||
}
|
||||
case nil:
|
||||
return nil
|
||||
default:
|
||||
return &json.UnsupportedTypeError{Type: reflect.TypeOf(v)}
|
||||
}
|
||||
|
||||
*s = aud
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s ClaimStrings) MarshalJSON() (b []byte, err 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(s) == 1 && !MarshalSingleStringAsArray {
|
||||
return json.Marshal(s[0])
|
||||
}
|
||||
|
||||
return json.Marshal([]string(s))
|
||||
}
|
||||
Reference in New Issue
Block a user