001/* 002 * nimbus-jose-jwt 003 * 004 * Copyright 2012-2016, Connect2id Ltd. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 007 * this file except in compliance with the License. You may obtain a copy of the 008 * License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software distributed 013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 015 * specific language governing permissions and limitations under the License. 016 */ 017 018package com.nimbusds.jose; 019 020 021import java.net.URI; 022import java.text.ParseException; 023import java.util.*; 024 025import net.jcip.annotations.Immutable; 026 027import com.nimbusds.jose.jwk.JWK; 028import com.nimbusds.jose.util.Base64; 029import com.nimbusds.jose.util.Base64URL; 030import com.nimbusds.jose.util.JSONObjectUtils; 031import com.nimbusds.jose.util.X509CertChainUtils; 032 033 034/** 035 * JSON Web Signature (JWS) header. This class is immutable. 036 * 037 * <p>Supports the following {@link #getRegisteredParameterNames registered 038 * header parameters}: 039 * 040 * <ul> 041 * <li>alg 042 * <li>jku 043 * <li>jwk 044 * <li>x5u 045 * <li>x5t 046 * <li>x5t#S256 047 * <li>x5c 048 * <li>kid 049 * <li>typ 050 * <li>cty 051 * <li>crit 052 * <li>b64 053 * </ul> 054 * 055 * <p>The header may also include {@link #getCustomParams custom 056 * parameters}; these will be serialised and parsed along the registered ones. 057 * 058 * <p>Example header of a JSON Web Signature (JWS) object using the 059 * {@link JWSAlgorithm#HS256 HMAC SHA-256 algorithm}: 060 * 061 * <pre> 062 * { 063 * "alg" : "HS256" 064 * } 065 * </pre> 066 * 067 * @author Vladimir Dzhuvinov 068 * @version 2022-03-07 069 */ 070@Immutable 071public final class JWSHeader extends CommonSEHeader { 072 073 074 private static final long serialVersionUID = 1L; 075 076 077 /** 078 * The registered parameter names. 079 */ 080 private static final Set<String> REGISTERED_PARAMETER_NAMES; 081 082 083 static { 084 Set<String> p = new HashSet<>(); 085 086 p.add(HeaderParameterNames.ALGORITHM); 087 p.add(HeaderParameterNames.JWK_SET_URL); 088 p.add(HeaderParameterNames.JWK); 089 p.add(HeaderParameterNames.X_509_CERT_URL); 090 p.add(HeaderParameterNames.X_509_CERT_SHA_1_THUMBPRINT); 091 p.add(HeaderParameterNames.X_509_CERT_SHA_256_THUMBPRINT); 092 p.add(HeaderParameterNames.X_509_CERT_CHAIN); 093 p.add(HeaderParameterNames.KEY_ID); 094 p.add(HeaderParameterNames.TYPE); 095 p.add(HeaderParameterNames.CONTENT_TYPE); 096 p.add(HeaderParameterNames.CRITICAL); 097 p.add(HeaderParameterNames.BASE64_URL_ENCODE_PAYLOAD); 098 099 REGISTERED_PARAMETER_NAMES = Collections.unmodifiableSet(p); 100 } 101 102 103 /** 104 * Builder for constructing JSON Web Signature (JWS) headers. 105 * 106 * <p>Example usage: 107 * 108 * <pre> 109 * JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.HS256) 110 * .contentType("text/plain") 111 * .customParam("exp", new Date().getTime()) 112 * .build(); 113 * </pre> 114 */ 115 public static class Builder { 116 117 118 /** 119 * The JWS algorithm. 120 */ 121 private final JWSAlgorithm alg; 122 123 124 /** 125 * The JOSE object type. 126 */ 127 private JOSEObjectType typ; 128 129 130 /** 131 * The content type. 132 */ 133 private String cty; 134 135 136 /** 137 * The critical headers. 138 */ 139 private Set<String> crit; 140 141 142 /** 143 * Public JWK Set URL. 144 */ 145 private URI jku; 146 147 148 /** 149 * Public JWK. 150 */ 151 private JWK jwk; 152 153 154 /** 155 * X.509 certificate URL. 156 */ 157 private URI x5u; 158 159 160 /** 161 * X.509 certificate SHA-1 thumbprint. 162 */ 163 @Deprecated 164 private Base64URL x5t; 165 166 167 /** 168 * X.509 certificate SHA-256 thumbprint. 169 */ 170 private Base64URL x5t256; 171 172 173 /** 174 * The X.509 certificate chain corresponding to the key used to 175 * sign the JWS object. 176 */ 177 private List<Base64> x5c; 178 179 180 /** 181 * Key ID. 182 */ 183 private String kid; 184 185 186 /** 187 * Base64URL encoding of the payload, the default is 188 * {@code true} for standard JWS serialisation. 189 */ 190 private boolean b64 = true; 191 192 193 /** 194 * Custom header parameters. 195 */ 196 private Map<String,Object> customParams; 197 198 199 /** 200 * The parsed Base64URL. 201 */ 202 private Base64URL parsedBase64URL; 203 204 205 /** 206 * Creates a new JWS header builder. 207 * 208 * @param alg The JWS algorithm ({@code alg}) parameter. Must 209 * not be "none" or {@code null}. 210 */ 211 public Builder(final JWSAlgorithm alg) { 212 213 if (alg.getName().equals(Algorithm.NONE.getName())) { 214 throw new IllegalArgumentException("The JWS algorithm \"alg\" cannot be \"none\""); 215 } 216 217 this.alg = alg; 218 } 219 220 221 /** 222 * Creates a new JWS header builder with the parameters from 223 * the specified header. 224 * 225 * @param jwsHeader The JWS header to use. Must not be 226 * {@code null}. 227 */ 228 public Builder(final JWSHeader jwsHeader) { 229 230 this(jwsHeader.getAlgorithm()); 231 232 typ = jwsHeader.getType(); 233 cty = jwsHeader.getContentType(); 234 crit = jwsHeader.getCriticalParams(); 235 236 jku = jwsHeader.getJWKURL(); 237 jwk = jwsHeader.getJWK(); 238 x5u = jwsHeader.getX509CertURL(); 239 x5t = jwsHeader.getX509CertThumbprint(); 240 x5t256 = jwsHeader.getX509CertSHA256Thumbprint(); 241 x5c = jwsHeader.getX509CertChain(); 242 kid = jwsHeader.getKeyID(); 243 b64 = jwsHeader.isBase64URLEncodePayload(); 244 customParams = jwsHeader.getCustomParams(); 245 } 246 247 248 /** 249 * Sets the type ({@code typ}) parameter. 250 * 251 * @param typ The type parameter, {@code null} if not 252 * specified. 253 * 254 * @return This builder. 255 */ 256 public Builder type(final JOSEObjectType typ) { 257 258 this.typ = typ; 259 return this; 260 } 261 262 263 /** 264 * Sets the content type ({@code cty}) parameter. 265 * 266 * @param cty The content type parameter, {@code null} if not 267 * specified. 268 * 269 * @return This builder. 270 */ 271 public Builder contentType(final String cty) { 272 273 this.cty = cty; 274 return this; 275 } 276 277 278 /** 279 * Sets the critical header parameters ({@code crit}) 280 * parameter. 281 * 282 * @param crit The names of the critical header parameters, 283 * empty set or {@code null} if none. 284 * 285 * @return This builder. 286 */ 287 public Builder criticalParams(final Set<String> crit) { 288 289 this.crit = crit; 290 return this; 291 } 292 293 294 /** 295 * Sets the public JSON Web Key (JWK) Set URL ({@code jku}) 296 * parameter. 297 * 298 * @param jku The public JSON Web Key (JWK) Set URL parameter, 299 * {@code null} if not specified. 300 * 301 * @return This builder. 302 */ 303 public Builder jwkURL(final URI jku) { 304 305 this.jku = jku; 306 return this; 307 } 308 309 310 /** 311 * Sets the public JSON Web Key (JWK) ({@code jwk}) parameter. 312 * 313 * @param jwk The public JSON Web Key (JWK) ({@code jwk}) 314 * parameter, {@code null} if not specified. 315 * 316 * @return This builder. 317 */ 318 public Builder jwk(final JWK jwk) { 319 320 if (jwk != null && jwk.isPrivate()) { 321 throw new IllegalArgumentException("The JWK must be public"); 322 } 323 324 this.jwk = jwk; 325 return this; 326 } 327 328 329 /** 330 * Sets the X.509 certificate URL ({@code x5u}) parameter. 331 * 332 * @param x5u The X.509 certificate URL parameter, {@code null} 333 * if not specified. 334 * 335 * @return This builder. 336 */ 337 public Builder x509CertURL(final URI x5u) { 338 339 this.x5u = x5u; 340 return this; 341 } 342 343 344 /** 345 * Sets the X.509 certificate SHA-1 thumbprint ({@code x5t}) 346 * parameter. 347 * 348 * @param x5t The X.509 certificate SHA-1 thumbprint parameter, 349 * {@code null} if not specified. 350 * 351 * @return This builder. 352 */ 353 @Deprecated 354 public Builder x509CertThumbprint(final Base64URL x5t) { 355 356 this.x5t = x5t; 357 return this; 358 } 359 360 361 /** 362 * Sets the X.509 certificate SHA-256 thumbprint 363 * ({@code x5t#S256}) parameter. 364 * 365 * @param x5t256 The X.509 certificate SHA-256 thumbprint 366 * parameter, {@code null} if not specified. 367 * 368 * @return This builder. 369 */ 370 public Builder x509CertSHA256Thumbprint(final Base64URL x5t256) { 371 372 this.x5t256 = x5t256; 373 return this; 374 } 375 376 377 /** 378 * Sets the X.509 certificate chain parameter ({@code x5c}) 379 * corresponding to the key used to sign the JWS object. 380 * 381 * @param x5c The X.509 certificate chain parameter, 382 * {@code null} if not specified. 383 * 384 * @return This builder. 385 */ 386 public Builder x509CertChain(final List<Base64> x5c) { 387 388 this.x5c = x5c; 389 return this; 390 } 391 392 393 /** 394 * Sets the key ID ({@code kid}) parameter. 395 * 396 * @param kid The key ID parameter, {@code null} if not 397 * specified. 398 * 399 * @return This builder. 400 */ 401 public Builder keyID(final String kid) { 402 403 this.kid = kid; 404 return this; 405 } 406 407 408 /** 409 * Sets the Base64URL encode payload ({@code b64}) parameter. 410 * 411 * @param b64 {@code true} to Base64URL encode the payload 412 * for standard JWS serialisation, {@code false} for 413 * unencoded payload (RFC 7797). 414 * 415 * @return This builder. 416 */ 417 public Builder base64URLEncodePayload(final boolean b64) { 418 419 this.b64 = b64; 420 return this; 421 } 422 423 424 /** 425 * Sets a custom (non-registered) parameter. 426 * 427 * @param name The name of the custom parameter. Must not 428 * match a registered parameter name and must not 429 * be {@code null}. 430 * @param value The value of the custom parameter, should map 431 * to a valid JSON entity, {@code null} if not 432 * specified. 433 * 434 * @return This builder. 435 * 436 * @throws IllegalArgumentException If the specified parameter 437 * name matches a registered 438 * parameter name. 439 */ 440 public Builder customParam(final String name, final Object value) { 441 442 if (getRegisteredParameterNames().contains(name)) { 443 throw new IllegalArgumentException("The parameter name \"" + name + "\" matches a registered name"); 444 } 445 446 if (customParams == null) { 447 customParams = new HashMap<>(); 448 } 449 450 customParams.put(name, value); 451 452 return this; 453 } 454 455 456 /** 457 * Sets the custom (non-registered) parameters. The values must 458 * be serialisable to a JSON entity, otherwise will be ignored. 459 * 460 * @param customParameters The custom parameters, empty map or 461 * {@code null} if none. 462 * 463 * @return This builder. 464 */ 465 public Builder customParams(final Map<String, Object> customParameters) { 466 467 this.customParams = customParameters; 468 return this; 469 } 470 471 472 /** 473 * Sets the parsed Base64URL. 474 * 475 * @param base64URL The parsed Base64URL, {@code null} if the 476 * header is created from scratch. 477 * 478 * @return This builder. 479 */ 480 public Builder parsedBase64URL(final Base64URL base64URL) { 481 482 this.parsedBase64URL = base64URL; 483 return this; 484 } 485 486 487 /** 488 * Builds a new JWS header. 489 * 490 * @return The JWS header. 491 */ 492 public JWSHeader build() { 493 494 return new JWSHeader( 495 alg, typ, cty, crit, 496 jku, jwk, x5u, x5t, x5t256, x5c, kid, b64, 497 customParams, parsedBase64URL); 498 } 499 } 500 501 502 /** 503 * Base64URL encoding of the payload, {@code true} for standard JWS 504 * serialisation, {@code false} for unencoded payload (RFC 7797). 505 */ 506 private final boolean b64; 507 508 509 /** 510 * Creates a new minimal JSON Web Signature (JWS) header. 511 * 512 * <p>Note: Use {@link PlainHeader} to create a header with algorithm 513 * {@link Algorithm#NONE none}. 514 * 515 * @param alg The JWS algorithm ({@code alg}) parameter. Must not be 516 * "none" or {@code null}. 517 */ 518 public JWSHeader(final JWSAlgorithm alg) { 519 520 this(alg, null, null, null, null, null, null, null, null, null, null, true,null, null); 521 } 522 523 524 /** 525 * Creates a new JSON Web Signature (JWS) header. 526 * 527 * <p>Note: Use {@link PlainHeader} to create a header with algorithm 528 * {@link Algorithm#NONE none}. 529 * 530 * @param alg The JWS algorithm ({@code alg}) parameter. 531 * Must not be "none" or {@code null}. 532 * @param typ The type ({@code typ}) parameter, 533 * {@code null} if not specified. 534 * @param cty The content type ({@code cty}) parameter, 535 * {@code null} if not specified. 536 * @param crit The names of the critical header 537 * ({@code crit}) parameters, empty set or 538 * {@code null} if none. 539 * @param jku The JSON Web Key (JWK) Set URL ({@code jku}) 540 * parameter, {@code null} if not specified. 541 * @param jwk The X.509 certificate URL ({@code jwk}) 542 * parameter, {@code null} if not specified. 543 * @param x5u The X.509 certificate URL parameter 544 * ({@code x5u}), {@code null} if not specified. 545 * @param x5t The X.509 certificate SHA-1 thumbprint 546 * ({@code x5t}) parameter, {@code null} if not 547 * specified. 548 * @param x5t256 The X.509 certificate SHA-256 thumbprint 549 * ({@code x5t#S256}) parameter, {@code null} if 550 * not specified. 551 * @param x5c The X.509 certificate chain ({@code x5c}) 552 * parameter, {@code null} if not specified. 553 * @param kid The key ID ({@code kid}) parameter, 554 * {@code null} if not specified. 555 * @param customParams The custom parameters, empty map or 556 * {@code null} if none. 557 * @param parsedBase64URL The parsed Base64URL, {@code null} if the 558 * header is created from scratch. 559 */ 560 @Deprecated 561 public JWSHeader(final JWSAlgorithm alg, 562 final JOSEObjectType typ, 563 final String cty, 564 final Set<String> crit, 565 final URI jku, 566 final JWK jwk, 567 final URI x5u, 568 final Base64URL x5t, 569 final Base64URL x5t256, 570 final List<Base64> x5c, 571 final String kid, 572 final Map<String,Object> customParams, 573 final Base64URL parsedBase64URL) { 574 575 this(alg, typ, cty, crit, jku, jwk, x5u, x5t, x5t256, x5c, kid, true, customParams, parsedBase64URL); 576 } 577 578 579 /** 580 * Creates a new JSON Web Signature (JWS) header. 581 * 582 * <p>Note: Use {@link PlainHeader} to create a header with algorithm 583 * {@link Algorithm#NONE none}. 584 * 585 * @param alg The JWS algorithm ({@code alg}) parameter. 586 * Must not be "none" or {@code null}. 587 * @param typ The type ({@code typ}) parameter, 588 * {@code null} if not specified. 589 * @param cty The content type ({@code cty}) parameter, 590 * {@code null} if not specified. 591 * @param crit The names of the critical header 592 * ({@code crit}) parameters, empty set or 593 * {@code null} if none. 594 * @param jku The JSON Web Key (JWK) Set URL ({@code jku}) 595 * parameter, {@code null} if not specified. 596 * @param jwk The X.509 certificate URL ({@code jwk}) 597 * parameter, {@code null} if not specified. 598 * @param x5u The X.509 certificate URL parameter 599 * ({@code x5u}), {@code null} if not specified. 600 * @param x5t The X.509 certificate SHA-1 thumbprint 601 * ({@code x5t}) parameter, {@code null} if not 602 * specified. 603 * @param x5t256 The X.509 certificate SHA-256 thumbprint 604 * ({@code x5t#S256}) parameter, {@code null} if 605 * not specified. 606 * @param x5c The X.509 certificate chain ({@code x5c}) 607 * parameter, {@code null} if not specified. 608 * @param kid The key ID ({@code kid}) parameter, 609 * {@code null} if not specified. 610 * @param b64 {@code true} to Base64URL encode the payload 611 * for standard JWS serialisation, {@code false} 612 * for unencoded payload (RFC 7797). 613 * @param customParams The custom parameters, empty map or 614 * {@code null} if none. 615 * @param parsedBase64URL The parsed Base64URL, {@code null} if the 616 * header is created from scratch. 617 */ 618 public JWSHeader(final JWSAlgorithm alg, 619 final JOSEObjectType typ, 620 final String cty, 621 final Set<String> crit, 622 final URI jku, 623 final JWK jwk, 624 final URI x5u, 625 final Base64URL x5t, 626 final Base64URL x5t256, 627 final List<Base64> x5c, 628 final String kid, 629 final boolean b64, 630 final Map<String,Object> customParams, 631 final Base64URL parsedBase64URL) { 632 633 super(alg, typ, cty, crit, jku, jwk, x5u, x5t, x5t256, x5c, kid, customParams, parsedBase64URL); 634 635 if (alg.getName().equals(Algorithm.NONE.getName())) { 636 throw new IllegalArgumentException("The JWS algorithm \"alg\" cannot be \"none\""); 637 } 638 639 this.b64 = b64; 640 } 641 642 643 /** 644 * Deep copy constructor. 645 * 646 * @param jwsHeader The JWS header to copy. Must not be {@code null}. 647 */ 648 public JWSHeader(final JWSHeader jwsHeader) { 649 650 this( 651 jwsHeader.getAlgorithm(), 652 jwsHeader.getType(), 653 jwsHeader.getContentType(), 654 jwsHeader.getCriticalParams(), 655 jwsHeader.getJWKURL(), 656 jwsHeader.getJWK(), 657 jwsHeader.getX509CertURL(), 658 jwsHeader.getX509CertThumbprint(), 659 jwsHeader.getX509CertSHA256Thumbprint(), 660 jwsHeader.getX509CertChain(), 661 jwsHeader.getKeyID(), 662 jwsHeader.isBase64URLEncodePayload(), 663 jwsHeader.getCustomParams(), 664 jwsHeader.getParsedBase64URL() 665 ); 666 } 667 668 669 /** 670 * Gets the registered parameter names for JWS headers. 671 * 672 * @return The registered parameter names, as an unmodifiable set. 673 */ 674 public static Set<String> getRegisteredParameterNames() { 675 676 return REGISTERED_PARAMETER_NAMES; 677 } 678 679 680 /** 681 * Gets the algorithm ({@code alg}) parameter. 682 * 683 * @return The algorithm parameter. 684 */ 685 @Override 686 public JWSAlgorithm getAlgorithm() { 687 688 return (JWSAlgorithm)super.getAlgorithm(); 689 } 690 691 692 /** 693 * Returns the Base64URL-encode payload ({@code b64}) parameter. 694 * 695 * @return {@code true} to Base64URL encode the payload for standard 696 * JWS serialisation, {@code false} for unencoded payload (RFC 697 * 7797). 698 */ 699 public boolean isBase64URLEncodePayload() { 700 701 return b64; 702 } 703 704 705 @Override 706 public Set<String> getIncludedParams() { 707 Set<String> includedParams = super.getIncludedParams(); 708 if (! isBase64URLEncodePayload()) { 709 includedParams.add(HeaderParameterNames.BASE64_URL_ENCODE_PAYLOAD); 710 } 711 return includedParams; 712 } 713 714 715 @Override 716 public Map<String, Object> toJSONObject() { 717 Map<String, Object> o = super.toJSONObject(); 718 if (! isBase64URLEncodePayload()) { 719 o.put(HeaderParameterNames.BASE64_URL_ENCODE_PAYLOAD, false); 720 } 721 return o; 722 } 723 724 725 /** 726 * Parses a JWS header from the specified JSON object. 727 * 728 * @param jsonObject The JSON object to parse. Must not be 729 * {@code null}. 730 * 731 * @return The JWS header. 732 * 733 * @throws ParseException If the specified JSON object doesn't 734 * represent a valid JWS header. 735 */ 736 public static JWSHeader parse(final Map<String, Object> jsonObject) 737 throws ParseException { 738 739 return parse(jsonObject, null); 740 } 741 742 743 /** 744 * Parses a JWS header from the specified JSON object. 745 * 746 * @param jsonObject The JSON object to parse. Must not be 747 * {@code null}. 748 * @param parsedBase64URL The original parsed Base64URL, {@code null} 749 * if not applicable. 750 * 751 * @return The JWS header. 752 * 753 * @throws ParseException If the specified JSON object doesn't 754 * represent a valid JWS header. 755 */ 756 public static JWSHeader parse(final Map<String, Object> jsonObject, 757 final Base64URL parsedBase64URL) 758 throws ParseException { 759 760 // Get the "alg" parameter 761 Algorithm alg = Header.parseAlgorithm(jsonObject); 762 763 if (! (alg instanceof JWSAlgorithm)) { 764 throw new ParseException("Not a JWS header", 0); 765 } 766 767 JWSHeader.Builder header = new Builder((JWSAlgorithm)alg).parsedBase64URL(parsedBase64URL); 768 769 // Parse optional + custom parameters 770 for (final String name: jsonObject.keySet()) { 771 772 if(HeaderParameterNames.ALGORITHM.equals(name)) { 773 // skip 774 } else if(HeaderParameterNames.TYPE.equals(name)) { 775 String typValue = JSONObjectUtils.getString(jsonObject, name); 776 if (typValue != null) { 777 header = header.type(new JOSEObjectType(typValue)); 778 } 779 } else if(HeaderParameterNames.CONTENT_TYPE.equals(name)) { 780 header = header.contentType(JSONObjectUtils.getString(jsonObject, name)); 781 } else if(HeaderParameterNames.CRITICAL.equals(name)) { 782 List<String> critValues = JSONObjectUtils.getStringList(jsonObject, name); 783 if (critValues != null) { 784 header = header.criticalParams(new HashSet<>(critValues)); 785 } 786 } else if(HeaderParameterNames.JWK_SET_URL.equals(name)) { 787 header = header.jwkURL(JSONObjectUtils.getURI(jsonObject, name)); 788 } else if(HeaderParameterNames.JWK.equals(name)) { 789 header = header.jwk(CommonSEHeader.parsePublicJWK(JSONObjectUtils.getJSONObject(jsonObject, name))); 790 } else if(HeaderParameterNames.X_509_CERT_URL.equals(name)) { 791 header = header.x509CertURL(JSONObjectUtils.getURI(jsonObject, name)); 792 } else if(HeaderParameterNames.X_509_CERT_SHA_1_THUMBPRINT.equals(name)) { 793 header = header.x509CertThumbprint(Base64URL.from(JSONObjectUtils.getString(jsonObject, name))); 794 } else if(HeaderParameterNames.X_509_CERT_SHA_256_THUMBPRINT.equals(name)) { 795 header = header.x509CertSHA256Thumbprint(Base64URL.from(JSONObjectUtils.getString(jsonObject, name))); 796 } else if(HeaderParameterNames.X_509_CERT_CHAIN.equals(name)) { 797 header = header.x509CertChain(X509CertChainUtils.toBase64List(JSONObjectUtils.getJSONArray(jsonObject, name))); 798 } else if(HeaderParameterNames.KEY_ID.equals(name)) { 799 header = header.keyID(JSONObjectUtils.getString(jsonObject, name)); 800 } else if(HeaderParameterNames.BASE64_URL_ENCODE_PAYLOAD.equals(name)) { 801 header = header.base64URLEncodePayload(JSONObjectUtils.getBoolean(jsonObject, name)); 802 } else { 803 header = header.customParam(name, jsonObject.get(name)); 804 } 805 } 806 807 return header.build(); 808 } 809 810 811 /** 812 * Parses a JWS header from the specified JSON object string. 813 * 814 * @param jsonString The JSON string to parse. Must not be 815 * {@code null}. 816 * 817 * @return The JWS header. 818 * 819 * @throws ParseException If the specified JSON object string doesn't 820 * represent a valid JWS header. 821 */ 822 public static JWSHeader parse(final String jsonString) 823 throws ParseException { 824 825 return parse(jsonString, null); 826 } 827 828 829 /** 830 * Parses a JWS header from the specified JSON object string. 831 * 832 * @param jsonString The JSON string to parse. Must not be 833 * {@code null}. 834 * @param parsedBase64URL The original parsed Base64URL, {@code null} 835 * if not applicable. 836 * 837 * @return The JWS header. 838 * 839 * @throws ParseException If the specified JSON object string doesn't 840 * represent a valid JWS header. 841 */ 842 public static JWSHeader parse(final String jsonString, 843 final Base64URL parsedBase64URL) 844 throws ParseException { 845 846 return parse(JSONObjectUtils.parse(jsonString, MAX_HEADER_STRING_LENGTH), parsedBase64URL); 847 } 848 849 850 /** 851 * Parses a JWS header from the specified Base64URL. 852 * 853 * @param base64URL The Base64URL to parse. Must not be {@code null}. 854 * 855 * @return The JWS header. 856 * 857 * @throws ParseException If the specified Base64URL doesn't represent 858 * a valid JWS header. 859 */ 860 public static JWSHeader parse(final Base64URL base64URL) 861 throws ParseException { 862 863 return parse(base64URL.decodeToString(), base64URL); 864 } 865}