2424import java .util .function .Consumer ;
2525
2626import org .springframework .security .oauth2 .core .converter .ClaimConversionService ;
27- import org .springframework .security .oauth2 .jose .jws . JwsAlgorithm ;
27+ import org .springframework .security .oauth2 .jose .JwaAlgorithm ;
2828import org .springframework .util .Assert ;
2929
3030/**
3636 * @author Joe Grandja
3737 * @since 0.0.1
3838 * @see Jwt
39- * @see <a target="_blank" href="https://tools .ietf.org/html/rfc7519#section-5">JWT JOSE Header</a>
40- * @see <a target="_blank" href="https://tools .ietf.org/html/rfc7515#section-4">JWS JOSE Header</a>
41- * @see <a target="_blank" href="https://tools .ietf.org/html/rfc7516#section-4">JWE JOSE Header</a>
39+ * @see <a target="_blank" href="https://datatracker .ietf.org/doc /html/rfc7519#section-5">JWT JOSE Header</a>
40+ * @see <a target="_blank" href="https://datatracker .ietf.org/doc /html/rfc7515#section-4">JWS JOSE Header</a>
41+ * @see <a target="_blank" href="https://datatracker .ietf.org/doc /html/rfc7516#section-4">JWE JOSE Header</a>
4242 */
4343public final class JoseHeader {
4444 private final Map <String , Object > headers ;
@@ -48,12 +48,13 @@ private JoseHeader(Map<String, Object> headers) {
4848 }
4949
5050 /**
51- * Returns the {@link JwsAlgorithm JWS algorithm} used to digitally sign the JWS.
51+ * Returns the {@link JwaAlgorithm JWA algorithm} used to digitally sign the JWS or encrypt the JWE .
5252 *
53- * @return the JWS algorithm
53+ * @return the {@link JwaAlgorithm}
5454 */
55- public JwsAlgorithm getJwsAlgorithm () {
56- return getHeader (JoseHeaderNames .ALG );
55+ @ SuppressWarnings ("unchecked" )
56+ public <T extends JwaAlgorithm > T getAlgorithm () {
57+ return (T ) getHeader (JoseHeaderNames .ALG );
5758 }
5859
5960 /**
@@ -62,7 +63,7 @@ public JwsAlgorithm getJwsAlgorithm() {
6263 *
6364 * @return the JWK Set URL
6465 */
65- public URL getJwkSetUri () {
66+ public URL getJwkSetUrl () {
6667 return getHeader (JoseHeaderNames .JKU );
6768 }
6869
@@ -91,13 +92,16 @@ public String getKeyId() {
9192 *
9293 * @return the X.509 URL
9394 */
94- public URL getX509Uri () {
95+ public URL getX509Url () {
9596 return getHeader (JoseHeaderNames .X5U );
9697 }
9798
9899 /**
99100 * Returns the X.509 certificate chain that contains the X.509 public key certificate
100- * or certificate chain corresponding to the key used to digitally sign the JWS or encrypt the JWE.
101+ * or certificate chain corresponding to the key used to digitally sign the JWS or
102+ * encrypt the JWE. The certificate or certificate chain is represented as a
103+ * {@code List} of certificate value {@code String}s. Each {@code String} in the
104+ * {@code List} is a Base64-encoded DER PKIX certificate value.
101105 *
102106 * @return the X.509 certificate chain
103107 */
@@ -125,16 +129,6 @@ public String getX509SHA256Thumbprint() {
125129 return getHeader (JoseHeaderNames .X5T_S256 );
126130 }
127131
128- /**
129- * Returns the critical headers that indicates which extensions to the JWS/JWE/JWA specifications
130- * are being used that MUST be understood and processed.
131- *
132- * @return the critical headers
133- */
134- public Set <String > getCritical () {
135- return getHeader (JoseHeaderNames .CRIT );
136- }
137-
138132 /**
139133 * Returns the type header that declares the media type of the JWS/JWE.
140134 *
@@ -153,6 +147,16 @@ public String getContentType() {
153147 return getHeader (JoseHeaderNames .CTY );
154148 }
155149
150+ /**
151+ * Returns the critical headers that indicates which extensions to the JWS/JWE/JWA specifications
152+ * are being used that MUST be understood and processed.
153+ *
154+ * @return the critical headers
155+ */
156+ public Set <String > getCritical () {
157+ return getHeader (JoseHeaderNames .CRIT );
158+ }
159+
156160 /**
157161 * Returns the headers.
158162 *
@@ -185,13 +189,13 @@ public static Builder builder() {
185189 }
186190
187191 /**
188- * Returns a new {@link Builder}, initialized with the provided {@link JwsAlgorithm }.
192+ * Returns a new {@link Builder}, initialized with the provided {@link JwaAlgorithm }.
189193 *
190- * @param jwsAlgorithm the {@link JwsAlgorithm }
194+ * @param jwaAlgorithm the {@link JwaAlgorithm }
191195 * @return the {@link Builder}
192196 */
193- public static Builder withAlgorithm (JwsAlgorithm jwsAlgorithm ) {
194- return new Builder (jwsAlgorithm );
197+ public static Builder withAlgorithm (JwaAlgorithm jwaAlgorithm ) {
198+ return new Builder (jwaAlgorithm );
195199 }
196200
197201 /**
@@ -213,9 +217,8 @@ public static final class Builder {
213217 private Builder () {
214218 }
215219
216- private Builder (JwsAlgorithm jwsAlgorithm ) {
217- Assert .notNull (jwsAlgorithm , "jwsAlgorithm cannot be null" );
218- header (JoseHeaderNames .ALG , jwsAlgorithm );
220+ private Builder (JwaAlgorithm jwaAlgorithm ) {
221+ algorithm (jwaAlgorithm );
219222 }
220223
221224 private Builder (JoseHeader headers ) {
@@ -224,24 +227,25 @@ private Builder(JoseHeader headers) {
224227 }
225228
226229 /**
227- * Sets the {@link JwsAlgorithm JWS algorithm} used to digitally sign the JWS.
230+ * Sets the {@link JwaAlgorithm JWA algorithm} used to digitally sign the JWS or encrypt the JWE .
228231 *
229- * @param jwsAlgorithm the JWS algorithm
232+ * @param jwaAlgorithm the {@link JwaAlgorithm}
230233 * @return the {@link Builder}
231234 */
232- public Builder jwsAlgorithm (JwsAlgorithm jwsAlgorithm ) {
233- return header (JoseHeaderNames .ALG , jwsAlgorithm );
235+ public Builder algorithm (JwaAlgorithm jwaAlgorithm ) {
236+ Assert .notNull (jwaAlgorithm , "jwaAlgorithm cannot be null" );
237+ return header (JoseHeaderNames .ALG , jwaAlgorithm );
234238 }
235239
236240 /**
237241 * Sets the JWK Set URL that refers to the resource of a set of JSON-encoded public keys,
238242 * one of which corresponds to the key used to digitally sign the JWS or encrypt the JWE.
239243 *
240- * @param jwkSetUri the JWK Set URL
244+ * @param jwkSetUrl the JWK Set URL
241245 * @return the {@link Builder}
242246 */
243- public Builder jwkSetUri (String jwkSetUri ) {
244- return header (JoseHeaderNames .JKU , jwkSetUri );
247+ public Builder jwkSetUrl (String jwkSetUrl ) {
248+ return header (JoseHeaderNames .JKU , convertAsURL ( JoseHeaderNames . JKU , jwkSetUrl ) );
245249 }
246250
247251 /**
@@ -269,16 +273,19 @@ public Builder keyId(String keyId) {
269273 * Sets the X.509 URL that refers to the resource for the X.509 public key certificate
270274 * or certificate chain corresponding to the key used to digitally sign the JWS or encrypt the JWE.
271275 *
272- * @param x509Uri the X.509 URL
276+ * @param x509Url the X.509 URL
273277 * @return the {@link Builder}
274278 */
275- public Builder x509Uri (String x509Uri ) {
276- return header (JoseHeaderNames .X5U , x509Uri );
279+ public Builder x509Url (String x509Url ) {
280+ return header (JoseHeaderNames .X5U , convertAsURL ( JoseHeaderNames . X5U , x509Url ) );
277281 }
278282
279283 /**
280284 * Sets the X.509 certificate chain that contains the X.509 public key certificate
281- * or certificate chain corresponding to the key used to digitally sign the JWS or encrypt the JWE.
285+ * or certificate chain corresponding to the key used to digitally sign the JWS or
286+ * encrypt the JWE. The certificate or certificate chain is represented as a
287+ * {@code List} of certificate value {@code String}s. Each {@code String} in the
288+ * {@code List} is a Base64-encoded DER PKIX certificate value.
282289 *
283290 * @param x509CertificateChain the X.509 certificate chain
284291 * @return the {@link Builder}
@@ -309,17 +316,6 @@ public Builder x509SHA256Thumbprint(String x509SHA256Thumbprint) {
309316 return header (JoseHeaderNames .X5T_S256 , x509SHA256Thumbprint );
310317 }
311318
312- /**
313- * Sets the critical headers that indicates which extensions to the JWS/JWE/JWA specifications
314- * are being used that MUST be understood and processed.
315- *
316- * @param headerNames the critical header names
317- * @return the {@link Builder}
318- */
319- public Builder critical (Set <String > headerNames ) {
320- return header (JoseHeaderNames .CRIT , headerNames );
321- }
322-
323319 /**
324320 * Sets the type header that declares the media type of the JWS/JWE.
325321 *
@@ -340,6 +336,17 @@ public Builder contentType(String contentType) {
340336 return header (JoseHeaderNames .CTY , contentType );
341337 }
342338
339+ /**
340+ * Sets the critical headers that indicates which extensions to the JWS/JWE/JWA specifications
341+ * are being used that MUST be understood and processed.
342+ *
343+ * @param headerNames the critical header names
344+ * @return the {@link Builder}
345+ */
346+ public Builder critical (Set <String > headerNames ) {
347+ return header (JoseHeaderNames .CRIT , headerNames );
348+ }
349+
343350 /**
344351 * Sets the header.
345352 *
@@ -373,19 +380,15 @@ public Builder headers(Consumer<Map<String, Object>> headersConsumer) {
373380 */
374381 public JoseHeader build () {
375382 Assert .notEmpty (this .headers , "headers cannot be empty" );
376- convertAsURL (JoseHeaderNames .JKU );
377- convertAsURL (JoseHeaderNames .X5U );
378383 return new JoseHeader (this .headers );
379384 }
380385
381- private void convertAsURL (String header ) {
382- Object value = this .headers .get (header );
383- if (value != null ) {
384- URL convertedValue = ClaimConversionService .getSharedInstance ().convert (value , URL .class );
385- Assert .isTrue (convertedValue != null ,
386- () -> "Unable to convert header '" + header + "' of type '" + value .getClass () + "' to URL." );
387- this .headers .put (header , convertedValue );
388- }
386+ private static URL convertAsURL (String header , String value ) {
387+ URL convertedValue = ClaimConversionService .getSharedInstance ().convert (value , URL .class );
388+ Assert .isTrue (convertedValue != null ,
389+ () -> "Unable to convert header '" + header + "' of type '" + value .getClass () + "' to URL." );
390+ return convertedValue ;
389391 }
392+
390393 }
391394}
0 commit comments