gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

parser.go (4721B)


      1 package jwt
      2 
      3 import (
      4 	"bytes"
      5 	"encoding/json"
      6 	"fmt"
      7 	"strings"
      8 )
      9 
     10 type Parser struct {
     11 	ValidMethods         []string // If populated, only these methods will be considered valid
     12 	UseJSONNumber        bool     // Use JSON Number format in JSON decoder
     13 	SkipClaimsValidation bool     // Skip claims validation during token parsing
     14 }
     15 
     16 // Parse, validate, and return a token.
     17 // keyFunc will receive the parsed token and should return the key for validating.
     18 // If everything is kosher, err will be nil
     19 func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
     20 	return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc)
     21 }
     22 
     23 func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) {
     24 	token, parts, err := p.ParseUnverified(tokenString, claims)
     25 	if err != nil {
     26 		return token, err
     27 	}
     28 
     29 	// Verify signing method is in the required set
     30 	if p.ValidMethods != nil {
     31 		var signingMethodValid = false
     32 		var alg = token.Method.Alg()
     33 		for _, m := range p.ValidMethods {
     34 			if m == alg {
     35 				signingMethodValid = true
     36 				break
     37 			}
     38 		}
     39 		if !signingMethodValid {
     40 			// signing method is not in the listed set
     41 			return token, NewValidationError(fmt.Sprintf("signing method %v is invalid", alg), ValidationErrorSignatureInvalid)
     42 		}
     43 	}
     44 
     45 	// Lookup key
     46 	var key interface{}
     47 	if keyFunc == nil {
     48 		// keyFunc was not provided.  short circuiting validation
     49 		return token, NewValidationError("no Keyfunc was provided.", ValidationErrorUnverifiable)
     50 	}
     51 	if key, err = keyFunc(token); err != nil {
     52 		// keyFunc returned an error
     53 		if ve, ok := err.(*ValidationError); ok {
     54 			return token, ve
     55 		}
     56 		return token, &ValidationError{Inner: err, Errors: ValidationErrorUnverifiable}
     57 	}
     58 
     59 	vErr := &ValidationError{}
     60 
     61 	// Validate Claims
     62 	if !p.SkipClaimsValidation {
     63 		if err := token.Claims.Valid(); err != nil {
     64 
     65 			// If the Claims Valid returned an error, check if it is a validation error,
     66 			// If it was another error type, create a ValidationError with a generic ClaimsInvalid flag set
     67 			if e, ok := err.(*ValidationError); !ok {
     68 				vErr = &ValidationError{Inner: err, Errors: ValidationErrorClaimsInvalid}
     69 			} else {
     70 				vErr = e
     71 			}
     72 		}
     73 	}
     74 
     75 	// Perform validation
     76 	token.Signature = parts[2]
     77 	if err = token.Method.Verify(strings.Join(parts[0:2], "."), token.Signature, key); err != nil {
     78 		vErr.Inner = err
     79 		vErr.Errors |= ValidationErrorSignatureInvalid
     80 	}
     81 
     82 	if vErr.valid() {
     83 		token.Valid = true
     84 		return token, nil
     85 	}
     86 
     87 	return token, vErr
     88 }
     89 
     90 // WARNING: Don't use this method unless you know what you're doing
     91 //
     92 // This method parses the token but doesn't validate the signature. It's only
     93 // ever useful in cases where you know the signature is valid (because it has
     94 // been checked previously in the stack) and you want to extract values from
     95 // it.
     96 func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Token, parts []string, err error) {
     97 	parts = strings.Split(tokenString, ".")
     98 	if len(parts) != 3 {
     99 		return nil, parts, NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed)
    100 	}
    101 
    102 	token = &Token{Raw: tokenString}
    103 
    104 	// parse Header
    105 	var headerBytes []byte
    106 	if headerBytes, err = DecodeSegment(parts[0]); err != nil {
    107 		if strings.HasPrefix(strings.ToLower(tokenString), "bearer ") {
    108 			return token, parts, NewValidationError("tokenstring should not contain 'bearer '", ValidationErrorMalformed)
    109 		}
    110 		return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed}
    111 	}
    112 	if err = json.Unmarshal(headerBytes, &token.Header); err != nil {
    113 		return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed}
    114 	}
    115 
    116 	// parse Claims
    117 	var claimBytes []byte
    118 	token.Claims = claims
    119 
    120 	if claimBytes, err = DecodeSegment(parts[1]); err != nil {
    121 		return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed}
    122 	}
    123 	dec := json.NewDecoder(bytes.NewBuffer(claimBytes))
    124 	if p.UseJSONNumber {
    125 		dec.UseNumber()
    126 	}
    127 	// JSON Decode.  Special case for map type to avoid weird pointer behavior
    128 	if c, ok := token.Claims.(MapClaims); ok {
    129 		err = dec.Decode(&c)
    130 	} else {
    131 		err = dec.Decode(&claims)
    132 	}
    133 	// Handle decode error
    134 	if err != nil {
    135 		return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed}
    136 	}
    137 
    138 	// Lookup signature method
    139 	if method, ok := token.Header["alg"].(string); ok {
    140 		if token.Method = GetSigningMethod(method); token.Method == nil {
    141 			return token, parts, NewValidationError("signing method (alg) is unavailable.", ValidationErrorUnverifiable)
    142 		}
    143 	} else {
    144 		return token, parts, NewValidationError("signing method (alg) is unspecified.", ValidationErrorUnverifiable)
    145 	}
    146 
    147 	return token, parts, nil
    148 }