...

Source file src/gopkg.in/go-jose/go-jose.v2/jwt/validation.go

Documentation: gopkg.in/go-jose/go-jose.v2/jwt

     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  

View as plain text