map_claims.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. package jwt
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "time"
  6. // "fmt"
  7. )
  8. // MapClaims is a claims type that uses the map[string]interface{} for JSON decoding.
  9. // This is the default claims type if you don't supply one
  10. type MapClaims map[string]interface{}
  11. // VerifyAudience Compares the aud claim against cmp.
  12. // If required is false, this method will return true if the value matches or is unset
  13. func (m MapClaims) VerifyAudience(cmp string, req bool) bool {
  14. var aud []string
  15. switch v := m["aud"].(type) {
  16. case string:
  17. aud = append(aud, v)
  18. case []string:
  19. aud = v
  20. case []interface{}:
  21. for _, a := range v {
  22. vs, ok := a.(string)
  23. if !ok {
  24. return false
  25. }
  26. aud = append(aud, vs)
  27. }
  28. }
  29. return verifyAud(aud, cmp, req)
  30. }
  31. // VerifyExpiresAt compares the exp claim against cmp (cmp <= exp).
  32. // If req is false, it will return true, if exp is unset.
  33. func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool {
  34. cmpTime := time.Unix(cmp, 0)
  35. v, ok := m["exp"]
  36. if !ok {
  37. return !req
  38. }
  39. switch exp := v.(type) {
  40. case float64:
  41. if exp == 0 {
  42. return verifyExp(nil, cmpTime, req)
  43. }
  44. return verifyExp(&newNumericDateFromSeconds(exp).Time, cmpTime, req)
  45. case json.Number:
  46. v, _ := exp.Float64()
  47. return verifyExp(&newNumericDateFromSeconds(v).Time, cmpTime, req)
  48. }
  49. return false
  50. }
  51. // VerifyIssuedAt compares the exp claim against cmp (cmp >= iat).
  52. // If req is false, it will return true, if iat is unset.
  53. func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool {
  54. cmpTime := time.Unix(cmp, 0)
  55. v, ok := m["iat"]
  56. if !ok {
  57. return !req
  58. }
  59. switch iat := v.(type) {
  60. case float64:
  61. if iat == 0 {
  62. return verifyIat(nil, cmpTime, req)
  63. }
  64. return verifyIat(&newNumericDateFromSeconds(iat).Time, cmpTime, req)
  65. case json.Number:
  66. v, _ := iat.Float64()
  67. return verifyIat(&newNumericDateFromSeconds(v).Time, cmpTime, req)
  68. }
  69. return false
  70. }
  71. // VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf).
  72. // If req is false, it will return true, if nbf is unset.
  73. func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool {
  74. cmpTime := time.Unix(cmp, 0)
  75. v, ok := m["nbf"]
  76. if !ok {
  77. return !req
  78. }
  79. switch nbf := v.(type) {
  80. case float64:
  81. if nbf == 0 {
  82. return verifyNbf(nil, cmpTime, req)
  83. }
  84. return verifyNbf(&newNumericDateFromSeconds(nbf).Time, cmpTime, req)
  85. case json.Number:
  86. v, _ := nbf.Float64()
  87. return verifyNbf(&newNumericDateFromSeconds(v).Time, cmpTime, req)
  88. }
  89. return false
  90. }
  91. // VerifyIssuer compares the iss claim against cmp.
  92. // If required is false, this method will return true if the value matches or is unset
  93. func (m MapClaims) VerifyIssuer(cmp string, req bool) bool {
  94. iss, _ := m["iss"].(string)
  95. return verifyIss(iss, cmp, req)
  96. }
  97. // Valid validates time based claims "exp, iat, nbf".
  98. // There is no accounting for clock skew.
  99. // As well, if any of the above claims are not in the token, it will still
  100. // be considered a valid claim.
  101. func (m MapClaims) Valid() error {
  102. vErr := new(ValidationError)
  103. now := TimeFunc().Unix()
  104. if !m.VerifyExpiresAt(now, false) {
  105. // TODO(oxisto): this should be replaced with ErrTokenExpired
  106. vErr.Inner = errors.New("Token is expired")
  107. vErr.Errors |= ValidationErrorExpired
  108. }
  109. if !m.VerifyIssuedAt(now, false) {
  110. // TODO(oxisto): this should be replaced with ErrTokenUsedBeforeIssued
  111. vErr.Inner = errors.New("Token used before issued")
  112. vErr.Errors |= ValidationErrorIssuedAt
  113. }
  114. if !m.VerifyNotBefore(now, false) {
  115. // TODO(oxisto): this should be replaced with ErrTokenNotValidYet
  116. vErr.Inner = errors.New("Token is not valid yet")
  117. vErr.Errors |= ValidationErrorNotValidYet
  118. }
  119. if vErr.valid() {
  120. return nil
  121. }
  122. return vErr
  123. }