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 }