1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.forgerock.json.jose.jws;
18
19 import static org.forgerock.json.jose.jws.JwsHeaderKey.CRIT;
20 import static org.forgerock.json.jose.jws.JwsHeaderKey.CTY;
21 import static org.forgerock.json.jose.jws.JwsHeaderKey.JKU;
22 import static org.forgerock.json.jose.jws.JwsHeaderKey.JWK;
23 import static org.forgerock.json.jose.jws.JwsHeaderKey.KID;
24 import static org.forgerock.json.jose.jws.JwsHeaderKey.X5C;
25 import static org.forgerock.json.jose.jws.JwsHeaderKey.X5T;
26 import static org.forgerock.json.jose.jws.JwsHeaderKey.X5U;
27 import static org.forgerock.json.jose.jws.JwsHeaderKey.getHeaderKey;
28
29 import java.net.MalformedURLException;
30 import java.net.URL;
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.Map;
34
35 import org.forgerock.json.jose.exceptions.JwtRuntimeException;
36 import org.forgerock.json.jose.jwe.CompressionAlgorithm;
37 import org.forgerock.json.jose.jwk.JWK;
38 import org.forgerock.json.jose.jwt.JwtHeader;
39 import org.forgerock.json.jose.utils.Utils;
40 import org.forgerock.util.encode.Base64;
41
42
43
44
45
46
47 public abstract class JwtSecureHeader extends JwtHeader {
48 private static final String COMPRESSION_ALGORITHM_HEADER_KEY = "zip";
49
50
51
52
53 public JwtSecureHeader() {
54 }
55
56
57
58
59
60
61 public JwtSecureHeader(Map<String, Object> headers) {
62 setParameters(headers);
63 }
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 public void setJwkSetUrl(URL jwkSetUrl) {
79 put(JKU.value(), new String(jwkSetUrl.toString()));
80 }
81
82
83
84
85
86
87 public URL getJwkSetUrl() {
88 try {
89 String url = get(JKU.value()).asString();
90 return url != null
91 ? new URL(url)
92 : null;
93 } catch (MalformedURLException e) {
94 throw new JwtRuntimeException(e);
95 }
96 }
97
98
99
100
101
102
103
104
105
106 public void setJsonWebKey(JWK jsonWebKey) {
107 put(JWK.value(), jsonWebKey);
108 }
109
110
111
112
113
114
115 public JWK getJsonWebKey() {
116 return (JWK) get(JWK.value()).getObject();
117 }
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134 public void setX509Url(URL x509Url) {
135 put(X5U.value(), new String(x509Url.toString()));
136 }
137
138
139
140
141
142
143 public URL getX509Url() {
144 try {
145 String url = get(X5U.value()).asString();
146 return url != null
147 ? new URL(url)
148 : null;
149 } catch (MalformedURLException e) {
150 throw new JwtRuntimeException(e);
151 }
152 }
153
154
155
156
157
158
159
160
161
162
163
164 public void setX509CertificateThumbprint(String x509CertificateThumbprint) {
165 put(X5T.value(), Utils.base64urlEncode(x509CertificateThumbprint));
166 }
167
168
169
170
171
172
173 public String getX509CertificateThumbprint() {
174 return get(X5T.value()).asString();
175 }
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193 public void setX509CertificateChain(List<String> x509CertificateChain) {
194 List<String> encodedCertChain = new ArrayList<>();
195 for (String x509Cert : x509CertificateChain) {
196 encodedCertChain.add(Base64.encode(x509Cert.getBytes(Utils.CHARSET)));
197 }
198 put(X5C.value(), encodedCertChain);
199 }
200
201
202
203
204
205
206 public List<String> getX509CertificateChain() {
207 return get(X5C.value()).asList(String.class);
208 }
209
210
211
212
213
214
215
216
217
218 public void setKeyId(String keyId) {
219 put(KID.value(), keyId);
220 }
221
222
223
224
225
226
227 public String getKeyId() {
228 return get(KID.value()).asString();
229 }
230
231
232
233
234
235
236
237
238 public void setContentType(String contentType) {
239 put(CTY.value(), contentType);
240 }
241
242
243
244
245
246
247 public String getContentType() {
248 return get(CTY.value()).asString();
249 }
250
251
252
253
254
255
256
257
258
259
260
261 public void setCriticalHeaders(List<String> criticalHeaders) {
262 if (criticalHeaders != null && criticalHeaders.isEmpty()) {
263 throw new JwtRuntimeException("Critical Headers parameter cannot be an empty list");
264 }
265 put(CRIT.value(), criticalHeaders);
266 }
267
268
269
270
271
272
273 public List<String> getCriticalHeaders() {
274 return get(CRIT.value()).asList(String.class);
275 }
276
277
278
279
280 @SuppressWarnings("unchecked")
281 @Override
282 public void setParameter(String key, Object value) {
283 JwsHeaderKey headerKey = getHeaderKey(key.toUpperCase());
284
285 switch (headerKey) {
286 case JKU: {
287 checkValueIsOfType(value, URL.class);
288 setJwkSetUrl((URL) value);
289 break;
290 }
291 case JWK: {
292 checkValueIsOfType(value, JWK.class);
293 setJsonWebKey((JWK) value);
294 break;
295 }
296 case X5U: {
297 checkValueIsOfType(value, URL.class);
298 setX509Url((URL) value);
299 break;
300 }
301 case X5T: {
302 checkValueIsOfType(value, String.class);
303 setX509CertificateThumbprint((String) value);
304 break;
305 }
306 case X5C: {
307 checkValueIsOfType(value, List.class);
308 checkListValuesAreOfType((List<?>) value, String.class);
309 setX509CertificateChain((List<String>) value);
310 break;
311 }
312 case KID: {
313 checkValueIsOfType(value, String.class);
314 setKeyId((String) value);
315 break;
316 }
317 case CTY: {
318 checkValueIsOfType(value, String.class);
319 setContentType((String) value);
320 break;
321 }
322 case CRIT: {
323 checkValueIsOfType(value, List.class);
324 checkListValuesAreOfType((List<?>) value, String.class);
325 setCriticalHeaders((List<String>) value);
326 break;
327 }
328 default: {
329 super.setParameter(key, value);
330 }
331 }
332 }
333
334
335
336
337 @Override
338 public Object getParameter(String key) {
339 JwsHeaderKey headerKey = getHeaderKey(key.toUpperCase());
340
341 Object value;
342
343 switch (headerKey) {
344 case JKU: {
345 value = getJwkSetUrl();
346 break;
347 }
348 case JWK: {
349 value = getJsonWebKey();
350 break;
351 }
352 case X5U: {
353 value = getX509Url();
354 break;
355 }
356 case X5T: {
357 value = getX509CertificateThumbprint();
358 break;
359 }
360 case X5C: {
361 value = getX509CertificateChain();
362 break;
363 }
364 case KID: {
365 value = getKeyId();
366 break;
367 }
368 case CTY: {
369 value = getContentType();
370 break;
371 }
372 case CRIT: {
373 value = getCriticalHeaders();
374 break;
375 }
376 default: {
377 value = super.getParameter(key);
378 }
379 }
380
381 return value;
382 }
383
384
385
386
387
388
389
390
391 public void setCompressionAlgorithm(CompressionAlgorithm compressionAlgorithm) {
392 put(COMPRESSION_ALGORITHM_HEADER_KEY, compressionAlgorithm.toString());
393 }
394
395
396
397
398
399
400 public CompressionAlgorithm getCompressionAlgorithm() {
401 String compressionAlgorithm = get(COMPRESSION_ALGORITHM_HEADER_KEY).asString();
402 if (compressionAlgorithm == null) {
403 return CompressionAlgorithm.NONE;
404 } else {
405 return CompressionAlgorithm.valueOf(compressionAlgorithm);
406 }
407 }
408
409 }