github.com/lestrrat-go/jwx/v2@v2.0.21/Changes-v2.md (about)

     1  # Incompatible Changes from v1 to v2
     2  
     3  These are changes that are incompatible with the v1.x.x version.
     4  
     5  * [tl;dr](#tldr) - If you don't feel like reading the details -- but you will read the details, right?
     6  * [Detailed List of Changes](#detailed-list-of-changes) - A comprehensive list of changes from v1 to v2
     7  
     8  # tl;dr
     9  
    10  ## JWT 
    11  
    12  ```go
    13  // most basic
    14  jwt.Parse(serialized, jwt.WithKey(alg, key)) // NOTE: verification and validation are ENABLED by default!
    15  jwt.Sign(token, jwt.WithKey(alg,key))
    16  
    17  // with a jwk.Set
    18  jwt.Parse(serialized, jwt.WithKeySet(set))
    19  
    20  // UseDefault/InferAlgorithm with JWKS
    21  jwt.Parse(serialized, jwt.WithKeySet(set,
    22    jws.WithUseDefault(true), jws.WithInferAlgorithm(true))
    23  
    24  // Use `jku`
    25  jwt.Parse(serialized, jwt.WithVerifyAuto(...))
    26  
    27  // Any other custom key provisioning (using functions in this
    28  // example, but can be anything that fulfills jws.KeyProvider)
    29  jwt.Parse(serialized, jwt.WithKeyProvider(jws.KeyProviderFunc(...)))
    30  ```
    31  
    32  ## JWK
    33  
    34  ```go
    35  // jwk.New() was confusing. Renamed to fit the actual implementation
    36  key, err := jwk.FromRaw(rawKey)
    37  
    38  // Algorithm() now returns jwa.KeyAlgorithm type. `jws.Sign()`
    39  // and other function that receive JWK algorithm names accept
    40  // this new type, so you can use the same key and do the following
    41  // (previosly you needed to type assert)
    42  jws.Sign(payload, jws.WithKey(key.Algorithm(), key))
    43  
    44  // If you need the specific type, type assert
    45  key.Algorithm().(jwa.SignatureAlgorithm)
    46  
    47  // jwk.AutoRefresh is no more. Use jwk.Cache
    48  cache := jwk.NewCache(ctx, options...)
    49  
    50  // Certificate chains are no longer jwk.CertificateChain type, but
    51  // *(github.com/lestrrat-go/jwx/cert).Chain
    52  cc := key.X509CertChain() // this is *cert.Chain now
    53  ```
    54  
    55  ## JWS
    56  
    57  ```go
    58  // basic
    59  jws.Sign(payload, jws.WithKey(alg, key))
    60  jws.Sign(payload, jws.WithKey(alg, key), jws.WithKey(alg, key), jws.WithJSON(true))
    61  jws.Verify(signed, jws.WithKey(alg, key))
    62  
    63  // other ways to pass the key
    64  jws.Sign(payload, jws.WithKeySet(jwks))
    65  jws.Sign(payload, jws.WithKeyProvider(kp))
    66  
    67  // retrieve the key that succeeded in verifying
    68  var keyUsed interface{}
    69  jws.Verify(signed, jws.WithKeySet(jwks), jws.WithKeyUsed(&keyUsed))
    70  ```
    71  
    72  ## JWE 
    73  
    74  ```go
    75  // basic
    76  jwe.Encrypt(payload, jwe.WithKey(alg, key)) // other defaults are infered
    77  jwe.Encrypt(payload, jwe.WithKey(alg, key), jwe.WithKey(alg, key), jwe.WithJSON(true))
    78  jwe.Decrypt(encrypted, jwe.WithKey(alg, key))
    79  
    80  // other ways to pass the key
    81  jwe.Encrypt(payload, jwe.WithKeySet(jwks))
    82  jwe.Encrypt(payload, jwe.WithKeyProvider(kp))
    83  
    84  // retrieve the key that succeeded in decrypting
    85  var keyUsed interface{}
    86  jwe.Verify(signed, jwe.WithKeySet(jwks), jwe.WithKeyUsed(&keyUsed))
    87  ```
    88  
    89  # Detailed List of Changes
    90  
    91  ## Module
    92  
    93  * Module now requires go 1.16
    94  
    95  * Use of github.com/pkg/errors is no more. If you were relying on bevaior
    96    that depends on the errors being an instance of github.com/pkg/errors
    97    then you need to change your code
    98  
    99  * File-generation tools have been moved out of internal/ directories.
   100    These files pre-dates Go modules, and they were in internal/ in order
   101    to avoid being listed in the `go doc` -- however, now that we can
   102    make them separate modules this is no longer necessary.
   103  
   104  * New package `cert` has been added to handle `x5c` certificate
   105    chains, and to work with certificates
   106      * cert.Chain to store base64 encoded ASN.1 DER format certificates
   107      * cert.EncodeBase64 to encode ASN.1 DER format certificate using base64
   108      * cert.Create to create a base64 encoded ASN.1 DER format certificates
   109      * cert.Parse to parse base64 encoded ASN.1 DER format certificates
   110  
   111  ## JWE
   112  
   113  * `jwe.Compact()`'s signature has changed to 
   114    `jwe.Compact(*jwe.Message, ...jwe.CompactOption)`
   115  
   116  * `jwe.JSON()` has been removed. You can generate JSON serialization
   117    using `jwe.Encrypt(jwe.WitJSON())` or `json.Marshal(jwe.Message)`
   118  
   119  * `(jwe.Message).Decrypt()` has been removed. Since formatting of the
   120    original serialized message matters (including whitespace), using a parsed
   121    object was inherently confusing.
   122  
   123  * `jwe.Encrypt()` can now generate JWE messages in either compact or JSON
   124    forms. By default, the compact form is used. JSON format can be
   125    enabled by using the `jwe.WithJSON` option.
   126  
   127  * `jwe.Encrypt()` can now accept multiple keys by passing multiple
   128    `jwe.WithKey()` options. This can be used with `jwe.WithJSON` to
   129    create JWE messages with multiple recipients.
   130  
   131  * `jwe.DecryptEncryptOption()` has been renamed to `jwe.EncryptDecryptOption()`.
   132    This is so that it is more uniform with `jws` equivalent of `jws.SignVerifyOption()`
   133    where the producer (`Sign`) comes before the consumer (`Verify`) in the naming
   134  
   135  * `jwe.WithCompact` and `jwe.WithJSON` options have been added
   136    to control the serialization format.
   137  
   138  * jwe.Decrypt()'s method signature has been changed to `jwt.Decrypt([]byte, ...jwe.DecryptOption) ([]byte, error)`.
   139    These options can be stacked. Therefore, you could configure the
   140    verification process to attempt a static key pair, a JWKS, and only
   141    try other forms if the first two fails, for example.
   142  
   143    - For static key pair, use `jwe.WithKey()`
   144    - For static JWKS, use `jwe.WithKeySet()` (NOTE: InferAlgorithmFromKey like in `jws` package is NOT supported)
   145    - For custom, possibly dynamic key provisioning, use `jwe.WithKeyProvider()`
   146  
   147  * jwe.Decrypter has been unexported. Users did not need this.
   148   
   149  * jwe.WithKeyProvider() has been added to specify arbitrary
   150    code to specify which keys to try.
   151  
   152  * jwe.KeyProvider interface has been added
   153  
   154  * jwe.KeyProviderFunc has been added
   155   
   156  * `WithPostParser()` has been removed. You can achieve the same effect
   157    by using `jwe.WithKeyProvider()`. Because this was the only consumer for
   158    `jwe.DecryptCtx`, this type has been removed as well.
   159  
   160  * `x5c` field type has been changed to `*cert.Chain` instead of `[]string`
   161  
   162  * Method signature for `jwe.Parse()` has been changed to include options,
   163    but options are currently not used
   164  
   165  * `jwe.ReadFile` now supports the option `jwe.WithFS` which allows you to
   166    read data from arbitrary `fs.FS` objects
   167  
   168  * jwe.WithKeyUsed has been added to allow users to retrieve
   169    the key used for decryption. This is useful in cases you provided
   170    multiple keys and you want to know which one was successful
   171  
   172  ## JWK
   173  
   174  * `jwk.New()` has been renamed to `jwk.FromRaw()`, which hopefully will
   175    make it easier for the users what the input should be.
   176  
   177  * `jwk.Set` has many interface changes:
   178    * Changed methods to match jwk.Key and its semantics:
   179      * Field is now Get() (returns values for arbitrary fields other than keys). Fetching a key is done via Key()
   180      * Remove() now removes arbitrary fields, not keys. to remove keys, use RemoveKey()
   181      * Iterate has been added to iterate through all non-key fields.
   182    * Add is now AddKey(Key) string, and returns an error when the same key is added
   183    * Get is now Key(int) (Key, bool)
   184    * Remove is now RemoveKey(Key) error
   185    * Iterate is now Keys(context.Context) KeyIterator
   186    * Clear is now Clear() error
   187  
   188  * `jwk.CachedSet` has been added. You can create a `jwk.Set` that is backed by
   189    `jwk.Cache` so you can do this:
   190  
   191  ```go
   192  cache := jkw.NewCache(ctx)
   193  cachedSet := jwk.NewCachedSet(cache, jwksURI)
   194  
   195  // cachedSet is always the refreshed, cached version from jwk.Cache
   196  jws.Verify(signed, jws.WithKeySet(cachedSet))
   197  ```
   198  
   199  * `jwk.NewRSAPRivateKey()`, `jwk.NewECDSAPrivateKey()`, etc have been removed.
   200    There is no longer any way to create concrete types of `jwk.Key` 
   201  
   202  * `jwk.Key` type no longer supports direct unmarshaling via `json.Unmarshal()`,
   203    because you can no longer instantiate concrete `jwk.Key` types. You will need to
   204    use `jwk.ParseKey()`. See the documentation for ways to parse JWKs.
   205  
   206  * `(jwk.Key).Algorithm()` is now of `jwk.KeyAlgorithm` type. This field used
   207    to be `string` and therefore could not be passed directly to `jwt.Sign()`
   208    `jws.Sign()`, `jwe.Encrypt()`, et al. This is no longer the case, and
   209    now you can pass it directly. See 
   210    https://github.com/lestrrat-go/jwx/blob/v2/docs/99-faq.md#why-is-jwkkeyalgorithm-and-jwakeyalgorithm-so-confusing
   211    for more details
   212  
   213  * `jwk.Fetcher` and `jwk.FetchFunc` has been added.
   214    They represent something that can fetch a `jwk.Set`
   215  
   216  * `jwk.CertificateChain` has been removed, use `*cert.Chain`
   217  * `x5c` field type has been changed to `*cert.Chain` instead of `[]*x509.Certificate`
   218  
   219  * `jwk.ReadFile` now supports the option `jwk.WithFS` which allows you to
   220    read data from arbitrary `fs.FS` objects
   221  
   222  * Added `jwk.PostFetcher`, `jwk.PostFetchFunc`, and `jwk.WithPostFetch` to
   223    allow users to get at the `jwk.Set` that was fetched in `jwk.Cache`.
   224    This will make it possible for users to supply extra information and edit
   225    `jwk.Set` after it has been fetched and parsed, but before it is cached.
   226    You could, for example, modify the `alg` field so that it's easier to
   227    work with when you use it in `jws.Verify` later.
   228  
   229  * Reworked `jwk.AutoRefresh` in terms of `github.com/lestrrat-go/httprc`
   230    and renamed it `jwk.Cache`.
   231  
   232    Major difference between `jwk.AutoRefresh` and `jwk.Cache` is that while
   233    former used one `time.Timer` per resource, the latter uses a static timer
   234    (based on `jwk.WithRefreshWindow()` value, default 15 minutes) that periodically
   235    refreshes all resources that were due to be refreshed within that time frame.
   236  
   237    This method may cause your updates to happen slightly later, but uses significantly
   238    less resources and is less prone to clogging.
   239  
   240  * Reimplemented `jwk.Fetch` in terms of `github.com/lestrrat-go/httprc`.
   241  
   242  * Previously `jwk.Fetch` and `jwk.AutoRefresh` respected backoff options,
   243    but this has been removed. This is to avoid unwanted clogging of the fetch workers
   244    which is the default processing mode in `github.com/lestrrat-go/httprc`.
   245  
   246    If you are using backoffs, you need to control your inputs more carefully so as to
   247    not clog your fetch queue, and therefore you should be writing custom code that
   248    suits your needs
   249  
   250  ## JWS
   251  
   252  * `jws.Sign()` can now generate JWS messages in either compact or JSON
   253    forms. By default, the compact form is used. JSON format can be
   254    enabled by using the `jws.WithJSON` option.
   255  
   256  * `jws.Sign()` can now accept multiple keys by passing multiple
   257    `jws.WithKey()` options. This can be used with `jws.WithJSON` to
   258    create JWS messages with multiple signatures.
   259  
   260  * `jws.WithCompact` and `jws.WithJSON` options have been added
   261    to control the serialization format.
   262  
   263  * jws.Verify()'s method signature has been changed to `jwt.Verify([]byte, ...jws.VerifyOption) ([]byte, error)`.
   264    These options can be stacked. Therefore, you could configure the
   265    verification process to attempt a static key pair, a JWKS, and only
   266    try other forms if the first two fails, for example.
   267   
   268    - For static key pair, use `jws.WithKey()`
   269    - For static JWKS, use `jws.WithKeySet()`
   270    - For enabling verification using `jku`, use `jws.WithVerifyAuto()`
   271    - For custom, possibly dynamic key provisioning, use `jws.WithKeyProvider()`
   272  
   273  * jws.WithVerify() has been removed.
   274  
   275  * jws.WithKey() has been added to specify an algorithm + key to
   276    verify the payload with.
   277  
   278  * jws.WithKeySet() has been added to specify a JWKS to be used for
   279    verification. By default `kid` AND `alg` must match between the signature
   280    and the key.
   281  
   282    The option can take further suboptions:
   283  
   284  ```go
   285  jws.Parse(serialized,
   286    jws.WithKeySet(set,
   287      // by default `kid` is required. set false to disable.
   288      jws.WithRequireKid(false),
   289      // optionally skip matching kid if there's exactly one key in set
   290      jws.WithUseDefault(true),
   291      // infer algorithm name from key type
   292      jws.WithInferAlgorithm(true),
   293    ),
   294  )
   295  ```
   296  
   297  * `jws.VerifuAuto` has been removed in favor of using
   298    `jws.WithVerifyAuto` option with `jws.Verify()`
   299  
   300  * `jws.WithVerifyAuto` has been added to enable verification
   301    using `jku`.
   302  
   303    The first argument must be a jwk.Fetcher object, but can be
   304    set to `nil` to use the default implementation which is `jwk.Fetch`
   305  
   306    The rest of the arguments are treated as options passed to the
   307    `(jwk.Fetcher).Fetch()` function.
   308  
   309  * Remove `jws.WithPayloadSigner()`. This should be completely repleceable
   310    using `jws.WithKey()`
   311  
   312  * jws.WithKeyProvider() has been added to specify arbitrary
   313    code to specify which keys to try.
   314  
   315  * jws.KeyProvider interface has been added
   316  
   317  * jws.KeyProviderFunc has been added
   318   
   319  * jws.WithKeyUsed has been added to allow users to retrieve
   320    the key used for verification. This is useful in cases you provided
   321    multiple keys and you want to know which one was successful
   322  
   323  * `x5c` field type has been changed to `*cert.Chain` instead of `[]string`
   324  
   325  * `jws.ReadFile` now supports the option `jws.WithFS` which allows you to
   326    read data from arbitrary `fs.FS` objects
   327  
   328  ## JWT
   329  
   330  * `jwt.Parse` now verifies the signature and validates the token
   331    by default. You must disable it explicitly using `jwt.WithValidate(false)`
   332    and/or `jwt.WithVerify(false)` if you only want to parse the JWT message.
   333  
   334    If you don't want either, a convenience function `jwt.ParseInsecure`
   335    has been added.
   336  
   337  * `jwt.Parse` can only parse raw JWT (JSON) or JWS (JSON or Compact).
   338    It no longer accepts JWE messages.
   339  
   340  * `jwt.WithDecrypt` has been removed
   341  
   342  * `jwt.WithJweHeaders` has been removed
   343  
   344  * `jwt.WithVerify()` has been renamed to `jwt.WithKey()`. The option can
   345    be used for signing, encryption, and parsing.
   346  
   347  * `jwt.Validator` has been changed to return `jwt.ValidationError`.
   348    If you provide a custom validator, you should wrap the error with
   349    `jwt.NewValidationError()`
   350  
   351  * `jwt.UseDefault()` has been removed. You should use `jws.WithUseDefault()`
   352    as a suboption in the `jwt.WithKeySet()` option.
   353  
   354  ```go
   355  jwt.Parse(serialized, jwt.WithKeySet(set, jws.WithUseDefault(true)))
   356  ```
   357  
   358  * `jwt.InferAlgorithmFromKey()` has been removed. You should use
   359    `jws.WithInferAlgorithmFromKey()` as a suboption in the `jwt.WithKeySet()` option.
   360  
   361  ```go
   362  jwt.Parse(serialized, jwt.WithKeySet(set, jws.WithInferAlgorithmFromKey(true)))
   363  ```
   364  
   365  * jwt.WithKeySetProvider has been removed. Use `jwt.WithKeyProvider()`
   366    instead. If jwt.WithKeyProvider seems a bit complicated,  use a combination of
   367    JWS parse, no-verify/validate JWT parse, and an extra JWS verify:
   368  
   369  ```go
   370  msg, _ := jws.Parse(signed)
   371  token, _ := jwt.Parse(msg.Payload(), jwt.WithVerify(false), jwt.WithValidate(false))
   372  // Get information out of token, for example, `iss`
   373  switch token.Issuer() {
   374  case ...:
   375    jws.Verify(signed, jwt.WithKey(...))
   376  }
   377  ```
   378  
   379  * `jwt.WithHeaders` and `jwt.WithJwsHeaders` have been removed.
   380    You should be able to use the new `jwt.WithKey` option to pass headers
   381  
   382  * `jwt.WithSignOption` and `jwt.WithEncryptOption` have been added as
   383    escape hatches for options that are declared in `jws` and `jwe` packages
   384    but not in `jwt`
   385  
   386  * `jwt.ReadFile` now supports the option `jwt.WithFS` which allows you to
   387    read data from arbitrary `fs.FS` objects
   388  
   389  * `jwt.Sign()` has been changed so that it works more like the new `jws.Sign()`
   390