1package jwt 2 3import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "strings" 8) 9 10type 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 19func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { 20 return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc) 21} 22 23func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) { 24 parts := strings.Split(tokenString, ".") 25 if len(parts) != 3 { 26 return nil, NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed) 27 } 28 29 var err error 30 token := &Token{Raw: tokenString} 31 32 // parse Header 33 var headerBytes []byte 34 if headerBytes, err = DecodeSegment(parts[0]); err != nil { 35 if strings.HasPrefix(strings.ToLower(tokenString), "bearer ") { 36 return token, NewValidationError("tokenstring should not contain 'bearer '", ValidationErrorMalformed) 37 } 38 return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} 39 } 40 if err = json.Unmarshal(headerBytes, &token.Header); err != nil { 41 return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} 42 } 43 44 // parse Claims 45 var claimBytes []byte 46 token.Claims = claims 47 48 if claimBytes, err = DecodeSegment(parts[1]); err != nil { 49 return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} 50 } 51 dec := json.NewDecoder(bytes.NewBuffer(claimBytes)) 52 if p.UseJSONNumber { 53 dec.UseNumber() 54 } 55 // JSON Decode. Special case for map type to avoid weird pointer behavior 56 if c, ok := token.Claims.(MapClaims); ok { 57 err = dec.Decode(&c) 58 } else { 59 err = dec.Decode(&claims) 60 } 61 // Handle decode error 62 if err != nil { 63 return token, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} 64 } 65 66 // Lookup signature method 67 if method, ok := token.Header["alg"].(string); ok { 68 if token.Method = GetSigningMethod(method); token.Method == nil { 69 return token, NewValidationError("signing method (alg) is unavailable.", ValidationErrorUnverifiable) 70 } 71 } else { 72 return token, NewValidationError("signing method (alg) is unspecified.", ValidationErrorUnverifiable) 73 } 74 75 // Verify signing method is in the required set 76 if p.ValidMethods != nil { 77 var signingMethodValid = false 78 var alg = token.Method.Alg() 79 for _, m := range p.ValidMethods { 80 if m == alg { 81 signingMethodValid = true 82 break 83 } 84 } 85 if !signingMethodValid { 86 // signing method is not in the listed set 87 return token, NewValidationError(fmt.Sprintf("signing method %v is invalid", alg), ValidationErrorSignatureInvalid) 88 } 89 } 90 91 // Lookup key 92 var key interface{} 93 if keyFunc == nil { 94 // keyFunc was not provided. short circuiting validation 95 return token, NewValidationError("no Keyfunc was provided.", ValidationErrorUnverifiable) 96 } 97 if key, err = keyFunc(token); err != nil { 98 // keyFunc returned an error 99 return token, &ValidationError{Inner: err, Errors: ValidationErrorUnverifiable} 100 } 101 102 vErr := &ValidationError{} 103 104 // Validate Claims 105 if !p.SkipClaimsValidation { 106 if err := token.Claims.Valid(); err != nil { 107 108 // If the Claims Valid returned an error, check if it is a validation error, 109 // If it was another error type, create a ValidationError with a generic ClaimsInvalid flag set 110 if e, ok := err.(*ValidationError); !ok { 111 vErr = &ValidationError{Inner: err, Errors: ValidationErrorClaimsInvalid} 112 } else { 113 vErr = e 114 } 115 } 116 } 117 118 // Perform validation 119 token.Signature = parts[2] 120 if err = token.Method.Verify(strings.Join(parts[0:2], "."), token.Signature, key); err != nil { 121 vErr.Inner = err 122 vErr.Errors |= ValidationErrorSignatureInvalid 123 } 124 125 if vErr.valid() { 126 token.Valid = true 127 return token, nil 128 } 129 130 return token, vErr 131} 132