Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / github.com / dgrijalva / jwt-go / parser.go
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 }