Closes#938.
* Fix compression being omitted for JWEs with arbitrary content
The JWE content was compressed only when claims was used as payload, but
when using arbitrary content, the compression was omitted, while keeping
the "zip" header field, leading to decompression failing.
* Refactor duplicate payload -> input stream logic from sign()/encrypt()
* Preserve the content name
* Fix name for JWE payload
* Extended the pre-existing check for SUN PKCS11 generic secret to allow `SecretKey`s with `getAlgorithm()` names starting with `Generic` (e.g. `GenericSecret` and `Generic Secret`) as valid keys for `HmacSHA*` algorithm name checks in `DefaultMacAlgorithm`. This matches at least with the Sun PKCS11 and AWS CloudHSM JCE providers, but likely others as well.
* Ensured `NestedCollection`s do not need their `.and()` method called to apply collection changes. Instead, changes are applied immediately as they occur (via `.add`, `.remove`, etc), and `.and()` is now purely for returning to the parent builder if necessary/desired.
* Updated associated JavaDoc with code examples to make the `.and()` method's purpose a little clearer.
* Updated CHANGELOG.md
Closes#916
Released 0.12.4, with the following additional changes:
- Added 0.12.4 release version references
- Added CI 'workflow_dispatch' event trigger
- Changed git url from ssh to https
Ensured there is an upper bound (maximum) iterations enforced for PBES2 decryption to help mitigate potential DoS attacks. Many thanks to Jingcheng Yang and Jianjun Chen from Sichuan University and Zhongguancun Lab for their work on this!
- Ensured Secret JWK 'k' byte arrays for HMAC-SHA algorithms can be larger than the identified HS* algorithm. This is allowed per https://datatracker.ietf.org/doc/html/rfc7518#section-3.2: "A key of the same size as the hash output ... _or larger_ MUST be used with this algorithm"
- Ensured that, when using the JwkBuilder, Secret JWK 'alg' values would automatically be set to 'HS256', 'HS384', or 'HS512' if the specified Java SecretKey algorithm name equals a JCA standard name (HmacSHA256, HmacSHA384, etc) or JCA standard HMAC-SHA OID.
- Updated CHANGELOG.md accordingly.
Fixes#905
All of Stormpath.com consistently responds with 404 ATM, therefore this commit replaces the links with archive.org versions that will hopefully stay available for good.
Blend of pre-0.11.0 behavior that cached implementation instances and post-0.11.0 behavior using the JDK ServiceLoader to find/create instances of an SPI interface. This change:
- Reinstates the <= 0.10.x behavior of caching application singleton service implementation instances in a thread-safe reference (previously an AtomicReference, but in this change, a ConcurrentMap). If an app singleton instance is cached and found, it is returned to be (re)used immediately when requested. This is ok for JJWT's purposes because all service implementations instances must be thread-safe application singletons by API contract/design, so caching them for repeated use is fine.
- Ensures that only if a service implementation instance is not in the app singleton cache, a new instance is located/created using a new JDK ServiceLoader instance, which doesn't require thread-safe considerations since it is used only in a single-threaded model for the short time it is used to discover a service implementation. This PR/change removes the post-0.11.0 concurrent cache of ServiceLoader instances since they themselves are not designed to be thread-safe.
- Ensures that if a ServiceLoader discovers an implementation and returns a new instance, that instance is then cached as an application singleton in the aforementioned ConcurrentMap for continued reuse.
- Renames Services#loadFirst to Services#get to more accurately reflect calling expectations: The fact that any 'loading' via the ServiceLoader may occur is not important for Services callers, and the previous method name was unnecessarily exposing internal implementation concepts. This is safe to do in a point release (0.12.3 -> 0.12.4) because the Services class and its methods, while public, are in the `impl` module, only to be used internally for JJWT's purpose and never intended to be used by application developers.
- Updates all test methods to use the renamed method accordingly.
Fixes#873
* Version reference changes in preparation for the 0.12.3 release (#863)
* [maven-release-plugin] prepare release 0.12.3
* [maven-release-plugin] prepare for next development iteration
* Closes#854.
- Replaced `ByteArrayInputStream` reflection with new `BytesInputStream` implementation. The reflection is what required `--add-opens java.base/java.io=jjwt.api` on JDK 17+.
- Refactored `KeysBridge` to perform our own key length logic instead of delegating to `sun.security.util.KeyUtil`. The reflection is what required `--add-opens java.base/sun.security.util=jjwt.api` on JDK 17+
- Removed `AddOpens.java` due to above refactoring (no longer needed).
- Returned a test-only `--add-opens` for `sun.security.util` for 3 test cases (added to `test.addOpens` maven property)
- enabled reflective access to `java.io.ByteArrayInputStream` and `sun.misc.security.KeyUtil` on JDK 17+
- Minor refactor to ServicesTest to avoid the need for PowerMock
* replaced JJWT_RELEASE_VERSION placeholders with 0.12.0
* [maven-release-plugin] prepare release 0.12.0
* [maven-release-plugin] prepare for next development iteration
* Closes#834
- Deprecated JwtParser parseContentJwt, parseClaimsJwt, parseContentJws and parseClaimsJws in favor of parseUnprotectedContent, parseUnprotectedClaims, parseSignedContent, and parseSignedClaims
- Renamed the not-yet-released JwtParser parseContentJwe and parseClaimsJwe to parseEncryptedContent and parseEncryptedClaims
- Renamed the not-yet-released JwtParser overloaded unencoded payload parseContentJws and parseClaimsJws methods to parseSignedContent and parseSignedClaims
- Deprecated JwtHandler and JwtHandlerAdapter in favor of JwtVisitor and SupportedJwtVisitor
Closes#328
- Ensured Parser worked with CharSequence, InputStream and Reader, not just String
- Changed Deserializer#deserialize(InputStream) to deserialize(Reader)
- JwtParser now extends from Parser to support these additional methods.
- Changed remaining JwtParser.parse* methods to accept CharSequence arguments instead of String args.
- Renamed X509Mutator#x509CertificateSha1Thumbprint to x509Sha1Thumbprint
- Renamed X509Mutator#x509CertificateSha256Thumbprint to x509Sha256Thumbprint
- Renamed X509Builder#withX509Sha1Thumbprint to x509Sha1Thumbprint
- Renamed X509Builder#withX509Sha256Thumbprint to x509Sha256Thumbprint
- Renamed X509Builder#x509CertificateChain to x509Chain
- Renamed X509Accessor#getX509CertificateChain to getX509Chain
- Renamed X509Accessor#getX509CertificateSha1Thumbprint getX509Sha1Thumbprint
- Renamed X509Accessor#getX509CertificateSha256Thumbprint to getX509Sha256Thumbprint
- Renamed JwtParserBuilder#enableUnsecured() to unsecured()
- Renamed JwtParserBuilder#enableUnsecuredDecompression() to unsecuredDecompression()
- Renamed KeyOperationPolicyBuilder#allowUnrelated(boolean) to unrelated() (removed boolean argument also to be consistent with JwtParserBuilder#unsecured())
Closes#837
Replaced raw `String` and `byte[]` usages with `CharSequence`, `InputStream`/`OutputStream` and `CharBuffer`/`ByteBuffer` concepts where possible to eliminate unnecessary creation of intermediate byte arrays and/or temporary Strings.
-----
- Changed TokenizedJwt and TokenizedJwe interfaces and implementations to return CharSequences instead of Strings to avoid creating new Strings on the heap
- Changed internal Base64 implementation to work with a CharSequence instead of a raw char[] to reduce need to create new arrays on the heap
- Changed Base64Decoder generics signature from Decoder<String,byte[]> to Decoder<CharSequence,byte[]>
- Decoders.BASE64 and Decoders.BASE64URL now reflect Decoder<CharSequence,byte[]>
- Changed Strings#utf8 implementation to accept a CharSequence instead of a String
- Added new Strings#wrap to wrap a CharSequence into a CharBuffer if necessary
- Renamed not-yet-released JwtBuilder#serializer method with JwtBuilder#json
- Renamed not-yet-released JwtParserBuilder#deserializer method with JwtParserBuilder#json
-----
- Moved JwtDeserializer from io.jsonwebtoken.impl to io.jsonwebtoken.impl.io package, created two new subclass implementations for use with Jwks and JwkSets
- Renamed JwtDeserializer to JsonObjectDeserializer that defaults to throwing MalformedJwtException. Added two subclasses, JwkDeserializer and JwkSetDeserializer that throws JWK and JWK Set-specific exceptions.
-----
Changed ParserBuilder#deserializer method name to ParserBuilder#jsonReader
-----
Removed all usages of Serializer#serialize and Deserializer#deserialize except for deprecated implementations. All other usages now use InputStream/OutputStream concepts
-----
Added Jwks#json and Jwks#UNSAFE_JSON for assistance in serializing JWKs to JSON (test cases, README examples, etc)
-----
- Ensured Encoder and CompressionAlgorithm supported streams instead of just byte arrays
- Copied over necessary (Apache-licensed) code from Apache commons-codec to obtain Base64OutputStream and Base64InputStream capability for efficient encoding during compact JWT creation. Hopefully this is temporary and we can strip out most if not all of this and modify our existing Base64.java class for simpler support since we have many less use cases than what commons-codec supports. All implementations are now in the `impl` module only.
-----
Converted all DigestAlgorithms to utilize an InputStream for data instead of byte[]
-----
- Added JwtBuilder InputStream payload support: added JwtBuilder#content(InputStream), JwtBuilder#content(InputStream, String contentType), JwtBuilder#content(String, String contentType)
- Added CountingInputStream as a way to check and assert that b64/unencoded payload InputStreams cannot be empty.
------
Renamed Encoder/Decoder and CompressionAlgorithm 'wrap' methods to encode/decode/compress/decompress for better readability and to make clearer the intent of the method. Also to avoid name/text/search collisions with 'wrap' references.
-----
Renamed new JwtBuilder#encoder and JwtParserBuilder#decoder methods to JwtBuilder#b64Url and JwtParserBuilder#b64Url for shorter method chains
-----
- Updated AeadAlgorithm and its AeadRequest/AeadResult concepts to utilize Input/Output Streams
- Renamed InitializationVectorSupplier to IvSupplier (was verbose, and it's a new interface, and it's not commonly referenced in the API, so the extra verbosity isn't needed)
* Update groovy patch version to support Java 21.
NOTE: This adds a Maven profile that ups the source/target version to Java 8, but ONLY when building with 21+
The first ServiceLoaders found when looking up a class will be cached. This cache can be reset by calling `Services.reload()`, to help
facilitate testing or instances where a classpaths are dynamically changed at runtime.
Fixes: #752
Closes#515
[RFC 7797)(https://www.rfc-editor.org/rfc/rfc7797.html) support.
JwsHeader:
- Added new JwtHeader#isPayloadEncoded() to check for `b64` in crit values and as parameter value.
JwtBuilder:
- Added new #content(String) method for non-detached unencoded payloads
- Added new #encodePayload(boolean) method to disable payload Base64URL-encoding
JwtParserBuilder:
- Added new #critical(String) convenience method to append to the crit set
JwtParser:
- Added new #parseContentJws(String, byte[]) method to allow supplying detached payloads for signature verification at parse time
- Added new #parseClaimsJws(String, byte[]) method to allow supplying detached serialized JSON claims for signature verification at parse time
- Added all backing implementations and test cases to 100% coverage
- Added RFC7797Test class for bulk of this RFC's tests so they don't get 'lost' in the already-too-large JwtsTest class
- README.md documentation added in JWS section
- CHANGELOG.md updated