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