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 18 package jwt 19 20 import "time" 21 22 const ( 23 // DefaultLeeway defines the default leeway for matching NotBefore/Expiry claims. 24 DefaultLeeway = 1.0 * time.Minute 25 ) 26 27 // Expected defines values used for protected claims validation. 28 // If field has zero value then validation is skipped. 29 type Expected struct { 30 // Issuer matches the "iss" claim exactly. 31 Issuer string 32 // Subject matches the "sub" claim exactly. 33 Subject string 34 // Audience matches the values in "aud" claim, regardless of their order. 35 Audience Audience 36 // ID matches the "jti" claim exactly. 37 ID string 38 // Time matches the "exp", "nbf" and "iat" claims with leeway. 39 Time time.Time 40 } 41 42 // WithTime copies expectations with new time. 43 func (e Expected) WithTime(t time.Time) Expected { 44 e.Time = t 45 return e 46 } 47 48 // Validate checks claims in a token against expected values. 49 // A default leeway value of one minute is used to compare time values. 50 // 51 // The default leeway will cause the token to be deemed valid until one 52 // minute after the expiration time. If you're a server application that 53 // wants to give an extra minute to client tokens, use this 54 // function. If you're a client application wondering if the server 55 // will accept your token, use ValidateWithLeeway with a leeway <=0, 56 // otherwise this function might make you think a token is valid when 57 // it is not. 58 func (c Claims) Validate(e Expected) error { 59 return c.ValidateWithLeeway(e, DefaultLeeway) 60 } 61 62 // ValidateWithLeeway checks claims in a token against expected values. A 63 // custom leeway may be specified for comparing time values. You may pass a 64 // zero value to check time values with no leeway, but you should not that 65 // numeric date values are rounded to the nearest second and sub-second 66 // precision is not supported. 67 // 68 // The leeway gives some extra time to the token from the server's 69 // point of view. That is, if the token is expired, ValidateWithLeeway 70 // will still accept the token for 'leeway' amount of time. This fails 71 // if you're using this function to check if a server will accept your 72 // token, because it will think the token is valid even after it 73 // expires. So if you're a client validating if the token is valid to 74 // be submitted to a server, use leeway <=0, if you're a server 75 // validation a token, use leeway >=0. 76 func (c Claims) ValidateWithLeeway(e Expected, leeway time.Duration) error { 77 if e.Issuer != "" && e.Issuer != c.Issuer { 78 return ErrInvalidIssuer 79 } 80 81 if e.Subject != "" && e.Subject != c.Subject { 82 return ErrInvalidSubject 83 } 84 85 if e.ID != "" && e.ID != c.ID { 86 return ErrInvalidID 87 } 88 89 if len(e.Audience) != 0 { 90 for _, v := range e.Audience { 91 if !c.Audience.Contains(v) { 92 return ErrInvalidAudience 93 } 94 } 95 } 96 97 if !e.Time.IsZero() { 98 if c.NotBefore != nil && e.Time.Add(leeway).Before(c.NotBefore.Time()) { 99 return ErrNotValidYet 100 } 101 102 if c.Expiry != nil && e.Time.Add(-leeway).After(c.Expiry.Time()) { 103 return ErrExpired 104 } 105 106 // IssuedAt is optional but cannot be in the future. This is not required by the RFC, but 107 // something is misconfigured if this happens and we should not trust it. 108 if c.IssuedAt != nil && e.Time.Add(leeway).Before(c.IssuedAt.Time()) { 109 return ErrIssuedInTheFuture 110 } 111 } 112 113 return nil 114 } 115