diff --git a/api/src/main/java/io/jsonwebtoken/security/AsymmetricJwkBuilder.java b/api/src/main/java/io/jsonwebtoken/security/AsymmetricJwkBuilder.java
index cf0e29b15..ca57c5d02 100644
--- a/api/src/main/java/io/jsonwebtoken/security/AsymmetricJwkBuilder.java
+++ b/api/src/main/java/io/jsonwebtoken/security/AsymmetricJwkBuilder.java
@@ -16,7 +16,7 @@
package io.jsonwebtoken.security;
import java.security.Key;
-import java.util.Set;
+import java.util.Collection;
/**
* A {@link JwkBuilder} that builds asymmetric (public or private) JWKs.
@@ -69,7 +69,7 @@ public interface AsymmetricJwkBuilder,
*
* Per
* JWK RFC 7517, Section 4.3, last paragraph,
- * the {@code use} (Public Key Use) and {@link #operations(Set) key_ops (Key Operations)} members
+ * the use (Public Key Use)
and {@link #operations(Collection) key_ops (Key Operations)} members
* SHOULD NOT be used together; however, if both are used, the information they convey MUST be
* consistent. Applications should specify which of these members they use, if either is to be used by the
* application.
diff --git a/api/src/main/java/io/jsonwebtoken/security/Jwk.java b/api/src/main/java/io/jsonwebtoken/security/Jwk.java
index 7f3a947af..daef62678 100644
--- a/api/src/main/java/io/jsonwebtoken/security/Jwk.java
+++ b/api/src/main/java/io/jsonwebtoken/security/Jwk.java
@@ -95,69 +95,15 @@ public interface Jwk extends Identifiable, Map {
String getAlgorithm();
/**
- * Returns the JWK
- * {@code key_ops} (Key Operations)
- * parameter values or {@code null} if not present. Any values within the returned {@code Set} are
- * CaSe-SeNsItIvE.
- *
- * The JWK specification defines the
- * following values:
- *
- *
- * JWK Key Operations
- *
- *
- * Value |
- * Operation |
- *
- *
- *
- *
- * {@code sign} |
- * compute digital signatures or MAC |
- *
- *
- * {@code verify} |
- * verify digital signatures or MAC |
- *
- *
- * {@code encrypt} |
- * encrypt content |
- *
- *
- * {@code decrypt} |
- * decrypt content and validate decryption, if applicable |
- *
- *
- * {@code wrapKey} |
- * encrypt key |
- *
- *
- * {@code unwrapKey} |
- * decrypt key and validate decryption, if applicable |
- *
- *
- * {@code deriveKey} |
- * derive key |
- *
- *
- * {@code deriveBits} |
- * derive bits not to be used as a key |
- *
- *
- *
- *
- * Other values MAY be used. For best interoperability with other applications however, it is
- * recommended to use only the values above.
- *
- * Multiple unrelated key operations SHOULD NOT be specified for a key because of the potential
- * vulnerabilities associated with using the same key with multiple algorithms. Thus, the combinations
- * {@code sign} with {@code verify}, {@code encrypt} with {@code decrypt}, and {@code wrapKey} with
- * {@code unwrapKey} are permitted, but other combinations SHOULD NOT be used.
+ * Returns the JWK {@code key_ops}
+ * (Key Operations) parameter values or {@code null} if not present. All JWK standard Key Operations are
+ * available via the {@link Jwks.OP} registry, but other (custom) values MAY be present in the returned
+ * set.
*
* @return the JWK {@code key_ops} value or {@code null} if not present.
+ * @see key_ops
(Key Operations) Parameter
*/
- Set getOperations();
+ Set getOperations();
/**
* Returns the required JWK
@@ -188,6 +134,11 @@ public interface Jwk extends Identifiable, Map {
* {@code oct} |
* Octet sequence (used to represent symmetric keys) |
*
+ *
+ * {@code OKP} |
+ * Octet Key Pair (used to represent Edwards
+ * Elliptic Curve keys) |
+ *
*
*
*
diff --git a/api/src/main/java/io/jsonwebtoken/security/JwkBuilder.java b/api/src/main/java/io/jsonwebtoken/security/JwkBuilder.java
index 25aa92665..4e5aad115 100644
--- a/api/src/main/java/io/jsonwebtoken/security/JwkBuilder.java
+++ b/api/src/main/java/io/jsonwebtoken/security/JwkBuilder.java
@@ -18,7 +18,7 @@
import io.jsonwebtoken.lang.MapMutator;
import java.security.Key;
-import java.util.Set;
+import java.util.Collection;
/**
* A {@link SecurityBuilder} that produces a JWK. A JWK is an immutable set of name/value pairs that represent a
@@ -103,6 +103,47 @@ public interface JwkBuilder, T extends JwkBuilde
*/
T idFromThumbprint(HashAlgorithm alg);
+ /**
+ * Specifies an operation for which the key may be used by adding it to the
+ * JWK {@code key_ops} (Key Operations)
+ * Parameter values. This method may be called multiple times.
+ *
+ * The {@code key_ops} (key operations) parameter identifies the operation(s) for which the key is
+ * intended to be used. The {@code key_ops} parameter is intended for use cases in which public,
+ * private, or symmetric keys may be present.
+ *
+ * Security Vulnerability Notice
+ *
+ * Multiple unrelated key operations SHOULD NOT be specified for a key because of the potential
+ * vulnerabilities associated with using the same key with multiple algorithms. Thus, the combinations
+ * {@link Jwks.OP#SIGN sign} with {@link Jwks.OP#VERIFY verify},
+ * {@link Jwks.OP#ENCRYPT encrypt} with {@link Jwks.OP#DECRYPT decrypt}, and
+ * {@link Jwks.OP#WRAP_KEY wrapKey} with {@link Jwks.OP#UNWRAP_KEY unwrapKey} are permitted, but other combinations
+ * SHOULD NOT be used. This is enforced by the builder's key operation
+ * {@link #operationPolicy(KeyOperationPolicy) policy}.
+ *
+ * Standard {@code KeyOperation}s and Overrides
+ *
+ * All RFC-standard JWK Key Operations in the {@link Jwks.OP} registry are supported via the builder's default
+ * operations {@link #operationPolicy(KeyOperationPolicy) policy}, but other (custom) values
+ * MAY be specified (for example, using a {@link Jwks.OP#builder()}).
+ *
+ * If the {@code JwkBuilder} is being used to rebuild or parse an existing JWK however, any custom operations
+ * should be enabled for the {@code JwkBuilder} by {@link #operationPolicy(KeyOperationPolicy) specifying}
+ * an operations policy that includes the custom values (e.g. via
+ * {@link Jwks.OP#policy()}.{@link KeyOperationPolicyBuilder#add(KeyOperation) add(customKeyOperation)}).
+ *
+ * For best interoperability with other applications however, it is recommended to use only the {@link Jwks.OP}
+ * constants.
+ *
+ * @param operation the value to add to the JWK {@code key_ops} value set
+ * @return the builder for method chaining.
+ * @throws IllegalArgumentException if {@code op} is {@code null} or if the operation is not permitted
+ * by the operations {@link #operationPolicy(KeyOperationPolicy) policy}.
+ * @see Jwks.OP
+ */
+ T operation(KeyOperation operation) throws IllegalArgumentException;
+
/**
* Sets the JWK {@code key_ops}
* (Key Operations) Parameter values.
@@ -111,68 +152,63 @@ public interface JwkBuilder, T extends JwkBuilde
* intended to be used. The {@code key_ops} parameter is intended for use cases in which public,
* private, or symmetric keys may be present.
*
- * The JWK specification defines the
- * following values:
- *
- *
- * JWK Key Operations
- *
- *
- * Value |
- * Operation |
- *
- *
- *
- *
- * {@code sign} |
- * compute digital signatures or MAC |
- *
- *
- * {@code verify} |
- * verify digital signatures or MAC |
- *
- *
- * {@code encrypt} |
- * encrypt content |
- *
- *
- * {@code decrypt} |
- * decrypt content and validate decryption, if applicable |
- *
- *
- * {@code wrapKey} |
- * encrypt key |
- *
- *
- * {@code unwrapKey} |
- * decrypt key and validate decryption, if applicable |
- *
- *
- * {@code deriveKey} |
- * derive key |
- *
- *
- * {@code deriveBits} |
- * derive bits not to be used as a key |
- *
- *
- *
- *
- * (Note that {@code key_ops} values intentionally match the {@code KeyUsage} values defined in the
- * Web Cryptography API specification.)
- *
- * Other values MAY be used. For best interoperability with other applications however, it is
- * recommended to use only the values above. Each value is a CaSe-SeNsItIvE string. Use of the
- * {@code key_ops} member is OPTIONAL, unless the application requires its presence.
+ * Security Vulnerability Notice
*
* Multiple unrelated key operations SHOULD NOT be specified for a key because of the potential
* vulnerabilities associated with using the same key with multiple algorithms. Thus, the combinations
- * {@code sign} with {@code verify}, {@code encrypt} with {@code decrypt}, and {@code wrapKey} with
- * {@code unwrapKey} are permitted, but other combinations SHOULD NOT be used.
+ * {@link Jwks.OP#SIGN sign} with {@link Jwks.OP#VERIFY verify},
+ * {@link Jwks.OP#ENCRYPT encrypt} with {@link Jwks.OP#DECRYPT decrypt}, and
+ * {@link Jwks.OP#WRAP_KEY wrapKey} with {@link Jwks.OP#UNWRAP_KEY unwrapKey} are permitted, but other combinations
+ * SHOULD NOT be used. This is enforced by the builder's default
+ * operation {@link #operationPolicy(KeyOperationPolicy) policy}.
+ *
+ * Standard {@code KeyOperation}s and Overrides
+ *
+ * All RFC-standard JWK Key Operations in the {@link Jwks.OP} registry are supported via the builder's default
+ * operations {@link #operationPolicy(KeyOperationPolicy) policy}, but other (custom) values
+ * MAY be specified (for example, using a {@link Jwks.OP#builder()}).
+ *
+ * If the {@code JwkBuilder} is being used to rebuild or parse an existing JWK however, any custom operations
+ * should be enabled for the {@code JwkBuilder} by {@link #operationPolicy(KeyOperationPolicy) specifying}
+ * an operations policy that includes the custom values (e.g. via
+ * {@link Jwks.OP#policy()}.{@link KeyOperationPolicyBuilder#add(KeyOperation) add(customKeyOperation)}).
+ *
+ * For best interoperability with other applications however, it is recommended to use only the {@link Jwks.OP}
+ * constants.
+ *
+ * @param ops the JWK {@code key_ops} value set, or {@code null} if not present.
+ * @return the builder for method chaining.
+ * @throws IllegalArgumentException {@code ops} is {@code null} or empty, or if any of the operations are not
+ * permitted by the operations {@link #operationPolicy(KeyOperationPolicy) policy}.
+ * @see Jwks.OP
+ */
+ T operations(Collection ops) throws IllegalArgumentException;
+
+ /**
+ * Sets the builder's {@link KeyOperationPolicy} that determines which key
+ * {@link #operations(Collection) operations} may be assigned to the JWK. Unless overridden by this method, the
+ * builder uses the default RFC-recommended policy where:
+ *
+ * - All {@link Jwks.OP RFC-standard key operations} are supported.
+ * - Multiple unrelated operations may not be assigned to the JWK per the
+ * RFC 7517, Section 4.3 recommendation:
+ *
+ * Multiple unrelated key operations SHOULD NOT be specified for a key
+ * because of the potential vulnerabilities associated with using the
+ * same key with multiple algorithms.
+ *
+ *
+ *
+ * If you wish to enable a different policy, perhaps to support additional custom {@code KeyOperation} values,
+ * one can be created by using the {@link Jwks.OP#policy()} builder, or by implementing the
+ * {@link KeyOperationPolicy} interface directly.
*
- * @param ops the JWK {@code key_ops} value set.
+ * @param policy the policy to apply during JWK construction
* @return the builder for method chaining.
- * @throws IllegalArgumentException if {@code ops} is {@code null} or empty.
+ * @throws IllegalArgumentException if the specified policy is null, or the policy's
+ * {@link KeyOperationPolicy#getOperations() operations} collection is null or
+ * empty.
+ * @see Jwks.OP#policy()
*/
- T operations(Set ops) throws IllegalArgumentException;
+ T operationPolicy(KeyOperationPolicy policy) throws IllegalArgumentException;
}
diff --git a/api/src/main/java/io/jsonwebtoken/security/JwkParserBuilder.java b/api/src/main/java/io/jsonwebtoken/security/JwkParserBuilder.java
index 7390765f4..eb58ba794 100644
--- a/api/src/main/java/io/jsonwebtoken/security/JwkParserBuilder.java
+++ b/api/src/main/java/io/jsonwebtoken/security/JwkParserBuilder.java
@@ -58,4 +58,28 @@ public interface JwkParserBuilder extends Builder {
*/
JwkParserBuilder deserializeJsonWith(Deserializer