Fix failing TestAuthExternalSAMLSuccess test
This commit is contained in:
+8
-2
@@ -83,7 +83,7 @@ func (c *RegisteredClaims) VerifyAudience(cmp string, req bool) bool {
|
||||
return verifyAud(c.Audience, cmp, req)
|
||||
}
|
||||
|
||||
// VerifyExpiresAt compares the exp claim against cmp (cmp <= exp).
|
||||
// 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 {
|
||||
@@ -113,6 +113,12 @@ func (c *RegisteredClaims) VerifyNotBefore(cmp time.Time, req bool) bool {
|
||||
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
|
||||
@@ -170,7 +176,7 @@ 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).
|
||||
// VerifyExpiresAt compares the exp claim against cmp (cmp < exp).
|
||||
// If req is false, it will return true, if exp is unset.
|
||||
func (c *StandardClaims) VerifyExpiresAt(cmp int64, req bool) bool {
|
||||
if c.ExpiresAt == 0 {
|
||||
|
||||
+5
@@ -53,6 +53,11 @@ 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
|
||||
|
||||
+27
-5
@@ -8,14 +8,36 @@ import (
|
||||
)
|
||||
|
||||
type Parser struct {
|
||||
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
|
||||
// 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
|
||||
}
|
||||
|
||||
// Parse parses, validates, and returns a token.
|
||||
// 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.
|
||||
// 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
@@ -0,0 +1,29 @@
|
||||
package jwt
|
||||
|
||||
// ParserOption is used to implement functional-style options that modify the behaviour 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 underyling 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
|
||||
}
|
||||
}
|
||||
+11
@@ -33,3 +33,14 @@ 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
|
||||
}
|
||||
|
||||
+30
-9
@@ -7,6 +7,14 @@ 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.
|
||||
@@ -29,11 +37,12 @@ type Token struct {
|
||||
Valid bool // Is the token valid? Populated when you Parse/Verify a token
|
||||
}
|
||||
|
||||
// New creates a new Token. Takes a signing method
|
||||
// New creates a new Token with the specified signing method and an empty map of claims.
|
||||
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{}{
|
||||
@@ -45,7 +54,8 @@ func NewWithClaims(method SigningMethod, claims Claims) *Token {
|
||||
}
|
||||
}
|
||||
|
||||
// SignedString retrieves the complete, signed token
|
||||
// SignedString creates and returns a complete, signed JWT.
|
||||
// The token is signed using the SigningMethod specified in the token.
|
||||
func (t *Token) SignedString(key interface{}) (string, error) {
|
||||
var sig, sstr string
|
||||
var err error
|
||||
@@ -82,15 +92,19 @@ func (t *Token) SigningString() (string, error) {
|
||||
return strings.Join(parts, "."), nil
|
||||
}
|
||||
|
||||
// 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)
|
||||
// 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)
|
||||
}
|
||||
|
||||
func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) {
|
||||
return new(Parser).ParseWithClaims(tokenString, claims, keyFunc)
|
||||
func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc, options ...ParserOption) (*Token, error) {
|
||||
return NewParser(options...).ParseWithClaims(tokenString, claims, keyFunc)
|
||||
}
|
||||
|
||||
// EncodeSegment encodes a JWT specific base64url encoding with padding stripped
|
||||
@@ -106,5 +120,12 @@ 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)
|
||||
}
|
||||
|
||||
+3
-1
@@ -3,6 +3,7 @@ package jwt
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -41,7 +42,8 @@ func NewNumericDate(t time.Time) *NumericDate {
|
||||
// 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 {
|
||||
return NewNumericDate(time.Unix(0, int64(f*float64(time.Second))))
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user