options.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. package jwt
  2. import (
  3. "context"
  4. "net/http"
  5. "time"
  6. "github.com/lestrrat-go/backoff/v2"
  7. "github.com/lestrrat-go/jwx/jwa"
  8. "github.com/lestrrat-go/jwx/jwe"
  9. "github.com/lestrrat-go/jwx/jwk"
  10. "github.com/lestrrat-go/jwx/jws"
  11. "github.com/lestrrat-go/option"
  12. )
  13. type Option = option.Interface
  14. // GlobalOption describes an Option that can be passed to `Settings()`.
  15. type GlobalOption interface {
  16. Option
  17. globalOption()
  18. }
  19. type globalOption struct {
  20. Option
  21. }
  22. func (*globalOption) globalOption() {}
  23. // ParseRequestOption describes an Option that can be passed to `ParseRequest()`.
  24. type ParseRequestOption interface {
  25. ParseOption
  26. httpParseOption()
  27. }
  28. type httpParseOption struct {
  29. ParseOption
  30. }
  31. func (*httpParseOption) httpParseOption() {}
  32. // ParseOption describes an Option that can be passed to `Parse()`.
  33. // ParseOption also implements ReadFileOption, therefore it may be
  34. // safely pass them to `jwt.ReadFile()`
  35. type ParseOption interface {
  36. ReadFileOption
  37. parseOption()
  38. }
  39. type parseOption struct {
  40. Option
  41. }
  42. func newParseOption(n interface{}, v interface{}) ParseOption {
  43. return &parseOption{option.New(n, v)}
  44. }
  45. func (*parseOption) parseOption() {}
  46. func (*parseOption) readFileOption() {}
  47. // SignOption describes an Option that can be passed to Sign() or
  48. // (jwt.Serializer).Sign
  49. type SignOption interface {
  50. Option
  51. signOption()
  52. }
  53. type signOption struct {
  54. Option
  55. }
  56. func newSignOption(n interface{}, v interface{}) SignOption {
  57. return &signOption{option.New(n, v)}
  58. }
  59. func (*signOption) signOption() {}
  60. // EncryptOption describes an Option that can be passed to Encrypt() or
  61. // (jwt.Serializer).Encrypt
  62. type EncryptOption interface {
  63. Option
  64. encryptOption()
  65. }
  66. type encryptOption struct {
  67. Option
  68. }
  69. func newEncryptOption(n interface{}, v interface{}) EncryptOption {
  70. return &encryptOption{option.New(n, v)}
  71. }
  72. func (*encryptOption) encryptOption() {}
  73. // ValidateOption describes an Option that can be passed to Validate().
  74. // ValidateOption also implements ParseOption, therefore it may be
  75. // safely passed to `Parse()` (and thus `jwt.ReadFile()`)
  76. type ValidateOption interface {
  77. ParseOption
  78. validateOption()
  79. }
  80. type validateOption struct {
  81. ParseOption
  82. }
  83. func newValidateOption(n interface{}, v interface{}) ValidateOption {
  84. return &validateOption{newParseOption(n, v)}
  85. }
  86. func (*validateOption) validateOption() {}
  87. type identAcceptableSkew struct{}
  88. type identClock struct{}
  89. type identContext struct{}
  90. type identDecrypt struct{}
  91. type identDefault struct{}
  92. type identFlattenAudience struct{}
  93. type identInferAlgorithmFromKey struct{}
  94. type identJweHeaders struct{}
  95. type identJwsHeaders struct{}
  96. type identKeySet struct{}
  97. type identKeySetProvider struct{}
  98. type identPedantic struct{}
  99. type identValidator struct{}
  100. type identToken struct{}
  101. type identTypedClaim struct{}
  102. type identValidate struct{}
  103. type identVerify struct{}
  104. type identVerifyAuto struct{}
  105. type identFetchBackoff struct{}
  106. type identFetchWhitelist struct{}
  107. type identHTTPClient struct{}
  108. type identJWKSetFetcher struct{}
  109. type identHeaderKey struct{}
  110. type identFormKey struct{}
  111. type VerifyParameters interface {
  112. Algorithm() jwa.SignatureAlgorithm
  113. Key() interface{}
  114. }
  115. type verifyParams struct {
  116. alg jwa.SignatureAlgorithm
  117. key interface{}
  118. }
  119. func (p *verifyParams) Algorithm() jwa.SignatureAlgorithm {
  120. return p.alg
  121. }
  122. func (p *verifyParams) Key() interface{} {
  123. return p.key
  124. }
  125. // WithVerify forces the Parse method to verify the JWT message
  126. // using the given key. XXX Should have been named something like
  127. // WithVerificationKey
  128. func WithVerify(alg jwa.SignatureAlgorithm, key interface{}) ParseOption {
  129. return newParseOption(identVerify{}, &verifyParams{
  130. alg: alg,
  131. key: key,
  132. })
  133. }
  134. // WithKeySet forces the Parse method to verify the JWT message
  135. // using one of the keys in the given key set.
  136. //
  137. // The key and the JWT MUST have a proper `kid` field set.
  138. // The key to use for signature verification is chosen by matching
  139. // the Key ID of the JWT and the ID of the given key set.
  140. //
  141. // When using this option, keys MUST have a proper 'alg' field
  142. // set. This is because we need to know the exact algorithm that
  143. // you (the user) wants to use to verify the token. We do NOT
  144. // trust the token's headers, because they can easily be tampered with.
  145. //
  146. // However, there _is_ a workaround if you do understand the risks
  147. // of allowing a library to automatically choose a signature verification strategy,
  148. // and you do not mind the verification process having to possibly
  149. // attempt using multiple times before succeeding to verify. See
  150. // `jwt.InferAlgorithmFromKey` option
  151. //
  152. // If you have only one key in the set, and are sure you want to
  153. // use that key, you can use the `jwt.WithDefaultKey` option.
  154. //
  155. // If provided with WithKeySetProvider(), this option takes precedence.
  156. func WithKeySet(set jwk.Set) ParseOption {
  157. return newParseOption(identKeySet{}, set)
  158. }
  159. // UseDefaultKey is used in conjunction with the option WithKeySet
  160. // to instruct the Parse method to default to the single key in a key
  161. // set when no Key ID is included in the JWT. If the key set contains
  162. // multiple keys then the default behavior is unchanged -- that is,
  163. // the since we can't determine the key to use, it returns an error.
  164. func UseDefaultKey(value bool) ParseOption {
  165. return newParseOption(identDefault{}, value)
  166. }
  167. // WithToken specifies the token instance that is used when parsing
  168. // JWT tokens.
  169. func WithToken(t Token) ParseOption {
  170. return newParseOption(identToken{}, t)
  171. }
  172. // WithHeaders is passed to `jwt.Sign()` function, to allow specifying arbitrary
  173. // header values to be included in the header section of the jws message
  174. //
  175. // This option will be deprecated in the next major version. Use
  176. // jwt.WithJwsHeaders() instead.
  177. func WithHeaders(hdrs jws.Headers) SignOption {
  178. return WithJwsHeaders(hdrs)
  179. }
  180. // WithJwsHeaders is passed to `jwt.Sign()` function or
  181. // "jwt.Serializer".Sign() method, to allow specifying arbitrary
  182. // header values to be included in the header section of the JWE message
  183. func WithJwsHeaders(hdrs jws.Headers) SignOption {
  184. return newSignOption(identJwsHeaders{}, hdrs)
  185. }
  186. // WithJweHeaders is passed to "jwt.Serializer".Encrypt() method to allow
  187. // specifying arbitrary header values to be included in the protected header
  188. // of the JWE message
  189. func WithJweHeaders(hdrs jwe.Headers) EncryptOption {
  190. return newEncryptOption(identJweHeaders{}, hdrs)
  191. }
  192. // WithValidate is passed to `Parse()` method to denote that the
  193. // validation of the JWT token should be performed after a successful
  194. // parsing of the incoming payload.
  195. func WithValidate(b bool) ParseOption {
  196. return newParseOption(identValidate{}, b)
  197. }
  198. // WithClock specifies the `Clock` to be used when verifying
  199. // claims exp and nbf.
  200. func WithClock(c Clock) ValidateOption {
  201. return newValidateOption(identClock{}, c)
  202. }
  203. // WithAcceptableSkew specifies the duration in which exp and nbf
  204. // claims may differ by. This value should be positive
  205. func WithAcceptableSkew(dur time.Duration) ValidateOption {
  206. return newValidateOption(identAcceptableSkew{}, dur)
  207. }
  208. // WithIssuer specifies that expected issuer value. If not specified,
  209. // the value of issuer is not verified at all.
  210. func WithIssuer(s string) ValidateOption {
  211. return WithValidator(ClaimValueIs(IssuerKey, s))
  212. }
  213. // WithSubject specifies that expected subject value. If not specified,
  214. // the value of subject is not verified at all.
  215. func WithSubject(s string) ValidateOption {
  216. return WithValidator(ClaimValueIs(SubjectKey, s))
  217. }
  218. // WithJwtID specifies that expected jti value. If not specified,
  219. // the value of jti is not verified at all.
  220. func WithJwtID(s string) ValidateOption {
  221. return WithValidator(ClaimValueIs(JwtIDKey, s))
  222. }
  223. // WithAudience specifies that expected audience value.
  224. // `Validate()` will return true if one of the values in the `aud` element
  225. // matches this value. If not specified, the value of issuer is not
  226. // verified at all.
  227. func WithAudience(s string) ValidateOption {
  228. return WithValidator(ClaimContainsString(AudienceKey, s))
  229. }
  230. // WithClaimValue specifies the expected value for a given claim
  231. func WithClaimValue(name string, v interface{}) ValidateOption {
  232. return WithValidator(ClaimValueIs(name, v))
  233. }
  234. // WithHeaderKey is used to specify header keys to search for tokens.
  235. //
  236. // While the type system allows this option to be passed to jwt.Parse() directly,
  237. // doing so will have no effect. Only use it for HTTP request parsing functions
  238. func WithHeaderKey(v string) ParseRequestOption {
  239. return &httpParseOption{newParseOption(identHeaderKey{}, v)}
  240. }
  241. // WithFormKey is used to specify header keys to search for tokens.
  242. //
  243. // While the type system allows this option to be passed to jwt.Parse() directly,
  244. // doing so will have no effect. Only use it for HTTP request parsing functions
  245. func WithFormKey(v string) ParseRequestOption {
  246. return &httpParseOption{newParseOption(identFormKey{}, v)}
  247. }
  248. // WithFlattenAudience specifies if the "aud" claim should be flattened
  249. // to a single string upon the token being serialized to JSON.
  250. //
  251. // This is sometimes important when a JWT consumer does not understand that
  252. // the "aud" claim can actually take the form of an array of strings.
  253. //
  254. // The default value is `false`, which means that "aud" claims are always
  255. // rendered as a arrays of strings. This setting has a global effect,
  256. // and will change the behavior for all JWT serialization.
  257. func WithFlattenAudience(v bool) GlobalOption {
  258. return &globalOption{option.New(identFlattenAudience{}, v)}
  259. }
  260. type claimPair struct {
  261. Name string
  262. Value interface{}
  263. }
  264. // WithTypedClaim allows a private claim to be parsed into the object type of
  265. // your choice. It works much like the RegisterCustomField, but the effect
  266. // is only applicable to the jwt.Parse function call which receives this option.
  267. //
  268. // While this can be extremely useful, this option should be used with caution:
  269. // There are many caveats that your entire team/user-base needs to be aware of,
  270. // and therefore in general its use is discouraged. Only use it when you know
  271. // what you are doing, and you document its use clearly for others.
  272. //
  273. // First and foremost, this is a "per-object" option. Meaning that given the same
  274. // serialized format, it is possible to generate two objects whose internal
  275. // representations may differ. That is, if you parse one _WITH_ the option,
  276. // and the other _WITHOUT_, their internal representation may completely differ.
  277. // This could potentially lead to problems.
  278. //
  279. // Second, specifying this option will slightly slow down the decoding process
  280. // as it needs to consult multiple definitions sources (global and local), so
  281. // be careful if you are decoding a large number of tokens, as the effects will stack up.
  282. //
  283. // Finally, this option will also NOT work unless the tokens themselves support such
  284. // parsing mechanism. For example, while tokens obtained from `jwt.New()` and
  285. // `openid.New()` will respect this option, if you provide your own custom
  286. // token type, it will need to implement the TokenWithDecodeCtx interface.
  287. func WithTypedClaim(name string, object interface{}) ParseOption {
  288. return newParseOption(identTypedClaim{}, claimPair{Name: name, Value: object})
  289. }
  290. // WithRequiredClaim specifies that the claim identified the given name
  291. // must exist in the token. Only the existence of the claim is checked:
  292. // the actual value associated with that field is not checked.
  293. func WithRequiredClaim(name string) ValidateOption {
  294. return WithValidator(IsRequired(name))
  295. }
  296. // WithMaxDelta specifies that given two claims `c1` and `c2` that represent time, the difference in
  297. // time.Duration must be less than equal to the value specified by `d`. If `c1` or `c2` is the
  298. // empty string, the current time (as computed by `time.Now` or the object passed via
  299. // `WithClock()`) is used for the comparison.
  300. //
  301. // `c1` and `c2` are also assumed to be required, therefore not providing either claim in the
  302. // token will result in an error.
  303. //
  304. // Because there is no way of reliably knowing how to parse private claims, we currently only
  305. // support `iat`, `exp`, and `nbf` claims.
  306. //
  307. // If the empty string is passed to c1 or c2, then the current time (as calculated by time.Now() or
  308. // the clock object provided via WithClock()) is used.
  309. //
  310. // For example, in order to specify that `exp` - `iat` should be less than 10*time.Second, you would write
  311. //
  312. // jwt.Validate(token, jwt.WithMaxDelta(10*time.Second, jwt.ExpirationKey, jwt.IssuedAtKey))
  313. //
  314. // If AcceptableSkew of 2 second is specified, the above will return valid for any value of
  315. // `exp` - `iat` between 8 (10-2) and 12 (10+2).
  316. func WithMaxDelta(dur time.Duration, c1, c2 string) ValidateOption {
  317. return WithValidator(MaxDeltaIs(c1, c2, dur))
  318. }
  319. // WithMinDelta is almost exactly the same as WithMaxDelta, but force validation to fail if
  320. // the difference between time claims are less than dur.
  321. //
  322. // For example, in order to specify that `exp` - `iat` should be greater than 10*time.Second, you would write
  323. //
  324. // jwt.Validate(token, jwt.WithMinDelta(10*time.Second, jwt.ExpirationKey, jwt.IssuedAtKey))
  325. //
  326. // The validation would fail if the difference is less than 10 seconds.
  327. //
  328. func WithMinDelta(dur time.Duration, c1, c2 string) ValidateOption {
  329. return WithValidator(MinDeltaIs(c1, c2, dur))
  330. }
  331. // WithValidator validates the token with the given Validator.
  332. //
  333. // For example, in order to validate tokens that are only valid during August, you would write
  334. //
  335. // validator := jwt.ValidatorFunc(func(_ context.Context, t jwt.Token) error {
  336. // if time.Now().Month() != 8 {
  337. // return fmt.Errorf(`tokens are only valid during August!`)
  338. // }
  339. // return nil
  340. // })
  341. // err := jwt.Validate(token, jwt.WithValidator(validator))
  342. //
  343. func WithValidator(v Validator) ValidateOption {
  344. return newValidateOption(identValidator{}, v)
  345. }
  346. type decryptParams struct {
  347. alg jwa.KeyEncryptionAlgorithm
  348. key interface{}
  349. }
  350. type DecryptParameters interface {
  351. Algorithm() jwa.KeyEncryptionAlgorithm
  352. Key() interface{}
  353. }
  354. func (dp *decryptParams) Algorithm() jwa.KeyEncryptionAlgorithm {
  355. return dp.alg
  356. }
  357. func (dp *decryptParams) Key() interface{} {
  358. return dp.key
  359. }
  360. // WithDecrypt allows users to specify parameters for decryption using
  361. // `jwe.Decrypt`. You must specify this if your JWT is encrypted.
  362. func WithDecrypt(alg jwa.KeyEncryptionAlgorithm, key interface{}) ParseOption {
  363. return newParseOption(identDecrypt{}, &decryptParams{
  364. alg: alg,
  365. key: key,
  366. })
  367. }
  368. // WithPedantic enables pedantic mode for parsing JWTs. Currently this only
  369. // applies to checking for the correct `typ` and/or `cty` when necessary.
  370. func WithPedantic(v bool) ParseOption {
  371. return newParseOption(identPedantic{}, v)
  372. }
  373. // InferAlgorithmFromKey allows jwt.Parse to guess the signature algorithm
  374. // passed to `jws.Verify()`, in case the key you provided does not have a proper `alg` header.
  375. //
  376. // Compared to providing explicit `alg` from the key this is slower, and in
  377. // case our heuristics are wrong or outdated, may fail to verify the token.
  378. // Also, automatic detection of signature verification methods are always
  379. // more vulnerable for potential attack vectors.
  380. //
  381. // It is highly recommended that you fix your key to contain a proper `alg`
  382. // header field instead of resorting to using this option, but sometimes
  383. // it just needs to happen.
  384. //
  385. // Your JWT still need to have an `alg` field, and it must match one of the
  386. // candidates that we produce for your key
  387. func InferAlgorithmFromKey(v bool) ParseOption {
  388. return newParseOption(identInferAlgorithmFromKey{}, v)
  389. }
  390. // KeySetProvider is an interface for objects that can choose the appropriate
  391. // jwk.Set to be used when verifying JWTs
  392. type KeySetProvider interface {
  393. // KeySetFrom returns the jwk.Set to be used to verify the token.
  394. // Keep in mind that the token at the point when the method is called is NOT VERIFIED.
  395. // DO NOT trust the contents of the Token too much. For example, do not take the
  396. // hint as to which signature algorithm to use from the token itself.
  397. KeySetFrom(Token) (jwk.Set, error)
  398. }
  399. // KeySetProviderFunc is an implementation of KeySetProvider that is based
  400. // on a function.
  401. type KeySetProviderFunc func(Token) (jwk.Set, error)
  402. func (fn KeySetProviderFunc) KeySetFrom(t Token) (jwk.Set, error) {
  403. return fn(t)
  404. }
  405. // WithKeySetProvider allows users to specify an object to choose which
  406. // jwk.Set to use for verification.
  407. //
  408. // If provided with WithKeySet(), WithKeySet() option takes precedence.
  409. func WithKeySetProvider(p KeySetProvider) ParseOption {
  410. return newParseOption(identKeySetProvider{}, p)
  411. }
  412. // WithContext allows you to specify a context.Context object to be used
  413. // with `jwt.Validate()` option.
  414. //
  415. // Please be aware that in the next major release of this library,
  416. // `jwt.Validate()`'s signature will change to include an explicit
  417. // `context.Context` object.
  418. func WithContext(ctx context.Context) ValidateOption {
  419. return newValidateOption(identContext{}, ctx)
  420. }
  421. // WithVerifyAuto specifies that the JWS verification should be performed
  422. // using `jws.VerifyAuto()`, which in turn attempts to verify the message
  423. // using values that are stored within the JWS message.
  424. //
  425. // Only passing this option to `jwt.Parse()` will not result in a successful
  426. // verification. Please make sure to carefully read the documentation in
  427. // `jws.VerifyAuto()`, and provide the necessary Whitelist object via
  428. // `jwt.WithFetchWhitelist()`
  429. //
  430. // You might also consider using a backoff policy by using `jwt.WithFetchBackoff()`
  431. // to control the number of requests being made.
  432. func WithVerifyAuto(v bool) ParseOption {
  433. return newParseOption(identVerifyAuto{}, v)
  434. }
  435. // WithFetchWhitelist specifies the `jwk.Whitelist` object that should be
  436. // passed to `jws.VerifyAuto()`, which in turn will be passed to `jwk.Fetch()`
  437. //
  438. // This is a wrapper over `jws.WithFetchWhitelist()` that can be passed
  439. // to `jwt.Parse()`, and will be ignored if you spcify `jws.WithJWKSetFetcher()`
  440. func WithFetchWhitelist(wl jwk.Whitelist) ParseOption {
  441. return newParseOption(identFetchWhitelist{}, wl)
  442. }
  443. // WithHTTPClient specifies the `*http.Client` object that should be
  444. // passed to `jws.VerifyAuto()`, which in turn will be passed to `jwk.Fetch()`
  445. //
  446. // This is a wrapper over `jws.WithHTTPClient()` that can be passed
  447. // to `jwt.Parse()`, and will be ignored if you spcify `jws.WithJWKSetFetcher()`
  448. func WithHTTPClient(httpcl *http.Client) ParseOption {
  449. return newParseOption(identHTTPClient{}, httpcl)
  450. }
  451. // WithFetchBackoff specifies the `backoff.Policy` object that should be
  452. // passed to `jws.VerifyAuto()`, which in turn will be passed to `jwk.Fetch()`
  453. //
  454. // This is a wrapper over `jws.WithFetchBackoff()` that can be passed
  455. // to `jwt.Parse()`, and will be ignored if you spcify `jws.WithJWKSetFetcher()`
  456. func WithFetchBackoff(b backoff.Policy) ParseOption {
  457. return newParseOption(identFetchBackoff{}, b)
  458. }
  459. // WithJWKSetFetcher specifies the `jws.JWKSetFetcher` object that should be
  460. // passed to `jws.VerifyAuto()`
  461. //
  462. // This is a wrapper over `jws.WithJWKSetFetcher()` that can be passed
  463. // to `jwt.Parse()`.
  464. func WithJWKSetFetcher(f jws.JWKSetFetcher) ParseOption {
  465. return newParseOption(identJWKSetFetcher{}, f)
  466. }