|
@@ -14,11 +14,12 @@
|
|
* limitations under the License.
|
|
* limitations under the License.
|
|
*/
|
|
*/
|
|
|
|
|
|
-package org.springframework.security.oauth2.client.endpoint;
|
|
|
|
|
|
+package org.springframework.security.oauth2.jwt;
|
|
|
|
|
|
import java.net.URL;
|
|
import java.net.URL;
|
|
import java.util.Collections;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.HashMap;
|
|
|
|
+import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.Set;
|
|
@@ -26,24 +27,8 @@ import java.util.function.Consumer;
|
|
|
|
|
|
import org.springframework.security.oauth2.core.converter.ClaimConversionService;
|
|
import org.springframework.security.oauth2.core.converter.ClaimConversionService;
|
|
import org.springframework.security.oauth2.jose.JwaAlgorithm;
|
|
import org.springframework.security.oauth2.jose.JwaAlgorithm;
|
|
-import org.springframework.security.oauth2.jwt.Jwt;
|
|
|
|
import org.springframework.util.Assert;
|
|
import org.springframework.util.Assert;
|
|
|
|
|
|
-/*
|
|
|
|
- * NOTE:
|
|
|
|
- * This originated in gh-9208 (JwtEncoder),
|
|
|
|
- * which is required to realize the feature in gh-8175 (JWT Client Authentication).
|
|
|
|
- * However, we decided not to merge gh-9208 as part of the 5.5.0 release
|
|
|
|
- * and instead packaged it up privately with the gh-8175 feature.
|
|
|
|
- * We MAY merge gh-9208 in a later release but that is yet to be determined.
|
|
|
|
- *
|
|
|
|
- * gh-9208 Introduce JwtEncoder
|
|
|
|
- * https://github.com/spring-projects/spring-security/pull/9208
|
|
|
|
- *
|
|
|
|
- * gh-8175 Support JWT for Client Authentication
|
|
|
|
- * https://github.com/spring-projects/spring-security/issues/8175
|
|
|
|
- */
|
|
|
|
-
|
|
|
|
/**
|
|
/**
|
|
* The JOSE header is a JSON object representing the header parameters of a JSON Web
|
|
* The JOSE header is a JSON object representing the header parameters of a JSON Web
|
|
* Token, whether the JWT is a JWS or JWE, that describe the cryptographic operations
|
|
* Token, whether the JWT is a JWS or JWE, that describe the cryptographic operations
|
|
@@ -51,7 +36,7 @@ import org.springframework.util.Assert;
|
|
*
|
|
*
|
|
* @author Anoop Garlapati
|
|
* @author Anoop Garlapati
|
|
* @author Joe Grandja
|
|
* @author Joe Grandja
|
|
- * @since 5.5
|
|
|
|
|
|
+ * @since 5.6
|
|
* @see Jwt
|
|
* @see Jwt
|
|
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc7519#section-5">JWT JOSE
|
|
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc7519#section-5">JWT JOSE
|
|
* Header</a>
|
|
* Header</a>
|
|
@@ -60,11 +45,12 @@ import org.springframework.util.Assert;
|
|
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc7516#section-4">JWE JOSE
|
|
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc7516#section-4">JWE JOSE
|
|
* Header</a>
|
|
* Header</a>
|
|
*/
|
|
*/
|
|
-final class JoseHeader {
|
|
|
|
|
|
+class JoseHeader {
|
|
|
|
|
|
private final Map<String, Object> headers;
|
|
private final Map<String, Object> headers;
|
|
|
|
|
|
- private JoseHeader(Map<String, Object> headers) {
|
|
|
|
|
|
+ protected JoseHeader(Map<String, Object> headers) {
|
|
|
|
+ Assert.notEmpty(headers, "headers cannot be empty");
|
|
this.headers = Collections.unmodifiableMap(new HashMap<>(headers));
|
|
this.headers = Collections.unmodifiableMap(new HashMap<>(headers));
|
|
}
|
|
}
|
|
|
|
|
|
@@ -74,7 +60,7 @@ final class JoseHeader {
|
|
* @return the {@link JwaAlgorithm}
|
|
* @return the {@link JwaAlgorithm}
|
|
*/
|
|
*/
|
|
@SuppressWarnings("unchecked")
|
|
@SuppressWarnings("unchecked")
|
|
- <T extends JwaAlgorithm> T getAlgorithm() {
|
|
|
|
|
|
+ public <T extends JwaAlgorithm> T getAlgorithm() {
|
|
return (T) getHeader(JoseHeaderNames.ALG);
|
|
return (T) getHeader(JoseHeaderNames.ALG);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -84,7 +70,7 @@ final class JoseHeader {
|
|
* the JWE.
|
|
* the JWE.
|
|
* @return the JWK Set URL
|
|
* @return the JWK Set URL
|
|
*/
|
|
*/
|
|
- URL getJwkSetUrl() {
|
|
|
|
|
|
+ public URL getJwkSetUrl() {
|
|
return getHeader(JoseHeaderNames.JKU);
|
|
return getHeader(JoseHeaderNames.JKU);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -93,7 +79,7 @@ final class JoseHeader {
|
|
* to digitally sign the JWS or encrypt the JWE.
|
|
* to digitally sign the JWS or encrypt the JWE.
|
|
* @return the JSON Web Key
|
|
* @return the JSON Web Key
|
|
*/
|
|
*/
|
|
- Map<String, Object> getJwk() {
|
|
|
|
|
|
+ public Map<String, Object> getJwk() {
|
|
return getHeader(JoseHeaderNames.JWK);
|
|
return getHeader(JoseHeaderNames.JWK);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -102,7 +88,7 @@ final class JoseHeader {
|
|
* or JWE.
|
|
* or JWE.
|
|
* @return the key ID
|
|
* @return the key ID
|
|
*/
|
|
*/
|
|
- String getKeyId() {
|
|
|
|
|
|
+ public String getKeyId() {
|
|
return getHeader(JoseHeaderNames.KID);
|
|
return getHeader(JoseHeaderNames.KID);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -112,7 +98,7 @@ final class JoseHeader {
|
|
* the JWS or encrypt the JWE.
|
|
* the JWS or encrypt the JWE.
|
|
* @return the X.509 URL
|
|
* @return the X.509 URL
|
|
*/
|
|
*/
|
|
- URL getX509Url() {
|
|
|
|
|
|
+ public URL getX509Url() {
|
|
return getHeader(JoseHeaderNames.X5U);
|
|
return getHeader(JoseHeaderNames.X5U);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -124,7 +110,7 @@ final class JoseHeader {
|
|
* {@code List} is a Base64-encoded DER PKIX certificate value.
|
|
* {@code List} is a Base64-encoded DER PKIX certificate value.
|
|
* @return the X.509 certificate chain
|
|
* @return the X.509 certificate chain
|
|
*/
|
|
*/
|
|
- List<String> getX509CertificateChain() {
|
|
|
|
|
|
+ public List<String> getX509CertificateChain() {
|
|
return getHeader(JoseHeaderNames.X5C);
|
|
return getHeader(JoseHeaderNames.X5C);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -134,7 +120,7 @@ final class JoseHeader {
|
|
* corresponding to the key used to digitally sign the JWS or encrypt the JWE.
|
|
* corresponding to the key used to digitally sign the JWS or encrypt the JWE.
|
|
* @return the X.509 certificate SHA-1 thumbprint
|
|
* @return the X.509 certificate SHA-1 thumbprint
|
|
*/
|
|
*/
|
|
- String getX509SHA1Thumbprint() {
|
|
|
|
|
|
+ public String getX509SHA1Thumbprint() {
|
|
return getHeader(JoseHeaderNames.X5T);
|
|
return getHeader(JoseHeaderNames.X5T);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -144,7 +130,7 @@ final class JoseHeader {
|
|
* corresponding to the key used to digitally sign the JWS or encrypt the JWE.
|
|
* corresponding to the key used to digitally sign the JWS or encrypt the JWE.
|
|
* @return the X.509 certificate SHA-256 thumbprint
|
|
* @return the X.509 certificate SHA-256 thumbprint
|
|
*/
|
|
*/
|
|
- String getX509SHA256Thumbprint() {
|
|
|
|
|
|
+ public String getX509SHA256Thumbprint() {
|
|
return getHeader(JoseHeaderNames.X5T_S256);
|
|
return getHeader(JoseHeaderNames.X5T_S256);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -152,7 +138,7 @@ final class JoseHeader {
|
|
* Returns the type header that declares the media type of the JWS/JWE.
|
|
* Returns the type header that declares the media type of the JWS/JWE.
|
|
* @return the type header
|
|
* @return the type header
|
|
*/
|
|
*/
|
|
- String getType() {
|
|
|
|
|
|
+ public String getType() {
|
|
return getHeader(JoseHeaderNames.TYP);
|
|
return getHeader(JoseHeaderNames.TYP);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -161,7 +147,7 @@ final class JoseHeader {
|
|
* (the payload).
|
|
* (the payload).
|
|
* @return the content type header
|
|
* @return the content type header
|
|
*/
|
|
*/
|
|
- String getContentType() {
|
|
|
|
|
|
+ public String getContentType() {
|
|
return getHeader(JoseHeaderNames.CTY);
|
|
return getHeader(JoseHeaderNames.CTY);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -170,7 +156,7 @@ final class JoseHeader {
|
|
* specifications are being used that MUST be understood and processed.
|
|
* specifications are being used that MUST be understood and processed.
|
|
* @return the critical headers
|
|
* @return the critical headers
|
|
*/
|
|
*/
|
|
- Set<String> getCritical() {
|
|
|
|
|
|
+ public Set<String> getCritical() {
|
|
return getHeader(JoseHeaderNames.CRIT);
|
|
return getHeader(JoseHeaderNames.CRIT);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -178,7 +164,7 @@ final class JoseHeader {
|
|
* Returns the headers.
|
|
* Returns the headers.
|
|
* @return the headers
|
|
* @return the headers
|
|
*/
|
|
*/
|
|
- Map<String, Object> getHeaders() {
|
|
|
|
|
|
+ public Map<String, Object> getHeaders() {
|
|
return this.headers;
|
|
return this.headers;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -189,53 +175,38 @@ final class JoseHeader {
|
|
* @return the header value
|
|
* @return the header value
|
|
*/
|
|
*/
|
|
@SuppressWarnings("unchecked")
|
|
@SuppressWarnings("unchecked")
|
|
- <T> T getHeader(String name) {
|
|
|
|
|
|
+ public <T> T getHeader(String name) {
|
|
Assert.hasText(name, "name cannot be empty");
|
|
Assert.hasText(name, "name cannot be empty");
|
|
return (T) getHeaders().get(name);
|
|
return (T) getHeaders().get(name);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Returns a new {@link Builder}, initialized with the provided {@link JwaAlgorithm}.
|
|
|
|
- * @param jwaAlgorithm the {@link JwaAlgorithm}
|
|
|
|
- * @return the {@link Builder}
|
|
|
|
- */
|
|
|
|
- static Builder withAlgorithm(JwaAlgorithm jwaAlgorithm) {
|
|
|
|
- return new Builder(jwaAlgorithm);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * Returns a new {@link Builder}, initialized with the provided {@code headers}.
|
|
|
|
- * @param headers the headers
|
|
|
|
- * @return the {@link Builder}
|
|
|
|
|
|
+ * A builder for subclasses of {@link JoseHeader}.
|
|
*/
|
|
*/
|
|
- static Builder from(JoseHeader headers) {
|
|
|
|
- return new Builder(headers);
|
|
|
|
- }
|
|
|
|
|
|
+ abstract static class AbstractBuilder<T extends JoseHeader, B extends AbstractBuilder<T, B>> {
|
|
|
|
|
|
- /**
|
|
|
|
- * A builder for {@link JoseHeader}.
|
|
|
|
- */
|
|
|
|
- static final class Builder {
|
|
|
|
|
|
+ private final Map<String, Object> headers = new HashMap<>();
|
|
|
|
|
|
- final Map<String, Object> headers = new HashMap<>();
|
|
|
|
|
|
+ protected AbstractBuilder() {
|
|
|
|
+ }
|
|
|
|
|
|
- private Builder(JwaAlgorithm jwaAlgorithm) {
|
|
|
|
- algorithm(jwaAlgorithm);
|
|
|
|
|
|
+ protected Map<String, Object> getHeaders() {
|
|
|
|
+ return this.headers;
|
|
}
|
|
}
|
|
|
|
|
|
- private Builder(JoseHeader headers) {
|
|
|
|
- Assert.notNull(headers, "headers cannot be null");
|
|
|
|
- this.headers.putAll(headers.getHeaders());
|
|
|
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
|
+ protected final B getThis() {
|
|
|
|
+ return (B) this; // avoid unchecked casts in subclasses by using "getThis()"
|
|
|
|
+ // instead of "(B) this"
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
* Sets the {@link JwaAlgorithm JWA algorithm} used to digitally sign the JWS or
|
|
* Sets the {@link JwaAlgorithm JWA algorithm} used to digitally sign the JWS or
|
|
* encrypt the JWE.
|
|
* encrypt the JWE.
|
|
* @param jwaAlgorithm the {@link JwaAlgorithm}
|
|
* @param jwaAlgorithm the {@link JwaAlgorithm}
|
|
- * @return the {@link Builder}
|
|
|
|
|
|
+ * @return the {@link AbstractBuilder}
|
|
*/
|
|
*/
|
|
- Builder algorithm(JwaAlgorithm jwaAlgorithm) {
|
|
|
|
- Assert.notNull(jwaAlgorithm, "jwaAlgorithm cannot be null");
|
|
|
|
|
|
+ public B algorithm(JwaAlgorithm jwaAlgorithm) {
|
|
return header(JoseHeaderNames.ALG, jwaAlgorithm);
|
|
return header(JoseHeaderNames.ALG, jwaAlgorithm);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -244,9 +215,9 @@ final class JoseHeader {
|
|
* public keys, one of which corresponds to the key used to digitally sign the JWS
|
|
* public keys, one of which corresponds to the key used to digitally sign the JWS
|
|
* or encrypt the JWE.
|
|
* or encrypt the JWE.
|
|
* @param jwkSetUrl the JWK Set URL
|
|
* @param jwkSetUrl the JWK Set URL
|
|
- * @return the {@link Builder}
|
|
|
|
|
|
+ * @return the {@link AbstractBuilder}
|
|
*/
|
|
*/
|
|
- Builder jwkSetUrl(String jwkSetUrl) {
|
|
|
|
|
|
+ public B jwkSetUrl(String jwkSetUrl) {
|
|
return header(JoseHeaderNames.JKU, convertAsURL(JoseHeaderNames.JKU, jwkSetUrl));
|
|
return header(JoseHeaderNames.JKU, convertAsURL(JoseHeaderNames.JKU, jwkSetUrl));
|
|
}
|
|
}
|
|
|
|
|
|
@@ -254,9 +225,9 @@ final class JoseHeader {
|
|
* Sets the JSON Web Key which is the public key that corresponds to the key used
|
|
* Sets the JSON Web Key which is the public key that corresponds to the key used
|
|
* to digitally sign the JWS or encrypt the JWE.
|
|
* to digitally sign the JWS or encrypt the JWE.
|
|
* @param jwk the JSON Web Key
|
|
* @param jwk the JSON Web Key
|
|
- * @return the {@link Builder}
|
|
|
|
|
|
+ * @return the {@link AbstractBuilder}
|
|
*/
|
|
*/
|
|
- Builder jwk(Map<String, Object> jwk) {
|
|
|
|
|
|
+ public B jwk(Map<String, Object> jwk) {
|
|
return header(JoseHeaderNames.JWK, jwk);
|
|
return header(JoseHeaderNames.JWK, jwk);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -264,9 +235,9 @@ final class JoseHeader {
|
|
* Sets the key ID that is a hint indicating which key was used to secure the JWS
|
|
* Sets the key ID that is a hint indicating which key was used to secure the JWS
|
|
* or JWE.
|
|
* or JWE.
|
|
* @param keyId the key ID
|
|
* @param keyId the key ID
|
|
- * @return the {@link Builder}
|
|
|
|
|
|
+ * @return the {@link AbstractBuilder}
|
|
*/
|
|
*/
|
|
- Builder keyId(String keyId) {
|
|
|
|
|
|
+ public B keyId(String keyId) {
|
|
return header(JoseHeaderNames.KID, keyId);
|
|
return header(JoseHeaderNames.KID, keyId);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -275,9 +246,9 @@ final class JoseHeader {
|
|
* certificate or certificate chain corresponding to the key used to digitally
|
|
* certificate or certificate chain corresponding to the key used to digitally
|
|
* sign the JWS or encrypt the JWE.
|
|
* sign the JWS or encrypt the JWE.
|
|
* @param x509Url the X.509 URL
|
|
* @param x509Url the X.509 URL
|
|
- * @return the {@link Builder}
|
|
|
|
|
|
+ * @return the {@link AbstractBuilder}
|
|
*/
|
|
*/
|
|
- Builder x509Url(String x509Url) {
|
|
|
|
|
|
+ public B x509Url(String x509Url) {
|
|
return header(JoseHeaderNames.X5U, convertAsURL(JoseHeaderNames.X5U, x509Url));
|
|
return header(JoseHeaderNames.X5U, convertAsURL(JoseHeaderNames.X5U, x509Url));
|
|
}
|
|
}
|
|
|
|
|
|
@@ -288,9 +259,9 @@ final class JoseHeader {
|
|
* {@code List} of certificate value {@code String}s. Each {@code String} in the
|
|
* {@code List} of certificate value {@code String}s. Each {@code String} in the
|
|
* {@code List} is a Base64-encoded DER PKIX certificate value.
|
|
* {@code List} is a Base64-encoded DER PKIX certificate value.
|
|
* @param x509CertificateChain the X.509 certificate chain
|
|
* @param x509CertificateChain the X.509 certificate chain
|
|
- * @return the {@link Builder}
|
|
|
|
|
|
+ * @return the {@link AbstractBuilder}
|
|
*/
|
|
*/
|
|
- Builder x509CertificateChain(List<String> x509CertificateChain) {
|
|
|
|
|
|
+ public B x509CertificateChain(List<String> x509CertificateChain) {
|
|
return header(JoseHeaderNames.X5C, x509CertificateChain);
|
|
return header(JoseHeaderNames.X5C, x509CertificateChain);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -299,9 +270,9 @@ final class JoseHeader {
|
|
* thumbprint (a.k.a. digest) of the DER encoding of the X.509 certificate
|
|
* thumbprint (a.k.a. digest) of the DER encoding of the X.509 certificate
|
|
* corresponding to the key used to digitally sign the JWS or encrypt the JWE.
|
|
* corresponding to the key used to digitally sign the JWS or encrypt the JWE.
|
|
* @param x509SHA1Thumbprint the X.509 certificate SHA-1 thumbprint
|
|
* @param x509SHA1Thumbprint the X.509 certificate SHA-1 thumbprint
|
|
- * @return the {@link Builder}
|
|
|
|
|
|
+ * @return the {@link AbstractBuilder}
|
|
*/
|
|
*/
|
|
- Builder x509SHA1Thumbprint(String x509SHA1Thumbprint) {
|
|
|
|
|
|
+ public B x509SHA1Thumbprint(String x509SHA1Thumbprint) {
|
|
return header(JoseHeaderNames.X5T, x509SHA1Thumbprint);
|
|
return header(JoseHeaderNames.X5T, x509SHA1Thumbprint);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -310,18 +281,18 @@ final class JoseHeader {
|
|
* SHA-256 thumbprint (a.k.a. digest) of the DER encoding of the X.509 certificate
|
|
* SHA-256 thumbprint (a.k.a. digest) of the DER encoding of the X.509 certificate
|
|
* corresponding to the key used to digitally sign the JWS or encrypt the JWE.
|
|
* corresponding to the key used to digitally sign the JWS or encrypt the JWE.
|
|
* @param x509SHA256Thumbprint the X.509 certificate SHA-256 thumbprint
|
|
* @param x509SHA256Thumbprint the X.509 certificate SHA-256 thumbprint
|
|
- * @return the {@link Builder}
|
|
|
|
|
|
+ * @return the {@link AbstractBuilder}
|
|
*/
|
|
*/
|
|
- Builder x509SHA256Thumbprint(String x509SHA256Thumbprint) {
|
|
|
|
|
|
+ public B x509SHA256Thumbprint(String x509SHA256Thumbprint) {
|
|
return header(JoseHeaderNames.X5T_S256, x509SHA256Thumbprint);
|
|
return header(JoseHeaderNames.X5T_S256, x509SHA256Thumbprint);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
* Sets the type header that declares the media type of the JWS/JWE.
|
|
* Sets the type header that declares the media type of the JWS/JWE.
|
|
* @param type the type header
|
|
* @param type the type header
|
|
- * @return the {@link Builder}
|
|
|
|
|
|
+ * @return the {@link AbstractBuilder}
|
|
*/
|
|
*/
|
|
- Builder type(String type) {
|
|
|
|
|
|
+ public B type(String type) {
|
|
return header(JoseHeaderNames.TYP, type);
|
|
return header(JoseHeaderNames.TYP, type);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -329,54 +300,56 @@ final class JoseHeader {
|
|
* Sets the content type header that declares the media type of the secured
|
|
* Sets the content type header that declares the media type of the secured
|
|
* content (the payload).
|
|
* content (the payload).
|
|
* @param contentType the content type header
|
|
* @param contentType the content type header
|
|
- * @return the {@link Builder}
|
|
|
|
|
|
+ * @return the {@link AbstractBuilder}
|
|
*/
|
|
*/
|
|
- Builder contentType(String contentType) {
|
|
|
|
|
|
+ public B contentType(String contentType) {
|
|
return header(JoseHeaderNames.CTY, contentType);
|
|
return header(JoseHeaderNames.CTY, contentType);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Sets the critical headers that indicates which extensions to the JWS/JWE/JWA
|
|
|
|
|
|
+ * Sets the critical header that indicates which extensions to the JWS/JWE/JWA
|
|
* specifications are being used that MUST be understood and processed.
|
|
* specifications are being used that MUST be understood and processed.
|
|
- * @param headerNames the critical header names
|
|
|
|
- * @return the {@link Builder}
|
|
|
|
|
|
+ * @param name the critical header name
|
|
|
|
+ * @param value the critical header value
|
|
|
|
+ * @return the {@link AbstractBuilder}
|
|
*/
|
|
*/
|
|
- Builder critical(Set<String> headerNames) {
|
|
|
|
- return header(JoseHeaderNames.CRIT, headerNames);
|
|
|
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
|
+ public B criticalHeader(String name, Object value) {
|
|
|
|
+ header(name, value);
|
|
|
|
+ getHeaders().computeIfAbsent(JoseHeaderNames.CRIT, (k) -> new HashSet<String>());
|
|
|
|
+ ((Set<String>) getHeaders().get(JoseHeaderNames.CRIT)).add(name);
|
|
|
|
+ return getThis();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
* Sets the header.
|
|
* Sets the header.
|
|
* @param name the header name
|
|
* @param name the header name
|
|
* @param value the header value
|
|
* @param value the header value
|
|
- * @return the {@link Builder}
|
|
|
|
|
|
+ * @return the {@link AbstractBuilder}
|
|
*/
|
|
*/
|
|
- Builder header(String name, Object value) {
|
|
|
|
|
|
+ public B header(String name, Object value) {
|
|
Assert.hasText(name, "name cannot be empty");
|
|
Assert.hasText(name, "name cannot be empty");
|
|
Assert.notNull(value, "value cannot be null");
|
|
Assert.notNull(value, "value cannot be null");
|
|
this.headers.put(name, value);
|
|
this.headers.put(name, value);
|
|
- return this;
|
|
|
|
|
|
+ return getThis();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
* A {@code Consumer} to be provided access to the headers allowing the ability to
|
|
* A {@code Consumer} to be provided access to the headers allowing the ability to
|
|
* add, replace, or remove.
|
|
* add, replace, or remove.
|
|
* @param headersConsumer a {@code Consumer} of the headers
|
|
* @param headersConsumer a {@code Consumer} of the headers
|
|
- * @return the {@link Builder}
|
|
|
|
|
|
+ * @return the {@link AbstractBuilder}
|
|
*/
|
|
*/
|
|
- Builder headers(Consumer<Map<String, Object>> headersConsumer) {
|
|
|
|
|
|
+ public B headers(Consumer<Map<String, Object>> headersConsumer) {
|
|
headersConsumer.accept(this.headers);
|
|
headersConsumer.accept(this.headers);
|
|
- return this;
|
|
|
|
|
|
+ return getThis();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
* Builds a new {@link JoseHeader}.
|
|
* Builds a new {@link JoseHeader}.
|
|
* @return a {@link JoseHeader}
|
|
* @return a {@link JoseHeader}
|
|
*/
|
|
*/
|
|
- JoseHeader build() {
|
|
|
|
- Assert.notEmpty(this.headers, "headers cannot be empty");
|
|
|
|
- return new JoseHeader(this.headers);
|
|
|
|
- }
|
|
|
|
|
|
+ public abstract T build();
|
|
|
|
|
|
private static URL convertAsURL(String header, String value) {
|
|
private static URL convertAsURL(String header, String value) {
|
|
URL convertedValue = ClaimConversionService.getSharedInstance().convert(value, URL.class);
|
|
URL convertedValue = ClaimConversionService.getSharedInstance().convert(value, URL.class);
|