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 2021-06-05 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 * JWK Set URL. 144 */ 145 private URI jku; 146 147 148 /** 149 * 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 JSON Web Key (JWK) Set URL ({@code jku}) parameter. 296 * 297 * @param jku The JSON Web Key (JWK) Set URL parameter, 298 * {@code null} if not specified. 299 * 300 * @return This builder. 301 */ 302 public Builder jwkURL(final URI jku) { 303 304 this.jku = jku; 305 return this; 306 } 307 308 309 /** 310 * Sets the JSON Web Key (JWK) ({@code jwk}) parameter. 311 * 312 * @param jwk The JSON Web Key (JWK) ({@code jwk}) parameter, 313 * {@code null} if not specified. 314 * 315 * @return This builder. 316 */ 317 public Builder jwk(final JWK jwk) { 318 319 this.jwk = jwk; 320 return this; 321 } 322 323 324 /** 325 * Sets the X.509 certificate URL ({@code x5u}) parameter. 326 * 327 * @param x5u The X.509 certificate URL parameter, {@code null} 328 * if not specified. 329 * 330 * @return This builder. 331 */ 332 public Builder x509CertURL(final URI x5u) { 333 334 this.x5u = x5u; 335 return this; 336 } 337 338 339 /** 340 * Sets the X.509 certificate SHA-1 thumbprint ({@code x5t}) 341 * parameter. 342 * 343 * @param x5t The X.509 certificate SHA-1 thumbprint parameter, 344 * {@code null} if not specified. 345 * 346 * @return This builder. 347 */ 348 @Deprecated 349 public Builder x509CertThumbprint(final Base64URL x5t) { 350 351 this.x5t = x5t; 352 return this; 353 } 354 355 356 /** 357 * Sets the X.509 certificate SHA-256 thumbprint 358 * ({@code x5t#S256}) parameter. 359 * 360 * @param x5t256 The X.509 certificate SHA-256 thumbprint 361 * parameter, {@code null} if not specified. 362 * 363 * @return This builder. 364 */ 365 public Builder x509CertSHA256Thumbprint(final Base64URL x5t256) { 366 367 this.x5t256 = x5t256; 368 return this; 369 } 370 371 372 /** 373 * Sets the X.509 certificate chain parameter ({@code x5c}) 374 * corresponding to the key used to sign the JWS object. 375 * 376 * @param x5c The X.509 certificate chain parameter, 377 * {@code null} if not specified. 378 * 379 * @return This builder. 380 */ 381 public Builder x509CertChain(final List<Base64> x5c) { 382 383 this.x5c = x5c; 384 return this; 385 } 386 387 388 /** 389 * Sets the key ID ({@code kid}) parameter. 390 * 391 * @param kid The key ID parameter, {@code null} if not 392 * specified. 393 * 394 * @return This builder. 395 */ 396 public Builder keyID(final String kid) { 397 398 this.kid = kid; 399 return this; 400 } 401 402 403 /** 404 * Sets the Base64URL encode payload ({@code b64}) parameter. 405 * 406 * @param b64 {@code true} to Base64URL encode the payload 407 * for standard JWS serialisation, {@code false} for 408 * unencoded payload (RFC 7797). 409 * 410 * @return This builder. 411 */ 412 public Builder base64URLEncodePayload(final boolean b64) { 413 414 this.b64 = b64; 415 return this; 416 } 417 418 419 /** 420 * Sets a custom (non-registered) parameter. 421 * 422 * @param name The name of the custom parameter. Must not 423 * match a registered parameter name and must not 424 * be {@code null}. 425 * @param value The value of the custom parameter, should map 426 * to a valid JSON entity, {@code null} if not 427 * specified. 428 * 429 * @return This builder. 430 * 431 * @throws IllegalArgumentException If the specified parameter 432 * name matches a registered 433 * parameter name. 434 */ 435 public Builder customParam(final String name, final Object value) { 436 437 if (getRegisteredParameterNames().contains(name)) { 438 throw new IllegalArgumentException("The parameter name \"" + name + "\" matches a registered name"); 439 } 440 441 if (customParams == null) { 442 customParams = new HashMap<>(); 443 } 444 445 customParams.put(name, value); 446 447 return this; 448 } 449 450 451 /** 452 * Sets the custom (non-registered) parameters. The values must 453 * be serialisable to a JSON entity, otherwise will be ignored. 454 * 455 * @param customParameters The custom parameters, empty map or 456 * {@code null} if none. 457 * 458 * @return This builder. 459 */ 460 public Builder customParams(final Map<String, Object> customParameters) { 461 462 this.customParams = customParameters; 463 return this; 464 } 465 466 467 /** 468 * Sets the parsed Base64URL. 469 * 470 * @param base64URL The parsed Base64URL, {@code null} if the 471 * header is created from scratch. 472 * 473 * @return This builder. 474 */ 475 public Builder parsedBase64URL(final Base64URL base64URL) { 476 477 this.parsedBase64URL = base64URL; 478 return this; 479 } 480 481 482 /** 483 * Builds a new JWS header. 484 * 485 * @return The JWS header. 486 */ 487 public JWSHeader build() { 488 489 return new JWSHeader( 490 alg, typ, cty, crit, 491 jku, jwk, x5u, x5t, x5t256, x5c, kid, b64, 492 customParams, parsedBase64URL); 493 } 494 } 495 496 497 /** 498 * Base64URL encoding of the payload, {@code true} for standard JWS 499 * serialisation, {@code false} for unencoded payload (RFC 7797). 500 */ 501 private final boolean b64; 502 503 504 /** 505 * Creates a new minimal JSON Web Signature (JWS) header. 506 * 507 * <p>Note: Use {@link PlainHeader} to create a header with algorithm 508 * {@link Algorithm#NONE none}. 509 * 510 * @param alg The JWS algorithm ({@code alg}) parameter. Must not be 511 * "none" or {@code null}. 512 */ 513 public JWSHeader(final JWSAlgorithm alg) { 514 515 this(alg, null, null, null, null, null, null, null, null, null, null, true,null, null); 516 } 517 518 519 /** 520 * Creates a new JSON Web Signature (JWS) header. 521 * 522 * <p>Note: Use {@link PlainHeader} to create a header with algorithm 523 * {@link Algorithm#NONE none}. 524 * 525 * @param alg The JWS algorithm ({@code alg}) parameter. 526 * Must not be "none" or {@code null}. 527 * @param typ The type ({@code typ}) parameter, 528 * {@code null} if not specified. 529 * @param cty The content type ({@code cty}) parameter, 530 * {@code null} if not specified. 531 * @param crit The names of the critical header 532 * ({@code crit}) parameters, empty set or 533 * {@code null} if none. 534 * @param jku The JSON Web Key (JWK) Set URL ({@code jku}) 535 * parameter, {@code null} if not specified. 536 * @param jwk The X.509 certificate URL ({@code jwk}) 537 * parameter, {@code null} if not specified. 538 * @param x5u The X.509 certificate URL parameter 539 * ({@code x5u}), {@code null} if not specified. 540 * @param x5t The X.509 certificate SHA-1 thumbprint 541 * ({@code x5t}) parameter, {@code null} if not 542 * specified. 543 * @param x5t256 The X.509 certificate SHA-256 thumbprint 544 * ({@code x5t#S256}) parameter, {@code null} if 545 * not specified. 546 * @param x5c The X.509 certificate chain ({@code x5c}) 547 * parameter, {@code null} if not specified. 548 * @param kid The key ID ({@code kid}) parameter, 549 * {@code null} if not specified. 550 * @param customParams The custom parameters, empty map or 551 * {@code null} if none. 552 * @param parsedBase64URL The parsed Base64URL, {@code null} if the 553 * header is created from scratch. 554 */ 555 @Deprecated 556 public JWSHeader(final JWSAlgorithm alg, 557 final JOSEObjectType typ, 558 final String cty, 559 final Set<String> crit, 560 final URI jku, 561 final JWK jwk, 562 final URI x5u, 563 final Base64URL x5t, 564 final Base64URL x5t256, 565 final List<Base64> x5c, 566 final String kid, 567 final Map<String,Object> customParams, 568 final Base64URL parsedBase64URL) { 569 570 this(alg, typ, cty, crit, jku, jwk, x5u, x5t, x5t256, x5c, kid, true, customParams, parsedBase64URL); 571 } 572 573 574 /** 575 * Creates a new JSON Web Signature (JWS) header. 576 * 577 * <p>Note: Use {@link PlainHeader} to create a header with algorithm 578 * {@link Algorithm#NONE none}. 579 * 580 * @param alg The JWS algorithm ({@code alg}) parameter. 581 * Must not be "none" or {@code null}. 582 * @param typ The type ({@code typ}) parameter, 583 * {@code null} if not specified. 584 * @param cty The content type ({@code cty}) parameter, 585 * {@code null} if not specified. 586 * @param crit The names of the critical header 587 * ({@code crit}) parameters, empty set or 588 * {@code null} if none. 589 * @param jku The JSON Web Key (JWK) Set URL ({@code jku}) 590 * parameter, {@code null} if not specified. 591 * @param jwk The X.509 certificate URL ({@code jwk}) 592 * parameter, {@code null} if not specified. 593 * @param x5u The X.509 certificate URL parameter 594 * ({@code x5u}), {@code null} if not specified. 595 * @param x5t The X.509 certificate SHA-1 thumbprint 596 * ({@code x5t}) parameter, {@code null} if not 597 * specified. 598 * @param x5t256 The X.509 certificate SHA-256 thumbprint 599 * ({@code x5t#S256}) parameter, {@code null} if 600 * not specified. 601 * @param x5c The X.509 certificate chain ({@code x5c}) 602 * parameter, {@code null} if not specified. 603 * @param kid The key ID ({@code kid}) parameter, 604 * {@code null} if not specified. 605 * @param b64 {@code true} to Base64URL encode the payload 606 * for standard JWS serialisation, {@code false} 607 * for unencoded payload (RFC 7797). 608 * @param customParams The custom parameters, empty map or 609 * {@code null} if none. 610 * @param parsedBase64URL The parsed Base64URL, {@code null} if the 611 * header is created from scratch. 612 */ 613 public JWSHeader(final JWSAlgorithm alg, 614 final JOSEObjectType typ, 615 final String cty, 616 final Set<String> crit, 617 final URI jku, 618 final JWK jwk, 619 final URI x5u, 620 final Base64URL x5t, 621 final Base64URL x5t256, 622 final List<Base64> x5c, 623 final String kid, 624 final boolean b64, 625 final Map<String,Object> customParams, 626 final Base64URL parsedBase64URL) { 627 628 super(alg, typ, cty, crit, jku, jwk, x5u, x5t, x5t256, x5c, kid, customParams, parsedBase64URL); 629 630 if (alg.getName().equals(Algorithm.NONE.getName())) { 631 throw new IllegalArgumentException("The JWS algorithm \"alg\" cannot be \"none\""); 632 } 633 634 this.b64 = b64; 635 } 636 637 638 /** 639 * Deep copy constructor. 640 * 641 * @param jwsHeader The JWS header to copy. Must not be {@code null}. 642 */ 643 public JWSHeader(final JWSHeader jwsHeader) { 644 645 this( 646 jwsHeader.getAlgorithm(), 647 jwsHeader.getType(), 648 jwsHeader.getContentType(), 649 jwsHeader.getCriticalParams(), 650 jwsHeader.getJWKURL(), 651 jwsHeader.getJWK(), 652 jwsHeader.getX509CertURL(), 653 jwsHeader.getX509CertThumbprint(), 654 jwsHeader.getX509CertSHA256Thumbprint(), 655 jwsHeader.getX509CertChain(), 656 jwsHeader.getKeyID(), 657 jwsHeader.isBase64URLEncodePayload(), 658 jwsHeader.getCustomParams(), 659 jwsHeader.getParsedBase64URL() 660 ); 661 } 662 663 664 /** 665 * Gets the registered parameter names for JWS headers. 666 * 667 * @return The registered parameter names, as an unmodifiable set. 668 */ 669 public static Set<String> getRegisteredParameterNames() { 670 671 return REGISTERED_PARAMETER_NAMES; 672 } 673 674 675 /** 676 * Gets the algorithm ({@code alg}) parameter. 677 * 678 * @return The algorithm parameter. 679 */ 680 @Override 681 public JWSAlgorithm getAlgorithm() { 682 683 return (JWSAlgorithm)super.getAlgorithm(); 684 } 685 686 687 /** 688 * Returns the Base64URL-encode payload ({@code b64}) parameter. 689 * 690 * @return {@code true} to Base64URL encode the payload for standard 691 * JWS serialisation, {@code false} for unencoded payload (RFC 692 * 7797). 693 */ 694 public boolean isBase64URLEncodePayload() { 695 696 return b64; 697 } 698 699 700 @Override 701 public Set<String> getIncludedParams() { 702 Set<String> includedParams = super.getIncludedParams(); 703 if (! isBase64URLEncodePayload()) { 704 includedParams.add(HeaderParameterNames.BASE64_URL_ENCODE_PAYLOAD); 705 } 706 return includedParams; 707 } 708 709 710 @Override 711 public Map<String, Object> toJSONObject() { 712 Map<String, Object> o = super.toJSONObject(); 713 if (! isBase64URLEncodePayload()) { 714 o.put(HeaderParameterNames.BASE64_URL_ENCODE_PAYLOAD, false); 715 } 716 return o; 717 } 718 719 720 /** 721 * Parses a JWS header from the specified JSON object. 722 * 723 * @param jsonObject The JSON object to parse. Must not be 724 * {@code null}. 725 * 726 * @return The JWS header. 727 * 728 * @throws ParseException If the specified JSON object doesn't 729 * represent a valid JWS header. 730 */ 731 public static JWSHeader parse(final Map<String, Object> jsonObject) 732 throws ParseException { 733 734 return parse(jsonObject, null); 735 } 736 737 738 /** 739 * Parses a JWS header from the specified JSON object. 740 * 741 * @param jsonObject The JSON object to parse. Must not be 742 * {@code null}. 743 * @param parsedBase64URL The original parsed Base64URL, {@code null} 744 * if not applicable. 745 * 746 * @return The JWS header. 747 * 748 * @throws ParseException If the specified JSON object doesn't 749 * represent a valid JWS header. 750 */ 751 public static JWSHeader parse(final Map<String, Object> jsonObject, 752 final Base64URL parsedBase64URL) 753 throws ParseException { 754 755 // Get the "alg" parameter 756 Algorithm alg = Header.parseAlgorithm(jsonObject); 757 758 if (! (alg instanceof JWSAlgorithm)) { 759 throw new ParseException("Not a JWS header", 0); 760 } 761 762 JWSHeader.Builder header = new Builder((JWSAlgorithm)alg).parsedBase64URL(parsedBase64URL); 763 764 // Parse optional + custom parameters 765 for (final String name: jsonObject.keySet()) { 766 767 if(HeaderParameterNames.ALGORITHM.equals(name)) { 768 // skip 769 } else if(HeaderParameterNames.TYPE.equals(name)) { 770 String typValue = JSONObjectUtils.getString(jsonObject, name); 771 if (typValue != null) { 772 header = header.type(new JOSEObjectType(typValue)); 773 } 774 } else if(HeaderParameterNames.CONTENT_TYPE.equals(name)) { 775 header = header.contentType(JSONObjectUtils.getString(jsonObject, name)); 776 } else if(HeaderParameterNames.CRITICAL.equals(name)) { 777 List<String> critValues = JSONObjectUtils.getStringList(jsonObject, name); 778 if (critValues != null) { 779 header = header.criticalParams(new HashSet<>(critValues)); 780 } 781 } else if(HeaderParameterNames.JWK_SET_URL.equals(name)) { 782 header = header.jwkURL(JSONObjectUtils.getURI(jsonObject, name)); 783 } else if(HeaderParameterNames.JWK.equals(name)) { 784 Map<String, Object> jwkObject = JSONObjectUtils.getJSONObject(jsonObject, name); 785 if (jwkObject != null) { 786 header = header.jwk(JWK.parse(jwkObject)); 787 } 788 } else if(HeaderParameterNames.X_509_CERT_URL.equals(name)) { 789 header = header.x509CertURL(JSONObjectUtils.getURI(jsonObject, name)); 790 } else if(HeaderParameterNames.X_509_CERT_SHA_1_THUMBPRINT.equals(name)) { 791 header = header.x509CertThumbprint(Base64URL.from(JSONObjectUtils.getString(jsonObject, name))); 792 } else if(HeaderParameterNames.X_509_CERT_SHA_256_THUMBPRINT.equals(name)) { 793 header = header.x509CertSHA256Thumbprint(Base64URL.from(JSONObjectUtils.getString(jsonObject, name))); 794 } else if(HeaderParameterNames.X_509_CERT_CHAIN.equals(name)) { 795 header = header.x509CertChain(X509CertChainUtils.toBase64List(JSONObjectUtils.getJSONArray(jsonObject, name))); 796 } else if(HeaderParameterNames.KEY_ID.equals(name)) { 797 header = header.keyID(JSONObjectUtils.getString(jsonObject, name)); 798 } else if(HeaderParameterNames.BASE64_URL_ENCODE_PAYLOAD.equals(name)) { 799 header = header.base64URLEncodePayload(JSONObjectUtils.getBoolean(jsonObject, name)); 800 } else { 801 header = header.customParam(name, jsonObject.get(name)); 802 } 803 } 804 805 return header.build(); 806 } 807 808 809 /** 810 * Parses a JWS header from the specified JSON object string. 811 * 812 * @param jsonString The JSON string to parse. Must not be 813 * {@code null}. 814 * 815 * @return The JWS header. 816 * 817 * @throws ParseException If the specified JSON object string doesn't 818 * represent a valid JWS header. 819 */ 820 public static JWSHeader parse(final String jsonString) 821 throws ParseException { 822 823 return parse(jsonString, null); 824 } 825 826 827 /** 828 * Parses a JWS header from the specified JSON object string. 829 * 830 * @param jsonString The JSON string to parse. Must not be 831 * {@code null}. 832 * @param parsedBase64URL The original parsed Base64URL, {@code null} 833 * if not applicable. 834 * 835 * @return The JWS header. 836 * 837 * @throws ParseException If the specified JSON object string doesn't 838 * represent a valid JWS header. 839 */ 840 public static JWSHeader parse(final String jsonString, 841 final Base64URL parsedBase64URL) 842 throws ParseException { 843 844 return parse(JSONObjectUtils.parse(jsonString, MAX_HEADER_STRING_LENGTH), parsedBase64URL); 845 } 846 847 848 /** 849 * Parses a JWS header from the specified Base64URL. 850 * 851 * @param base64URL The Base64URL to parse. Must not be {@code null}. 852 * 853 * @return The JWS header. 854 * 855 * @throws ParseException If the specified Base64URL doesn't represent 856 * a valid JWS header. 857 */ 858 public static JWSHeader parse(final Base64URL base64URL) 859 throws ParseException { 860 861 return parse(base64URL.decodeToString(), base64URL); 862 } 863}