### Example Compact JWS Source: https://github.com/jwtk/jjwt/blob/main/README.adoc An example of a final compact JSON Web Signature (JWS) string. ```text eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UifQ.1KP0SsvENi7Uz1oQc07aXTL7kpQG5jBNIybqr60AlD4 ``` -------------------------------- ### JSON Header Example Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Example of a JSON header for a JWT, specifying the signing algorithm. ```json { "alg": "HS256" } ``` -------------------------------- ### Base64 Decoding Examples Source: https://github.com/jwtk/jjwt/blob/main/README.adoc These examples demonstrate how different Base64 strings can decode to the same byte array, highlighting why simple signature edits might not fail validation. ```text dGVzdCBzdHJpbmo dGVzdCBzdHJpbmp dGVzdCBzdHJpbmq dGVzdCBzdHJpbmr ``` -------------------------------- ### Example Compact JWE Source: https://github.com/jwtk/jjwt/blob/main/README.adoc An example of a final compact JSON Web Encryption (JWE) string, which is fully encrypted and authenticated. ```text eyJhbGciOiJBMTI4S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0. 6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ. AxY8DCtDaGlsbGljb3RoZQ. KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY. U0m_YmjN04DJvceFICbCVQ ``` -------------------------------- ### Verify Maven Version Source: https://github.com/jwtk/jjwt/wiki/Home Confirm that Maven version 3.8.8 is installed and being used, as it is the last version compatible with JDK 7. ```bash $mvn -version Apache Maven 3.8.8 (4c87b05d9aedce574290d1acc98575ed5eb6cd39) ``` -------------------------------- ### Create and Parse SecretKey JWK Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Example of creating a secret JWK from a SecretKey and then parsing it back. Verifies ID and key equality, and demonstrates serialization/deserialization. ```java SecretKey key = Jwts.SIG.HS512.key().build(); // or HS384 or HS256 SecretJwk jwk = Jwks.builder().key(key).idFromThumbprint().build(); assert jwk.getId().equals(jwk.thumbprint().toString()); assert key.equals(jwk.toKey()); byte[] utf8Bytes = new JacksonSerializer().serialize(jwk); // or GsonSerializer(), etc String jwkJson = new String(utf8Bytes, StandardCharsets.UTF_8); Jwk parsed = Jwks.parser().build().parse(jwkJson); assert parsed instanceof SecretJwk; assert jwk.equals(parsed); ``` -------------------------------- ### JWT Header and Payload Initialization Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Initializes the header and payload strings for JWT creation. The header is a JSON string, and the payload is a plain text string in this example. ```groovy String header = '{"alg":"none"}' String payload = 'The true sign of intelligence is not knowledge but imagination.' ``` -------------------------------- ### Verification Key with SecretKey Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Example of how to specify a SecretKey for JWS signature verification. ```APIDOC ## Verification Key with SecretKey ### Description This demonstrates how to use a `SecretKey` to verify the signature of a JWS. ### Method N/A (SDK Operation) ### Endpoint N/A (SDK Operation) ### Parameters - **secretKey** (SecretKey) - Required - The secret key used for signing and verification. - **jwsString** (String) - Required - The JWS string to parse. ### Request Example ```java Jwts.parser() .verifyWith(secretKey) .build() .parseSignedClaims(jwsString); ``` ``` -------------------------------- ### Verification Key with PublicKey Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Example of how to specify a PublicKey for JWS signature verification when the JWS was signed with a PrivateKey. ```APIDOC ## Verification Key with PublicKey ### Description This demonstrates how to use a `PublicKey` to verify the signature of a JWS that was signed using its corresponding `PrivateKey`. ### Method N/A (SDK Operation) ### Endpoint N/A (SDK Operation) ### Parameters - **publicKey** (PublicKey) - Required - The public key corresponding to the private key used for signing. - **jwsString** (String) - Required - The JWS string to parse. ### Request Example ```java Jwts.parser() .verifyWith(publicKey) .build() .parseSignedClaims(jwsString); ``` ``` -------------------------------- ### JSON Payload Example Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Example of a JSON payload (claims) for a JWT, containing subject information. ```json { "sub": "Joe" } ``` -------------------------------- ### Example JWK Thumbprint URI String Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Illustrates the format of a JWK thumbprint's canonical URI string, which includes the URN scheme, hash algorithm identifier, and the Base64URL-encoded thumbprint digest. ```text urn:ietf:params:oauth:jwk-thumbprint:HASH_ALG_ID:BASE64URL_DIGEST ``` -------------------------------- ### Verify Zulu JDK 7 Version Source: https://github.com/jwtk/jjwt/wiki/Home Check that the installed Java version is a Zulu JDK 7 distribution, which is required for publishing to Nexus OSSRH due to TLS protocol support. ```bash openjdk version "1.7.0_342" OpenJDK Runtime Environment (Zulu 7.54.0.13-CA-macosx) (build 1.7.0_342-b01) OpenJDK 64-Bit Server VM (Zulu 7.54.0.13-CA-macosx) (build 24.342-b01, mixed mode) ``` -------------------------------- ### Set Maven Options Source: https://github.com/jwtk/jjwt/wiki/Home Configure Maven memory settings before running the release build. Ensure MAVEN_OPTS is exported in your shell. ```bash export MAVEN_OPTS="-Xmx512m -XX:MaxPermSize=128m" ``` -------------------------------- ### Run JJWT Release Build Source: https://github.com/jwtk/jjwt/wiki/Home Execute Maven commands to clean, prepare, and perform the release. Follow prompts for version numbers and SCM tags. ```bash mvn clean mvn release:clean mvn release:prepare # Choose a version number. # Choose an SCM release tag. This should be *just* the version number: 0.5, not jjwt-0.5 # Choose the new development version. If releasing 0.5, this would be 0.6-SNAPSHOT mvn release:perform ``` -------------------------------- ### Remove Whitespace and Get Bytes Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Removes unnecessary whitespace from JSON header and claims, then gets their UTF-8 byte representations. ```groovy String header = '{"alg":"HS256"}' String claims = '{"sub":"Joe"}' ``` -------------------------------- ### Verify JWS with a Secret Key Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Demonstrates how to configure the JWS parser to verify signatures using a single, static SecretKey. ```java Jwts.parser() .verifyWith(secretKey) // <---- .build() .parseSignedClaims(jwsString); ``` -------------------------------- ### Verify JWS with a Public Key Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Shows how to configure the JWS parser to verify signatures using a static PublicKey, which corresponds to a PrivateKey used for signing. ```java Jwts.parser() .verifyWith(publicKey) // <---- publicKey, not privateKey .build() .parseSignedClaims(jwsString); ``` -------------------------------- ### Create and Push Staging Branch Source: https://github.com/jwtk/jjwt/wiki/Home Create a staging branch for release changes and push it to the remote repository. ```bash git checkout master && git pull git checkout -b 0.11.4-staging git push -u origin # push the new 0.11.4-staging branch to the remote origin server (i.e. GitHub) ``` -------------------------------- ### JWK Set JSON Structure Example Source: https://github.com/jwtk/jjwt/blob/main/README.adoc A JWK Set is a JSON object with a 'keys' member, which is an array of JWK objects. It may contain other custom members. ```text { "keys": [ jwk1, jwk2, ...] } ``` -------------------------------- ### Create a JWK from a Java Key Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Create a JWK by providing a Java Key (SecretKey, PublicKey, or PrivateKey) and optionally setting metadata like a Key ID. ```java SecretKey key = getSecretKey(); // or RSA or EC PublicKey or PrivateKey SecretJwk = Jwks.builder().key(key) // (1) and (2) .id("mySecretKeyId") // (3) // ... etc ... .build(); // (4) ``` -------------------------------- ### JwkSet Interface Definition Source: https://github.com/jwtk/jjwt/wiki/JWK-scratchpad Defines the JwkSet interface for managing a collection of JWKs. Includes methods for getting and setting JWK lists and a constant for the 'keys' parameter. ```java import java.util.List; import java.util.Map; /** * A {@code JwkSet} represents a set of {@link Jwk}s. * * @param JwkSet type * @since 0.7 */ public interface JwkSet> extends Map { /** * JWK Set Keys Parameter name: the string literal keys */ public static final String KEYS = "keys"; /** * Returns a list of {@code Jwk}s. By default, the order of the JWK values within the List does not imply an * order of preference among them, although applications can choose to assign a meaning to the order * for their purposes, if desired. * * @return a list of {@code Jwk}s */ List getKeys(); /** * Sets a list of {@code Jwk}s. By default, the order of the JWK values within the List does not imply an * order of preference among them, although applications can choose to assign a meaning to the order * for their purposes, if desired. * * @param keys a list of {@code Jwk}s */ T setKeys(List keys); } ``` -------------------------------- ### Create and Parse RSA Public JWK Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Demonstrates creating an RSA Public JWK from a key pair, generating an ID from its thumbprint, serializing it, and then parsing it back. Ensure you have a JSON serializer like Jackson or Gson configured. ```java RSAPublicKey key = (RSAPublicKey)Jwts.SIG.RS512.keyPair().build().getPublic(); RsaPublicJwk jwk = Jwks.builder().key(key).idFromThumbprint().build(); assert jwk.getId().equals(jwk.thumbprint().toString()); assert key.equals(jwk.toKey()); byte[] utf8Bytes = new JacksonSerializer().serialize(jwk); // or GsonSerializer(), etc String jwkJson = new String(utf8Bytes, StandardCharsets.UTF_8); Jwk parsed = Jwks.parser().build().parse(jwkJson); assert parsed instanceof RsaPublicJwk; assert jwk.equals(parsed); ``` -------------------------------- ### Build a JWT with Header and Subject Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Constructs a JWT by setting an optional key ID in the header and the subject claim. The JWT can then be signed or encrypted and compacted into a string. ```java String jwt = Jwts.builder() // (1) .header() // (2) optional .keyId("aKeyId") .and() .subject("Bob") // (3) JSON Claims, or //.content(aByteArray, "text/plain") // any byte[] content, with media type .signWith(signingKey) // (4) if signing, or //.encryptWith(key, keyAlg, encryptionAlg) // if encrypting .compact(); // (5) ``` -------------------------------- ### Compacting JWT Header and Payload Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Concatenates the Base64URL-encoded header and payload with a period ('.') to form the compact JWT string. An empty string is appended for the signature part in this unprotected JWT example. ```groovy String compact = encodedHeader + '.' + encodedPayload + '.' ``` -------------------------------- ### Get JWK Thumbprint Canonical URI Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Retrieve the canonical URI representation of a JWK thumbprint as defined by RFC 9278. The URI includes the hash algorithm ID and the Base64URL-encoded digest. ```java URI canonicalThumbprintURI = jwk.thumbprint().toURI(); ``` -------------------------------- ### Create and Parse RSA Private JWK Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Shows how to create an RSA Private JWK, derive its public counterpart, and then serialize and parse the private JWK. Requires a JSON serializer. ```java KeyPair pair = Jwts.SIG.RS512.keyPair().build(); RSAPublicKey pubKey = (RSAPublicKey) pair.getPublic(); RSAPrivateKey privKey = (RSAPrivateKey) pair.getPrivate(); RsaPrivateJwk privJwk = Jwks.builder().key(privKey).idFromThumbprint().build(); RsaPublicJwk pubJwk = privJwk.toPublicJwk(); assert privJwk.getId().equals(privJwk.thumbprint().toString()); assert pubJwk.getId().equals(pubJwk.thumbprint().toString()); assert privKey.equals(privJwk.toKey()); assert pubKey.equals(pubJwk.toKey()); byte[] utf8Bytes = new JacksonSerializer().serialize(privJwk); // or GsonSerializer(), etc String jwkJson = new String(utf8Bytes, StandardCharsets.UTF_8); Jwk parsed = Jwks.parser().build().parse(jwkJson); assert parsed instanceof RsaPrivateJwk; assert privJwk.equals(parsed); ``` -------------------------------- ### Create a Compact JWS Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Builds and signs a JWS using the JwtBuilder. The subject and signing key are specified before compacting. ```java String jws = Jwts.builder() // (1) .subject("Bob") // (2) .signWith(key) // (3) <--- .compact(); // (4) ``` -------------------------------- ### Create a JWE Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Use the JwtBuilder to set payload and header parameters, then encrypt with a key, key algorithm, and encryption algorithm, finally compacting the result into a JWE string. ```java String jwe = Jwts.builder() // (1) .subject("Bob") // (2) .encryptWith(key, keyAlgorithm, encryptionAlgorithm) // (3) .compact(); // (4) ``` -------------------------------- ### Create Compact JWS Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Base64URL-encodes the signature and appends it to the concatenated string with a period delimiter to form the final JWS. ```groovy String compact = concatenated + '.' + base64URLEncode( signature ) ``` -------------------------------- ### Decrypt JWE with PKCS11 Private Key via Key Locator Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Demonstrates how a custom key locator can return a decryption key built using `Keys.builder` for PKCS11 private keys, enabling JWE decryption. ```java Jwts.parser() .keyLocator(keyLocator) // your keyLocator.locate(header) would return Keys.builder... .build() .parseEncryptedClaims(jweString); ``` -------------------------------- ### Associate Provider with Key using Keys.builder Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Use Keys.builder to associate a specific security Provider with a key, ensuring it's used for decryption with the JWE 'alg' header. This is useful when some keys require a specific provider (e.g., PKCS11 or HSM) while others can use a default. ```java public Key locate(Header header) { PrivateKey /* or SecretKey */ key = findKey(header); // implement me Provider keySpecificProvider = findKeyProvider(key); // implement me if (keySpecificProvider != null) { // Ensure the key-specific provider (e.g. for PKCS11 or HSM) will be used // during decryption with the KeyAlgorithm in the JWE 'alg' header return Keys.builder(key).provider(keySpecificProvider).build(); } // otherwise default provider is fine: return key; } ``` -------------------------------- ### Configure JwtParser to Support Custom Compression Algorithm Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Add custom CompressionAlgorithm implementations to the JwtParserBuilder's zip collection using add() to enable decompression of JWTs compressed with custom algorithms. ```java CompressionAlgorithm myAlg = new MyCompressionAlgorithm(); Jwts.parser() .zip().add(myAlg).and() // <---- // .. etc ... ``` -------------------------------- ### Reading a JWS Source: https://github.com/jwtk/jjwt/blob/main/README.adoc This snippet demonstrates the standard procedure for parsing a JWS string, including signature verification using a key locator or a static key. ```APIDOC ## Reading a JWS ### Description This endpoint allows you to parse a JWS string and verify its signature. It supports dynamic key lookup or verification with a static key. ### Method N/A (This is an SDK operation) ### Endpoint N/A (This is an SDK operation) ### Parameters #### Key Specification - **keyLocator** (KeyLocator) - Optional - A mechanism to dynamically locate the verification key. - **verifyWith(key)** (Key) - Optional - A static key used for signature verification. #### Input - **jwsString** (String) - Required - The JWS string to parse. ### Request Example ```java Jws jws; try { jws = Jwts.parser() .keyLocator(keyLocator) // or .verifyWith(key) .build() .parseSignedClaims(jwsString); } catch (JwtException ex) { // Handle exception } ``` ### Response #### Success Response - **Jws** - If parsing and verification are successful, returns the JWS object containing claims. - **Jws** - If parsing content is expected, returns the JWS object containing the content. #### Response Example ```json { "header": { ... }, "payload": { ... }, "signature": "..." } ``` ### Type-safe JWSs - Use `parseSignedClaims(String)` for JWSs with a Claims payload. - Use `parseSignedContent(String)` for JWSs with a content payload. ``` -------------------------------- ### Configure JWT Parser with Custom Key Locator Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Instantiate a custom `Locator` and set it on the `JwtParserBuilder` using the `keyLocator` method. This is essential for dynamically looking up keys during JWT parsing. ```java Locator keyLocator = getMyKeyLocator(); Jwts.parser() .keyLocator(keyLocator) // <---- .build() // ... etc ... ``` -------------------------------- ### Create a JWK Set Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Use Jwks.set() to create a JwkSetBuilder, add JWKs using add(), optionally set other members or an operation policy, and then build the set. ```java Jwk jwk = Jwks.builder()/* ... */.build(); SecretJwk = Jwks.set() // 1 .add(jwk) // 2, appends a key //.add(aCollection) // append multiple keys //.keys(allJwks) // sets/replaces all keys //.add("aName", "aValue") // 3, optional //.operationPolicy(Jwks.OP // 3, optional // .policy() // /* etc... */ // .build()) //.provider(aJcaProvider) // optional .build(); // (4) ``` -------------------------------- ### Separate Key Locators for JWS and JWE Source: https://github.com/jwtk/jjwt/blob/main/README.adoc If signature verification and decryption require different lookup strategies, override both `locate(JwsHeader)` and `locate(JweHeader)` in your `KeyLocator` implementation. ```java public class MyKeyLocator extends LocatorAdapter { @Override public Key locate(JwsHeader header) { String keyId = header.getKeyId(); //or any other parameter that you need to inspect return lookupSignatureVerificationKey(keyId); //implement me } @Override public Key locate(JweHeader header) { String keyId = header.getKeyId(); //or any other parameter// that you need to inspect return lookupDecryptionKey(keyId); //implement me } } ``` -------------------------------- ### Create and Parse Elliptic Curve Private JWK Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Illustrates creating an Elliptic Curve Private JWK, obtaining its public part, and then serializing and parsing the private JWK. Requires a configured JSON serializer. ```java KeyPair pair = Jwts.SIG.ES512.keyPair().build(); ECPublicKey pubKey = (ECPublicKey) pair.getPublic(); ECPrivateKey privKey = (ECPrivateKey) pair.getPrivate(); EcPrivateJwk privJwk = Jwks.builder().key(privKey).idFromThumbprint().build(); EcPublicJwk pubJwk = privJwk.toPublicJwk(); assert privJwk.getId().equals(privJwk.thumbprint().toString()); assert pubJwk.getId().equals(pubJwk.thumbprint().toString()); assert privKey.equals(privJwk.toKey()); assert pubKey.equals(pubJwk.toKey()); byte[] utf8Bytes = new JacksonSerializer().serialize(privJwk); // or GsonSerializer(), etc String jwkJson = new String(utf8Bytes, StandardCharsets.UTF_8); Jwk parsed = Jwks.parser().build().parse(jwkJson); assert parsed instanceof EcPrivateJwk; assert privJwk.equals(parsed); ``` -------------------------------- ### Read a JWE with Key Locator Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Use the JwtParserBuilder to specify a keyLocator for dynamic decryption key lookup, build the parser, and then parse the JWE string into encrypted claims or content. Wrap in a try-catch block for error handling. ```java Jwe jwe; try { jwe = Jwts.parser() // (1) .keyLocator(keyLocator) // (2) dynamically lookup decryption keys based on each JWE //.decryptWith(key) // or a static key used to decrypt all encountered JWEs .build() // (3) .parseEncryptedClaims(jweString); // (4) or parseEncryptedContent(jweString); // we can safely trust the JWT catch (JwtException ex) { // (5) // we *cannot* use the JWT as intended by its creator } ``` -------------------------------- ### Default Gson Instance Configuration Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Illustrates the default Gson instance configuration used internally by JJWT when the jjwt-gson dependency is included. This shows the custom serializers and strategies applied. ```java new GsonBuilder() .registerTypeHierarchyAdapter(io.jsonwebtoken.security.ConfidentialValue.class, GsonConfidentialValueSerializer.INSTANCE) .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) .setNumberToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE) ``` -------------------------------- ### Abstract Key Locator Implementation Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Extend `LocatorAdapter` to implement the key lookup logic. The `locate` method is invoked with the JWT header to determine the appropriate key. ```java public class MyKeyLocator extends LocatorAdapter { @Override public Key locate(ProtectedHeader header) { // a JwsHeader or JweHeader // implement me } } ``` -------------------------------- ### Sign JWT with RSA Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Shows how to sign and verify a JWT using RSA cryptography. Requires RSA keys of 2048 bits or larger. Bob signs with his private key, Alice verifies with his public key. ```java // Create a test key suitable for the desired RSA signature algorithm: SignatureAlgorithm alg = Jwts.SIG.RS512; //or PS512, RS256, etc... KeyPair pair = alg.keyPair().build(); // Bob creates the compact JWS with his RSA private key: String jws = Jwts.builder().subject("Alice") .signWith(pair.getPrivate(), alg) // <-- Bob's RSA private key .compact(); // Alice receives and verifies the compact JWS came from Bob: String subject = Jwts.parser() .verifyWith(pair.getPublic()) // <-- Bob's RSA public key .build().parseSignedClaims(jws).getPayload().getSubject(); assert "Alice".equals(subject); ``` -------------------------------- ### Sign and Verify JWT with EdDSA Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Bob creates a compact JWS with his Edwards Curve private key, and Alice verifies it using his public key. ```java String jws = Jwts.builder().subject("Alice") .signWith(pair.getPrivate(), Jwts.SIG.EdDSA) // <-- Bob's Edwards Curve private key w/ EdDSA .compact(); ``` ```java String subject = Jwts.parser() .verifyWith(pair.getPublic()) // <-- Bob's Edwards Curve public key .build().parseSignedClaims(jws).getPayload().getSubject(); assert "Alice".equals(subject); ``` -------------------------------- ### BSD License for MigBase64 Source: https://github.com/jwtk/jjwt/blob/main/NOTICE.md This is the BSD license notice for the MigBase64 library, which forms the basis of JJWT's Base64 implementation. It must be retained as per the original code's requirements. ```text Licence (BSD): ============== Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (base64 @ miginfocom . com) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the MiG InfoCom AB nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ``` -------------------------------- ### Create and Parse Elliptic Curve Public JWK Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Demonstrates the process of generating an Elliptic Curve Public JWK, assigning an ID from its thumbprint, serializing it to JSON, and then parsing it back. A JSON serializer is necessary. ```java ECPublicKey key = (ECPublicKey) Jwts.SIG.ES512.keyPair().build().getPublic(); EcPublicJwk jwk = Jwks.builder().key(key).idFromThumbprint().build(); assert jwk.getId().equals(jwk.thumbprint().toString()); assert key.equals(jwk.toKey()); byte[] utf8Bytes = new JacksonSerializer().serialize(jwk); // or GsonSerializer(), etc String jwkJson = new String(utf8Bytes, StandardCharsets.UTF_8); Jwk parsed = Jwks.parser().build().parse(jwkJson); assert parsed instanceof EcPublicJwk; assert jwk.equals(parsed); ``` -------------------------------- ### Build a Standalone Header Instance Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Use Jwts.header() to create an independent Header instance outside of the JwtBuilder context. Use build() to finalize. ```java Header header = Jwts.header() .keyId("aKeyId") .x509Url(aUri) .add("someName", anyValue) .add(mapValues) // ... etc ... .build() // <---- not 'and()' ``` -------------------------------- ### Convert Private JWK to Public JWK and Key Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Obtain the corresponding public JWK, Java PublicKey, or KeyPair from an existing private JWK. ```java RsaPrivateJwk privateJwk = Jwks.builder().key(rsaPrivateKey).build(); // or ecPrivateKey or edEcPrivateKey // Get the matching public JWK and/or PublicKey: RsaPublicJwk pubJwk = privateJwk.toPublicJwk(); // JWK instance RSAPublicKey pubKey = pubJwk.toKey(); // Java PublicKey instance KeyPair pair = privateJwk.toKeyPair(); // io.jsonwebtoken.security.KeyPair retains key types ``` -------------------------------- ### Android Bouncy Castle Provider Registration (Kotlin) Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Register the BouncyCastleProvider early in your Android application's lifecycle, typically in a static initializer block of your main Activity. This replaces the legacy Android provider and is required for specific cryptographic algorithms. ```kotlin import java.security.Security import org.bouncycastle.jce.provider.BouncyCastleProvider class MainActivity : AppCompatActivity() { companion object { init { Security.removeProvider("BC") //remove old/legacy Android-provided BC provider Security.addProvider(BouncyCastleProvider()) // add 'real'/correct BC provider } } // ... etc ... } ``` -------------------------------- ### Create a JWK from a Map Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Construct a JWK instance from a Map containing JWK name/value pairs. ```java Map jwkValues = getMyJwkMap(); Jwk jwk = Jwks.builder().add(jwkValues).build(); ``` -------------------------------- ### Configure JWT Header Parameters Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Use the JwtBuilder's header() method to set standard and custom header parameters. Call and() to return to the JwtBuilder. ```java String jwt = Jwts.builder() .header() // <---- .keyId("aKeyId") .x509Url(aUri) .add("someName", anyValue) .add(mapValues) // ... etc ... .and() // go back to the JwtBuilder .subject("Joe") // resume JwtBuilder calls... // ... etc ... .compact(); ``` -------------------------------- ### Run CI Workflow Source: https://github.com/jwtk/jjwt/wiki/Home Trigger the CI workflow for the staging branch to ensure build success before proceeding with the release. ```bash gh workflow run CI --ref "$STAGING_BRANCH_ID" ``` -------------------------------- ### Read a JWK Set Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Build a JWK Set Parser using Jwks.setParser(), optionally configuring providers, deserializers, or policies, then call parse() with the JSON input. ```java JwkSet jwkSet = Jwks.setParser() //.provider(aJcaProvider) // optional //.deserializer(deserializer) // optional //.policy(aKeyOperationPolicy) // optional .build() // create the parser .parse(json); // actually parse JSON String, InputStream, Reader, etc. jwkSet.forEach(jwk -> System.out.println(jwk)); ``` -------------------------------- ### Create JWS with Password as SecretKey Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Converts a raw string password into a SecretKey suitable for HMAC-SHA algorithms. ```java Password key = Keys.password(secretString.toCharArray()); ``` -------------------------------- ### Maven Settings for OSSRH Release Source: https://github.com/jwtk/jjwt/wiki/Home Configure Maven settings.xml to include the 'ossrh' profile and server for publishing artifacts to Nexus/OSSRH. Ensure GPG is configured for signing. ```xml ossrh gpg YOUR_GPG_KEY_ID YOUR_GPG_KEY_PASSPHRASE ossrh YOUR_OSSRH_ACCESS_TOKEN_USERNAME YOUR_OSSRH_ACCESS_TOKEN_PASSWORD ``` -------------------------------- ### Create JWS with SecretKey from Base64URL String Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Decodes a Base64URL-encoded string into a SecretKey for HMAC-SHA signing. ```java SecretKey key = Keys.hmacShaKeyFor(Decoders.BASE64URL.decode(secretString)); ``` -------------------------------- ### Jwk Interface Methods Source: https://github.com/jwtk/jjwt/wiki/JWK-scratchpad This section details the methods available on the Jwk interface for managing JWK properties. ```APIDOC ## Jwk Interface ### Description The `Jwk` interface represents a cryptographic key in the JWK (JSON Web Key) format. It extends `Map` and provides specific methods for JWK parameters. ### Methods #### `getKeyType()` * **Description**: Returns the JWK `kty` (Key Type) parameter value. * **Returns**: The JWK `kty` parameter value or `null` if not present. #### `setKeyType(String kty)` * **Description**: Sets the JWK `kty` (Key Type) parameter value. * **Parameters**: * `kty` (String) - The JWK `kty` parameter value or `null` to remove the property. * **Returns**: The `Jwk` instance for method chaining. #### `getPublicKeyUse()` * **Description**: Returns the JWK `use` (Public Key Use) parameter value. * **Returns**: The JWK `use` parameter value or `null` if not present. #### `setPublicKeyUse(String use)` * **Description**: Sets the JWK `use` (Public Key Use) parameter value. * **Parameters**: * `use` (String) - The JWK `use` parameter value or `null` to remove the property. * **Returns**: The `Jwk` instance for method chaining. #### `getKeyOperations()` * **Description**: Returns the JWK `key_ops` (Key Operations) parameter value. * **Returns**: The JWK `key_ops` parameter value or `null` if not present. #### `setKeyOperations(String keyOps)` * **Description**: Sets the JWK `key_ops` (Key Operations) parameter value. * **Parameters**: * `keyOps` (String) - The JWK `key_ops` parameter value or `null` to remove the property. * **Returns**: The `Jwk` instance for method chaining. #### `getAlgorithm()` * **Description**: Returns the JWK `alg` (Algorithm) parameter value. * **Returns**: The JWK `alg` parameter value or `null` if not present. ### Constants * `KEY_TYPE`: "kty" * `PUBLIC_KEY_USE`: "use" * `KEY_OPERATIONS`: "key_ops" * `ALGORITHM`: "alg" * `KEY_ID`: "kid" * `X509_URL`: "x5u" * `X509_CERT_CHAIN`: "x5c" * `X509_CERT_SHA1_THUMBPRINT`: "x5t" * `X509_CERT_SHA256_THUMBPRINT`: "x5t#S256" ``` -------------------------------- ### Create a Private JWK with Explicit Public Key Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Create a private JWK from a PrivateKey, optionally providing the corresponding PublicKey to avoid extra computation. ```java RSAPrivateKey rsaPrivateKey = getRSAPrivateKey(); // or ECPrivateKey RsaPrivateJwk jwk = Jwks.builder().key(rsaPrivateKey) //.publicKey(rsaPublicKey) // optional, but recommended to avoid extra computation work .build(); ``` -------------------------------- ### Sign JWT with HMAC Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Demonstrates signing a JWT with HMAC-SHA algorithms (HS256, HS384, HS512). Requires a SecretKey of appropriate size. ```java // Create a test key suitable for the desired HMAC-SHA algorithm: MacAlgorithm alg = Jwts.SIG.HS512; //or HS384 or HS256 SecretKey key = alg.key().build(); String message = "Hello World!"; byte[] content = message.getBytes(StandardCharsets.UTF_8); // Create the compact JWS: String jws = Jwts.builder().content(content, "text/plain").signWith(key, alg).compact(); // Parse the compact JWS: content = Jwts.parser().verifyWith(key).build().parseSignedContent(jws).getPayload(); assert message.equals(new String(content, StandardCharsets.UTF_8)); ``` -------------------------------- ### Sign JWS with SecretKey Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Demonstrates signing a JWS with a SecretKey. JJWT automatically selects the appropriate HMAC algorithm based on key strength. ```java String jws = Jwts.builder() // ... etc ... .signWith(key) // <--- .compact(); ``` -------------------------------- ### Populate JwtBuilder with a Standalone Header Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Append a pre-built standalone Header instance to a JwtBuilder's header configuration using the add method. ```java // perhaps somewhere in application configuration: Header commonHeaders = Jwts.header() .issuer("My Company") // ... etc ... .build(); // -------------------------------- // somewhere else during actual Jwt construction: String jwt = Jwts.builder() .header() .add(commonHeaders) // <---- .add("specificHeader", specificValue) // jwt-specific headers... .and() .subject("whatever") // ... etc ... .compact(); ``` -------------------------------- ### Lookup Key using Key ID (kid) in Locator Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Implement the `locate` method in your `KeyLocator` to retrieve the `kid` from the JWT header and use it to look up the corresponding verification or decryption key. ```java public class MyKeyLocator extends LocatorAdapter { @Override public Key locate(ProtectedHeader header) { // both JwsHeader and JweHeader extend ProtectedHeader //inspect the header, lookup and return the verification key String keyId = header.getKeyId(); //or any other parameter that you need to inspect Key key = lookupKey(keyId); //implement me return key; } } ``` -------------------------------- ### Create JWT with Standard Claims Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Utilize the `JwtBuilder`'s convenient methods for setting standard registered Claim names like issuer, subject, audience, expiration, etc. ```java String jws = Jwts.builder() .issuer("me") .subject("Bob") .audience().add("you").and() .expiration(expiration) //a java.util.Date .notBefore(notBefore) //a java.util.Date .issuedAt(new Date()) // for example, now .id(UUID.randomUUID().toString()) //just an example id /// ... etc ... ``` -------------------------------- ### Add Multiple Header Parameters from a Map Source: https://github.com/jwtk/jjwt/blob/main/README.adoc The add method can also accept a Map to add multiple header parameters at once. ```java Jwts.builder() .header() .add(multipleHeaderParamsMap) // ... etc ... .and() // return to the JwtBuilder // ... etc ... ``` -------------------------------- ### Create JWS with SecretKey from Base64 String Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Decodes a Base64-encoded string into a SecretKey for HMAC-SHA signing. ```java SecretKey key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(secretString)); ``` -------------------------------- ### Decrypt JWE with Asymmetric Private Key Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Use this when the JWE was encrypted with an asymmetric key. Provide the corresponding `PrivateKey` (not `PublicKey`) to `decryptWith`. ```java Jwts.parser() .decryptWith(privateKey) // <---- a `PrivateKey`, not a `PublicKey` .build() .parseSignedClaims(jweString); ``` -------------------------------- ### JWT Encryption Two-Step Process Pseudocode Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Illustrates the two-step process of JWT encryption: first producing an encryption key using a key management algorithm, and then using that key to encrypt the payload. This pseudocode is language-agnostic. ```groovy Key algorithmKey = getKeyManagementAlgorithmKey(); // PublicKey, SecretKey, or Password SecretKey contentEncryptionKey = keyManagementAlgorithm.produceEncryptionKey(algorithmKey); // 1 byte[] ciphertext = encryptionAlgorithm.encrypt(payload, contentEncryptionKey); // 2 ``` -------------------------------- ### Handle JWT Parsing or Signature Validation Errors Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Demonstrates how to catch JwtException to handle cases where JWT parsing or signature validation fails, preventing the use of untrusted tokens. ```java try { Jwts.parser().verifyWith(key).build().parseSignedClaims(compactJws); //OK, we can trust this JWT } catch (JwtException e) { //don't trust the JWT! } ``` -------------------------------- ### Encrypt and Decrypt JWT with AEAD Algorithm Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Demonstrates encrypting a JWT payload using an AEAD algorithm and then decrypting it. Ensure the correct key and algorithm are used for both operations. ```java // Chooose the Encryption Algorithm used to encrypt the payload: AeadAlgorithm enc = Jwts.ENC.A256GCM; //or A192GCM, A128GCM, A256CBC-HS512, etc... // Create the compact JWE: String jwe = Jwts.builder().issuer("me").encryptWith(key, alg, enc).compact(); // Parse the compact JWE: String issuer = Jwts.parser().decryptWith(key).build() .parseEncryptedClaims(jwe).getPayload().getIssuer(); assert "me".equals(issuer); ``` -------------------------------- ### Create and Sign a JWT Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Generates a JWT with a subject and signs it using an HS256 key. The key should typically be loaded from application configuration. ```java import io.jsonwebtoken.Jwts; import io.jsonwebtoken.security.Keys; import javax.crypto.SecretKey; // We need a signing key, so we'll create one just for this example. Usually // the key would be read from your application configuration instead. SecretKey key = Jwts.SIG.HS256.key().build(); String jws = Jwts.builder().subject("Joe").signWith(key).compact(); ``` -------------------------------- ### Build Decryption Key for PKCS11 Private Keys Source: https://github.com/jwtk/jjwt/blob/main/README.adoc When using PKCS11 private keys, especially from HSMs, provide both the PKCS11 `PrivateKey` and its companion `PublicKey` using `Keys.builder` to create a usable decryption key. ```java KeyPair pair = getMyPkcs11KeyPair(); PrivateKey jwtParserDecryptionKey = Keys.builder(pair.getPrivate()) .publicKey(pair.getPublic()) // PublicKey must implement ECKey or EdECKey or BouncyCastle equivalent .build(); ``` -------------------------------- ### JwkSet Interface Methods Source: https://github.com/jwtk/jjwt/wiki/JWK-scratchpad This snippet details the methods available in the JwkSet interface for managing JWK sets. ```APIDOC ## JwkSet Interface ### Description Represents a set of {@link Jwk}s. This interface extends {@code Map} and provides specific methods for JWK set management. ### Methods #### getKeys() ##### Description Returns a list of {@code Jwk}s contained within the JWK set. ##### Returns - {@code List} - A list of Jwk objects. #### setKeys(List keys) ##### Description Sets the list of {@code Jwk}s for this JWK set. ##### Parameters - **keys** (List) - Required - The list of Jwk objects to set. ##### Returns - T - The modified JwkSet instance for chaining. ``` -------------------------------- ### Create and Parse Edwards Elliptic Curve Public JWK Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Demonstrates creating and parsing an Edwards Elliptic Curve Public JWK (e.g., Ed25519, X25519). Note that RFC 8037 refers to these as 'Octet' keys. A JSON serializer is needed. ```java PublicKey key = Jwks.CRV.Ed25519.keyPair().build().getPublic(); // or Ed448, X25519, X448 OctetPublicJwk jwk = builder().octetKey(key).idFromThumbprint().build(); assert jwk.getId().equals(jwk.thumbprint().toString()); assert key.equals(jwk.toKey()); byte[] utf8Bytes = new JacksonSerializer().serialize(jwk); // or GsonSerializer(), etc String jwkJson = new String(utf8Bytes, StandardCharsets.UTF_8); Jwk parsed = Jwks.parser().build().parse(jwkJson); assert parsed instanceof OctetPublicJwk; assert jwk.equals(parsed); ``` -------------------------------- ### Rebase and Force Push Staging Branch Source: https://github.com/jwtk/jjwt/wiki/Home Squash all changes on the staging branch into a single commit and force push to the origin. ```bash git rebase -i origin/master # resolve any conflicts and commit git push -u origin --force # push to origin ``` -------------------------------- ### Verify and Parse a JWT Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Verifies the signature of a JWT using the provided key and then parses its claims to extract the subject. Throws a JwtException if verification fails. ```java assert Jwts.parser().verifyWith(key).build().parseSignedClaims(jws).getPayload().getSubject().equals("Joe"); ``` -------------------------------- ### Create Private JWKs from KeyPairs Source: https://github.com/jwtk/jjwt/blob/main/README.adoc Generate specific private JWK types (RSA, EC, Octet) directly from Java KeyPair instances. ```java KeyPair rsaKeyPair = getRSAKeyPair(); RsaPrivateJwk rsaPrivJwk = Jwks.builder().rsaKeyPair(rsaKeyPair).build(); KeyPair ecKeyPair = getECKeyPair(); EcPrivateJwk ecPrivJwk = Jwks.builder().ecKeyPair(ecKeyPair).build(); KeyPair edEcKeyPair = getEdECKeyPair(); OctetPrivateJwk edEcPrivJwk = Jwks.builder().octetKeyPair(edEcKeyPair).build(); ```