You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

parser.go 4.6KB

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