validation.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /*-
  2. * Copyright 2016 Zbigniew Mandziejewicz
  3. * Copyright 2016 Square, Inc.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package jwt
  18. import "time"
  19. const (
  20. // DefaultLeeway defines the default leeway for matching NotBefore/Expiry claims.
  21. DefaultLeeway = 1.0 * time.Minute
  22. )
  23. // Expected defines values used for protected claims validation.
  24. // If field has zero value then validation is skipped.
  25. type Expected struct {
  26. // Issuer matches the "iss" claim exactly.
  27. Issuer string
  28. // Subject matches the "sub" claim exactly.
  29. Subject string
  30. // Audience matches the values in "aud" claim, regardless of their order.
  31. Audience Audience
  32. // ID matches the "jti" claim exactly.
  33. ID string
  34. // Time matches the "exp" and "nbf" claims with leeway.
  35. Time time.Time
  36. }
  37. // WithTime copies expectations with new time.
  38. func (e Expected) WithTime(t time.Time) Expected {
  39. e.Time = t
  40. return e
  41. }
  42. // Validate checks claims in a token against expected values.
  43. // A default leeway value of one minute is used to compare time values.
  44. //
  45. // The default leeway will cause the token to be deemed valid until one
  46. // minute after the expiration time. If you're a server application that
  47. // wants to give an extra minute to client tokens, use this
  48. // function. If you're a client application wondering if the server
  49. // will accept your token, use ValidateWithLeeway with a leeway <=0,
  50. // otherwise this function might make you think a token is valid when
  51. // it is not.
  52. func (c Claims) Validate(e Expected) error {
  53. return c.ValidateWithLeeway(e, DefaultLeeway)
  54. }
  55. // ValidateWithLeeway checks claims in a token against expected values. A
  56. // custom leeway may be specified for comparing time values. You may pass a
  57. // zero value to check time values with no leeway, but you should not that
  58. // numeric date values are rounded to the nearest second and sub-second
  59. // precision is not supported.
  60. //
  61. // The leeway gives some extra time to the token from the server's
  62. // point of view. That is, if the token is expired, ValidateWithLeeway
  63. // will still accept the token for 'leeway' amount of time. This fails
  64. // if you're using this function to check if a server will accept your
  65. // token, because it will think the token is valid even after it
  66. // expires. So if you're a client validating if the token is valid to
  67. // be submitted to a server, use leeway <=0, if you're a server
  68. // validation a token, use leeway >=0.
  69. func (c Claims) ValidateWithLeeway(e Expected, leeway time.Duration) error {
  70. if e.Issuer != "" && e.Issuer != c.Issuer {
  71. return ErrInvalidIssuer
  72. }
  73. if e.Subject != "" && e.Subject != c.Subject {
  74. return ErrInvalidSubject
  75. }
  76. if e.ID != "" && e.ID != c.ID {
  77. return ErrInvalidID
  78. }
  79. if len(e.Audience) != 0 {
  80. for _, v := range e.Audience {
  81. if !c.Audience.Contains(v) {
  82. return ErrInvalidAudience
  83. }
  84. }
  85. }
  86. if !e.Time.IsZero() && e.Time.Add(leeway).Before(c.NotBefore.Time()) {
  87. return ErrNotValidYet
  88. }
  89. if !e.Time.IsZero() && e.Time.Add(-leeway).After(c.Expiry.Time()) {
  90. return ErrExpired
  91. }
  92. return nil
  93. }