mirror of
https://github.com/rclone/rclone.git
synced 2025-06-24 05:51:34 +02:00
lib/jwtutil: upgrade jwt-go (golang-jwt) from v4 to v5
This commit is contained in:
parent
f4d7df1511
commit
8c3ea2842c
@ -1,18 +1,18 @@
|
|||||||
package jwtutil
|
package jwtutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/subtle"
|
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The following is the StandardClaims implementation from jwt-go v4,
|
// The following is the declaration of the StandardClaims type from jwt-go v4
|
||||||
// where it was marked as deprecated before removed in v5. Some small
|
// (https://github.com/golang-jwt/jwt/blob/v4/claims.go), where it was marked
|
||||||
// adjustments the original code have been made, to satisfy linters etc.
|
// as deprecated before later removed in v5. It was distributed under the terms
|
||||||
// The type has also been renamed to LegacyStandardClaims to avoid confusion.
|
// of the MIT License (https://github.com/golang-jwt/jwt/blob/v4/LICENSE), with
|
||||||
// Source: https://github.com/golang-jwt/jwt/blob/v4/claims.go
|
// the copy right notice included below. We have renamed the type to
|
||||||
|
// LegacyStandardClaims to avoid confusion, and made it compatible with
|
||||||
|
// jwt-go v5 by implementing functions to satisfy the changed Claims interface.
|
||||||
|
|
||||||
// Copyright (c) 2012 Dave Grijalva
|
// Copyright (c) 2012 Dave Grijalva
|
||||||
// Copyright (c) 2021 golang-jwt maintainers
|
// Copyright (c) 2021 golang-jwt maintainers
|
||||||
@ -53,132 +53,32 @@ type LegacyStandardClaims struct {
|
|||||||
Subject string `json:"sub,omitempty"`
|
Subject string `json:"sub,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Valid validates time based claims "exp, iat, nbf". There is no accounting for clock skew.
|
// GetExpirationTime implements the Claims interface.
|
||||||
// As well, if any of the above claims are not in the token, it will still
|
func (c LegacyStandardClaims) GetExpirationTime() (*jwt.NumericDate, error) {
|
||||||
// be considered a valid claim.
|
return jwt.NewNumericDate(time.Unix(c.ExpiresAt, 0)), nil
|
||||||
func (c LegacyStandardClaims) Valid() error {
|
|
||||||
vErr := new(jwt.ValidationError)
|
|
||||||
now := jwt.TimeFunc().Unix()
|
|
||||||
|
|
||||||
// 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 := time.Unix(now, 0).Sub(time.Unix(c.ExpiresAt, 0))
|
|
||||||
vErr.Inner = fmt.Errorf("%s by %s", jwt.ErrTokenExpired, delta)
|
|
||||||
vErr.Errors |= jwt.ValidationErrorExpired
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !c.VerifyIssuedAt(now, false) {
|
// GetIssuedAt implements the Claims interface.
|
||||||
vErr.Inner = jwt.ErrTokenUsedBeforeIssued
|
func (c LegacyStandardClaims) GetIssuedAt() (*jwt.NumericDate, error) {
|
||||||
vErr.Errors |= jwt.ValidationErrorIssuedAt
|
return jwt.NewNumericDate(time.Unix(c.IssuedAt, 0)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !c.VerifyNotBefore(now, false) {
|
// GetNotBefore implements the Claims interface.
|
||||||
vErr.Inner = jwt.ErrTokenNotValidYet
|
func (c LegacyStandardClaims) GetNotBefore() (*jwt.NumericDate, error) {
|
||||||
vErr.Errors |= jwt.ValidationErrorNotValidYet
|
return jwt.NewNumericDate(time.Unix(c.NotBefore, 0)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if vErr.Errors == 0 {
|
// GetIssuer implements the Claims interface.
|
||||||
return nil
|
func (c LegacyStandardClaims) GetIssuer() (string, error) {
|
||||||
|
return c.Issuer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return vErr
|
// GetSubject implements the Claims interface.
|
||||||
|
func (c LegacyStandardClaims) GetSubject() (string, error) {
|
||||||
|
return c.Subject, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyAudience compares the aud claim against cmp.
|
// GetAudience implements the Claims interface.
|
||||||
// If required is false, this method will return true if the value matches or is unset
|
func (c LegacyStandardClaims) GetAudience() (jwt.ClaimStrings, error) {
|
||||||
func (c *LegacyStandardClaims) VerifyAudience(cmp string, req bool) bool {
|
return []string{c.Audience}, nil
|
||||||
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.
|
|
||||||
func (c *LegacyStandardClaims) 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VerifyIssuedAt compares the iat claim against cmp (cmp >= iat).
|
|
||||||
// If req is false, it will return true, if iat is unset.
|
|
||||||
func (c *LegacyStandardClaims) 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 *LegacyStandardClaims) 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 *LegacyStandardClaims) VerifyIssuer(cmp string, req bool) bool {
|
|
||||||
return verifyIss(c.Issuer, cmp, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----- helpers
|
|
||||||
|
|
||||||
func verifyAud(aud []string, cmp string, required bool) bool {
|
|
||||||
if len(aud) == 0 {
|
|
||||||
return !required
|
|
||||||
}
|
|
||||||
// use a var here to keep constant time compare when looping over a number of claims
|
|
||||||
result := false
|
|
||||||
|
|
||||||
var stringClaims string
|
|
||||||
for _, a := range aud {
|
|
||||||
if subtle.ConstantTimeCompare([]byte(a), []byte(cmp)) != 0 {
|
|
||||||
result = true
|
|
||||||
}
|
|
||||||
stringClaims += a
|
|
||||||
}
|
|
||||||
|
|
||||||
// case where "" is sent in one or many aud claims
|
|
||||||
if len(stringClaims) == 0 {
|
|
||||||
return !required
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
func verifyExp(exp *time.Time, now time.Time, required bool) bool {
|
|
||||||
if exp == nil {
|
|
||||||
return !required
|
|
||||||
}
|
|
||||||
return now.Before(*exp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func verifyIat(iat *time.Time, now time.Time, required bool) bool {
|
|
||||||
if iat == nil {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
func verifyIss(iss string, cmp string, required bool) bool {
|
|
||||||
if iss == "" {
|
|
||||||
return !required
|
|
||||||
}
|
|
||||||
return subtle.ConstantTimeCompare([]byte(iss), []byte(cmp)) != 0
|
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v4"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
"github.com/rclone/rclone/fs"
|
"github.com/rclone/rclone/fs"
|
||||||
"github.com/rclone/rclone/fs/config/configmap"
|
"github.com/rclone/rclone/fs/config/configmap"
|
||||||
"github.com/rclone/rclone/lib/oauthutil"
|
"github.com/rclone/rclone/lib/oauthutil"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user