...

Source file src/github.com/lestrrat-go/jwx/jwk/option.go

Documentation: github.com/lestrrat-go/jwx/jwk

     1  package jwk
     2  
     3  import (
     4  	"crypto"
     5  	"time"
     6  
     7  	"github.com/lestrrat-go/backoff/v2"
     8  	"github.com/lestrrat-go/jwx/internal/json"
     9  	"github.com/lestrrat-go/option"
    10  )
    11  
    12  type Option = option.Interface
    13  
    14  type identHTTPClient struct{}
    15  type identThumbprintHash struct{}
    16  type identRefreshInterval struct{}
    17  type identMinRefreshInterval struct{}
    18  type identFetchBackoff struct{}
    19  type identPEM struct{}
    20  type identTypedField struct{}
    21  type identLocalRegistry struct{}
    22  type identFetchWhitelist struct{}
    23  type identIgnoreParseError struct{}
    24  
    25  // AutoRefreshOption is a type of Option that can be passed to the
    26  // AutoRefresh object.
    27  type AutoRefreshOption interface {
    28  	Option
    29  	autoRefreshOption()
    30  }
    31  
    32  type autoRefreshOption struct {
    33  	Option
    34  }
    35  
    36  func (*autoRefreshOption) autoRefreshOption() {}
    37  
    38  // FetchOption is a type of Option that can be passed to `jwk.Fetch()`
    39  // FetchOption also implements the `AutoRefreshOption`, and thus can
    40  // safely be passed to `(*jwk.AutoRefresh).Configure()`
    41  type FetchOption interface {
    42  	AutoRefreshOption
    43  	fetchOption()
    44  }
    45  
    46  type fetchOption struct {
    47  	Option
    48  }
    49  
    50  func (*fetchOption) autoRefreshOption() {}
    51  func (*fetchOption) fetchOption()       {}
    52  
    53  // ParseOption is a type of Option that can be passed to `jwk.Parse()`
    54  // ParseOption also implmentsthe `ReadFileOPtion` and `AutoRefreshOption`,
    55  // and thus safely be passed to `jwk.ReadFile` and `(*jwk.AutoRefresh).Configure()`
    56  type ParseOption interface {
    57  	ReadFileOption
    58  	AutoRefreshOption
    59  	parseOption()
    60  }
    61  
    62  type parseOption struct {
    63  	Option
    64  }
    65  
    66  func (*parseOption) autoRefreshOption() {}
    67  func (*parseOption) parseOption()       {}
    68  func (*parseOption) readFileOption()    {}
    69  
    70  // WithHTTPClient allows users to specify the "net/http".Client object that
    71  // is used when fetching jwk.Set objects.
    72  func WithHTTPClient(cl HTTPClient) FetchOption {
    73  	return &fetchOption{option.New(identHTTPClient{}, cl)}
    74  }
    75  
    76  // WithFetchBackoff specifies the backoff policy to use when
    77  // refreshing a JWKS from a remote server fails.
    78  //
    79  // This does not have any effect on initial `Fetch()`, or any of the `Refresh()` calls --
    80  // the backoff is applied ONLY on the background refreshing goroutine.
    81  func WithFetchBackoff(v backoff.Policy) FetchOption {
    82  	return &fetchOption{option.New(identFetchBackoff{}, v)}
    83  }
    84  
    85  func WithThumbprintHash(h crypto.Hash) Option {
    86  	return option.New(identThumbprintHash{}, h)
    87  }
    88  
    89  // WithRefreshInterval specifies the static interval between refreshes
    90  // of jwk.Set objects controlled by jwk.AutoRefresh.
    91  //
    92  // Providing this option overrides the adaptive token refreshing based
    93  // on Cache-Control/Expires header (and jwk.WithMinRefreshInterval),
    94  // and refreshes will *always* happen in this interval.
    95  func WithRefreshInterval(d time.Duration) AutoRefreshOption {
    96  	return &autoRefreshOption{
    97  		option.New(identRefreshInterval{}, d),
    98  	}
    99  }
   100  
   101  // WithMinRefreshInterval specifies the minimum refresh interval to be used
   102  // when using AutoRefresh. This value is ONLY used if you did not specify
   103  // a user-supplied static refresh interval via `WithRefreshInterval`.
   104  //
   105  // This value is used as a fallback value when tokens are refreshed.
   106  //
   107  // When we fetch the key from a remote URL, we first look at the max-age
   108  // directive from Cache-Control response header. If this value is present,
   109  // we compare the max-age value and the value specified by this option
   110  // and take the larger one.
   111  //
   112  // Next we check for the Expires header, and similarly if the header is
   113  // present, we compare it against the value specified by this option,
   114  // and take the larger one.
   115  //
   116  // Finally, if neither of the above headers are present, we use the
   117  // value specified by this option as the next refresh timing
   118  //
   119  // If unspecified, the minimum refresh interval is 1 hour
   120  func WithMinRefreshInterval(d time.Duration) AutoRefreshOption {
   121  	return &autoRefreshOption{
   122  		option.New(identMinRefreshInterval{}, d),
   123  	}
   124  }
   125  
   126  // WithPEM specifies that the input to `Parse()` is a PEM encoded key.
   127  func WithPEM(v bool) ParseOption {
   128  	return &parseOption{
   129  		option.New(identPEM{}, v),
   130  	}
   131  }
   132  
   133  type typedFieldPair struct {
   134  	Name  string
   135  	Value interface{}
   136  }
   137  
   138  // WithTypedField allows a private field to be parsed into the object type of
   139  // your choice. It works much like the RegisterCustomField, but the effect
   140  // is only applicable to the jwt.Parse function call which receives this option.
   141  //
   142  // While this can be extremely useful, this option should be used with caution:
   143  // There are many caveats that your entire team/user-base needs to be aware of,
   144  // and therefore in general its use is discouraged. Only use it when you know
   145  // what you are doing, and you document its use clearly for others.
   146  //
   147  // First and foremost, this is a "per-object" option. Meaning that given the same
   148  // serialized format, it is possible to generate two objects whose internal
   149  // representations may differ. That is, if you parse one _WITH_ the option,
   150  // and the other _WITHOUT_, their internal representation may completely differ.
   151  // This could potentially lead to problems.
   152  //
   153  // Second, specifying this option will slightly slow down the decoding process
   154  // as it needs to consult multiple definitions sources (global and local), so
   155  // be careful if you are decoding a large number of tokens, as the effects will stack up.
   156  func WithTypedField(name string, object interface{}) ParseOption {
   157  	return &parseOption{
   158  		option.New(identTypedField{},
   159  			typedFieldPair{Name: name, Value: object},
   160  		),
   161  	}
   162  }
   163  
   164  // This option is only available for internal code. Users don't get to play with it
   165  func withLocalRegistry(r *json.Registry) ParseOption {
   166  	return &parseOption{option.New(identLocalRegistry{}, r)}
   167  }
   168  
   169  // WithFetchWhitelist specifies the Whitelist object to use when
   170  // fetching JWKs from a remote source. This option can be passed
   171  // to both `jwk.Fetch()`, `jwk.NewAutoRefresh()`, and `(*jwk.AutoRefresh).Configure()`
   172  func WithFetchWhitelist(w Whitelist) FetchOption {
   173  	return &fetchOption{option.New(identFetchWhitelist{}, w)}
   174  }
   175  
   176  // WithIgnoreParseError is only applicable when used with `jwk.Parse()`
   177  // (i.e. to parse JWK sets). If passed to `jwk.ParseKey()`, the function
   178  // will return an error no matter what the input is.
   179  //
   180  // DO NOT USE WITHOUT EXHAUSTING ALL OTHER ROUTES FIRST.
   181  //
   182  // The option specifies that errors found during parsing of individual
   183  // keys are ignored. For example, if you had keys A, B, C where B is
   184  // invalid (e.g. it does not contain the required fields), then the
   185  // resulting JWKS will contain keys A and C only.
   186  //
   187  // This options exists as an escape hatch for those times when a
   188  // key in a JWKS that is irrelevant for your use case is causing
   189  // your JWKS parsing to fail, and you want to get to the rest of the
   190  // keys in the JWKS.
   191  //
   192  // Again, DO NOT USE unless you have exhausted all other routes.
   193  // When you use this option, you will not be able to tell if you are
   194  // using a faulty JWKS, except for when there are JSON syntax errors.
   195  func WithIgnoreParseError(b bool) ParseOption {
   196  	return &parseOption{option.New(identIgnoreParseError{}, b)}
   197  }
   198  

View as plain text