001package com.nimbusds.openid.connect.sdk.rp; 002 003 004import java.net.URI; 005import java.net.URISyntaxException; 006import java.util.*; 007 008import com.nimbusds.jose.EncryptionMethod; 009import com.nimbusds.jose.JWEAlgorithm; 010import com.nimbusds.jose.JWSAlgorithm; 011import com.nimbusds.oauth2.sdk.ParseException; 012import com.nimbusds.oauth2.sdk.client.ClientMetadata; 013import com.nimbusds.oauth2.sdk.client.RegistrationError; 014import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 015import com.nimbusds.openid.connect.sdk.SubjectType; 016import com.nimbusds.openid.connect.sdk.claims.ACR; 017import com.nimbusds.openid.connect.sdk.id.SectorID; 018import net.minidev.json.JSONArray; 019import net.minidev.json.JSONObject; 020import org.apache.commons.collections.CollectionUtils; 021 022 023/** 024 * OpenID Connect client metadata. 025 * 026 * <p>Related specifications: 027 * 028 * <ul> 029 * <li>OpenID Connect Dynamic Client Registration 1.0, section 2. 030 * <li>OpenID Connect Session Management 1.0, section 5.1.1. 031 * <li>OAuth 2.0 Dynamic Client Registration Protocol (RFC 7591), section 032 * 2. 033 * </ul> 034 */ 035public class OIDCClientMetadata extends ClientMetadata { 036 037 038 /** 039 * The registered parameter names. 040 */ 041 private static final Set<String> REGISTERED_PARAMETER_NAMES; 042 043 044 /** 045 * Initialises the registered parameter name set. 046 */ 047 static { 048 // Start with the base OAuth 2.0 client params 049 Set<String> p = new HashSet<>(ClientMetadata.getRegisteredParameterNames()); 050 051 // OIDC params 052 p.add("application_type"); 053 p.add("subject_type"); 054 p.add("sector_identifier_uri"); 055 p.add("request_uris"); 056 p.add("request_object_signing_alg"); 057 p.add("request_object_encryption_alg"); 058 p.add("request_object_encryption_enc"); 059 p.add("id_token_signed_response_alg"); 060 p.add("id_token_encrypted_response_alg"); 061 p.add("id_token_encrypted_response_enc"); 062 p.add("userinfo_signed_response_alg"); 063 p.add("userinfo_encrypted_response_alg"); 064 p.add("userinfo_encrypted_response_enc"); 065 p.add("default_max_age"); 066 p.add("require_auth_time"); 067 p.add("default_acr_values"); 068 p.add("initiate_login_uri"); 069 070 // OIDC session 071 p.add("post_logout_redirect_uris"); 072 073 REGISTERED_PARAMETER_NAMES = Collections.unmodifiableSet(p); 074 } 075 076 077 /** 078 * The client application type. 079 */ 080 private ApplicationType applicationType; 081 082 083 /** 084 * The subject identifier type for responses to this client. 085 */ 086 private SubjectType subjectType; 087 088 089 /** 090 * Sector identifier URI. 091 */ 092 private URI sectorIDURI; 093 094 095 /** 096 * Pre-registered OpenID Connect request URIs. 097 */ 098 private Set<URI> requestObjectURIs; 099 100 101 /** 102 * The JSON Web Signature (JWS) algorithm required for the OpenID 103 * Connect request objects sent by this client. 104 */ 105 private JWSAlgorithm requestObjectJWSAlg; 106 107 108 /** 109 * The JSON Web Encryption (JWE) algorithm required for the OpenID 110 * Connect request objects sent by this client. 111 */ 112 private JWEAlgorithm requestObjectJWEAlg; 113 114 115 /** 116 * The JSON Web Encryption (JWE) method required for the OpenID Connect 117 * request objects sent by this client. 118 */ 119 private EncryptionMethod requestObjectJWEEnc; 120 121 122 /** 123 * The JSON Web Signature (JWS) algorithm required for the ID Tokens 124 * issued to this client. 125 */ 126 private JWSAlgorithm idTokenJWSAlg; 127 128 129 /** 130 * The JSON Web Encryption (JWE) algorithm required for the ID Tokens 131 * issued to this client. 132 */ 133 private JWEAlgorithm idTokenJWEAlg; 134 135 136 /** 137 * The JSON Web Encryption (JWE) method required for the ID Tokens 138 * issued to this client. 139 */ 140 private EncryptionMethod idTokenJWEEnc; 141 142 143 /** 144 * The JSON Web Signature (JWS) algorithm required for the UserInfo 145 * responses to this client. 146 */ 147 private JWSAlgorithm userInfoJWSAlg; 148 149 150 /** 151 * The JSON Web Encryption (JWE) algorithm required for the UserInfo 152 * responses to this client. 153 */ 154 private JWEAlgorithm userInfoJWEAlg; 155 156 157 /** 158 * The JSON Web Encryption (JWE) method required for the UserInfo 159 * responses to this client. 160 */ 161 private EncryptionMethod userInfoJWEEnc; 162 163 164 /** 165 * The default max authentication age, in seconds. If not specified 0. 166 */ 167 private int defaultMaxAge; 168 169 170 /** 171 * If {@code true} the {@code auth_time} claim in the ID Token is 172 * required by default. 173 */ 174 private boolean requiresAuthTime; 175 176 177 /** 178 * The default Authentication Context Class Reference (ACR) values, by 179 * order of preference. 180 */ 181 private List<ACR> defaultACRs; 182 183 184 /** 185 * Authorisation server initiated login HTTPS URI. 186 */ 187 private URI initiateLoginURI; 188 189 190 /** 191 * Logout redirection URIs. 192 */ 193 private Set<URI> postLogoutRedirectURIs; 194 195 196 /** 197 * Creates a new OpenID Connect client metadata instance. 198 */ 199 public OIDCClientMetadata() { 200 201 super(); 202 } 203 204 205 /** 206 * Creates a new OpenID Connect client metadata instance from the 207 * specified base OAuth 2.0 client metadata. 208 * 209 * @param metadata The base OAuth 2.0 client metadata. Must not be 210 * {@code null}. 211 */ 212 public OIDCClientMetadata(final ClientMetadata metadata) { 213 214 super(metadata); 215 } 216 217 218 /** 219 * Gets the registered (standard) OpenID Connect client metadata 220 * parameter names. 221 * 222 * @return The registered OpenID Connect parameter names, as an 223 * unmodifiable set. 224 */ 225 public static Set<String> getRegisteredParameterNames() { 226 227 return REGISTERED_PARAMETER_NAMES; 228 } 229 230 231 /** 232 * Gets the client application type. Corresponds to the 233 * {@code application_type} client metadata field. 234 * 235 * @return The client application type, {@code null} if not specified. 236 */ 237 public ApplicationType getApplicationType() { 238 239 return applicationType; 240 } 241 242 243 /** 244 * Sets the client application type. Corresponds to the 245 * {@code application_type} client metadata field. 246 * 247 * @param applicationType The client application type, {@code null} if 248 * not specified. 249 */ 250 public void setApplicationType(final ApplicationType applicationType) { 251 252 this.applicationType = applicationType; 253 } 254 255 256 /** 257 * Gets the subject identifier type for responses to this client. 258 * Corresponds to the {@code subject_type} client metadata field. 259 * 260 * @return The subject identifier type, {@code null} if not specified. 261 */ 262 public SubjectType getSubjectType() { 263 264 return subjectType; 265 } 266 267 268 /** 269 * Sets the subject identifier type for responses to this client. 270 * Corresponds to the {@code subject_type} client metadata field. 271 * 272 * @param subjectType The subject identifier type, {@code null} if not 273 * specified. 274 */ 275 public void setSubjectType(final SubjectType subjectType) { 276 277 this.subjectType = subjectType; 278 } 279 280 281 /** 282 * Gets the sector identifier URI. Corresponds to the 283 * {@code sector_identifier_uri} client metadata field. 284 * 285 * @return The sector identifier URI, {@code null} if not specified. 286 */ 287 public URI getSectorIDURI() { 288 289 return sectorIDURI; 290 } 291 292 293 /** 294 * Sets the sector identifier URI. Corresponds to the 295 * {@code sector_identifier_uri} client metadata field. 296 * 297 * @param sectorIDURI The sector identifier URI, {@code null} if not 298 * specified. 299 */ 300 public void setSectorIDURI(final URI sectorIDURI) { 301 302 if (sectorIDURI != null) { 303 SectorID.ensureHTTPScheme(sectorIDURI); 304 SectorID.ensureHostComponent(sectorIDURI); 305 } 306 307 this.sectorIDURI = sectorIDURI; 308 } 309 310 311 /** 312 * Resolves the sector identifier from the client metadata. 313 * 314 * @return The sector identifier, {@code null} if the subject type is 315 * set to public. 316 * 317 * @throws IllegalStateException If resolution failed due to incomplete 318 * or inconsistent metadata. 319 */ 320 public SectorID resolveSectorID() { 321 322 if (! SubjectType.PAIRWISE.equals(getSubjectType())) { 323 // subject type is not pairwise or null 324 return null; 325 } 326 327 // Check sector identifier URI first 328 if (getSectorIDURI() != null) { 329 return new SectorID(getSectorIDURI()); 330 } 331 332 // Check redirect URIs second 333 if (CollectionUtils.isEmpty(getRedirectionURIs())) { 334 throw new IllegalStateException("Couldn't resolve sector ID: Missing redirect_uris"); 335 } 336 337 if (getRedirectionURIs().size() > 1) { 338 throw new IllegalStateException("Couldn't resolve sector ID: More than one redirect_uri, sector_identifier_uri not specified"); 339 } 340 341 return new SectorID(getRedirectionURIs().iterator().next()); 342 } 343 344 345 /** 346 * Gets the pre-registered OpenID Connect request object URIs. 347 * Corresponds to the {@code request_uris} client metadata field. 348 * 349 * @return The request object URIs, {@code null} if not specified. 350 */ 351 public Set<URI> getRequestObjectURIs() { 352 353 return requestObjectURIs; 354 } 355 356 357 /** 358 * Sets the pre-registered OpenID Connect request object URIs. 359 * Corresponds to the {@code request_uris} client metadata field. 360 * 361 * @param requestObjectURIs The request object URIs, {@code null} if 362 * not specified. 363 */ 364 public void setRequestObjectURIs(final Set<URI> requestObjectURIs) { 365 366 this.requestObjectURIs = requestObjectURIs; 367 } 368 369 370 /** 371 * Gets the JSON Web Signature (JWS) algorithm required for the OpenID 372 * Connect request objects sent by this client. Corresponds to the 373 * {@code request_object_signing_alg} client metadata field. 374 * 375 * @return The JWS algorithm, {@code null} if not specified. 376 */ 377 public JWSAlgorithm getRequestObjectJWSAlg() { 378 379 return requestObjectJWSAlg; 380 } 381 382 383 /** 384 * Sets the JSON Web Signature (JWS) algorithm required for the OpenID 385 * Connect request objects sent by this client. Corresponds to the 386 * {@code request_object_signing_alg} client metadata field. 387 * 388 * @param requestObjectJWSAlg The JWS algorithm, {@code null} if not 389 * specified. 390 */ 391 public void setRequestObjectJWSAlg(final JWSAlgorithm requestObjectJWSAlg) { 392 393 this.requestObjectJWSAlg = requestObjectJWSAlg; 394 } 395 396 397 /** 398 * Gets the JSON Web Encryption (JWE) algorithm required for the OpenID 399 * Connect request objects sent by this client. Corresponds to the 400 * {@code request_object_encryption_alg} client metadata field. 401 * 402 * @return The JWE algorithm, {@code null} if not specified. 403 */ 404 public JWEAlgorithm getRequestObjectJWEAlg() { 405 406 return requestObjectJWEAlg; 407 } 408 409 410 /** 411 * Sets the JSON Web Encryption (JWE) algorithm required for the OpenID 412 * Connect request objects sent by this client. Corresponds to the 413 * {@code request_object_encryption_alg} client metadata field. 414 * 415 * @param requestObjectJWEAlg The JWE algorithm, {@code null} if not 416 * specified. 417 */ 418 public void setRequestObjectJWEAlg(final JWEAlgorithm requestObjectJWEAlg) { 419 420 this.requestObjectJWEAlg = requestObjectJWEAlg; 421 } 422 423 424 /** 425 * Gets the JSON Web Encryption (JWE) method required for the OpenID 426 * Connect request objects sent by this client. Corresponds to the 427 * {@code request_object_encryption_enc} client metadata field. 428 * 429 * @return The JWE method, {@code null} if not specified. 430 */ 431 public EncryptionMethod getRequestObjectJWEEnc() { 432 433 return requestObjectJWEEnc; 434 } 435 436 437 /** 438 * Sets the JSON Web Encryption (JWE) method required for the OpenID 439 * Connect request objects sent by this client. Corresponds to the 440 * {@code request_object_encryption_enc} client metadata field. 441 * 442 * @param requestObjectJWEEnc The JWE method, {@code null} if not 443 * specified. 444 */ 445 public void setRequestObjectJWEEnc(final EncryptionMethod requestObjectJWEEnc) { 446 447 this.requestObjectJWEEnc = requestObjectJWEEnc; 448 } 449 450 451 /** 452 * Gets the JSON Web Signature (JWS) algorithm required for the ID 453 * Tokens issued to this client. Corresponds to the 454 * {@code id_token_signed_response_alg} client metadata field. 455 * 456 * @return The JWS algorithm, {@code null} if not specified. 457 */ 458 public JWSAlgorithm getIDTokenJWSAlg() { 459 460 return idTokenJWSAlg; 461 } 462 463 464 /** 465 * Sets the JSON Web Signature (JWS) algorithm required for the ID 466 * Tokens issued to this client. Corresponds to the 467 * {@code id_token_signed_response_alg} client metadata field. 468 * 469 * @param idTokenJWSAlg The JWS algorithm, {@code null} if not 470 * specified. 471 */ 472 public void setIDTokenJWSAlg(final JWSAlgorithm idTokenJWSAlg) { 473 474 this.idTokenJWSAlg = idTokenJWSAlg; 475 } 476 477 478 /** 479 * Gets the JSON Web Encryption (JWE) algorithm required for the ID 480 * Tokens issued to this client. Corresponds to the 481 * {@code id_token_encrypted_response_alg} client metadata field. 482 * 483 * @return The JWE algorithm, {@code null} if not specified. 484 */ 485 public JWEAlgorithm getIDTokenJWEAlg() { 486 487 return idTokenJWEAlg; 488 } 489 490 491 /** 492 * Sets the JSON Web Encryption (JWE) algorithm required for the ID 493 * Tokens issued to this client. Corresponds to the 494 * {@code id_token_encrypted_response_alg} client metadata field. 495 * 496 * @param idTokenJWEAlg The JWE algorithm, {@code null} if not 497 * specified. 498 */ 499 public void setIDTokenJWEAlg(final JWEAlgorithm idTokenJWEAlg) { 500 501 this.idTokenJWEAlg = idTokenJWEAlg; 502 } 503 504 505 /** 506 * Gets the JSON Web Encryption (JWE) method required for the ID Tokens 507 * issued to this client. Corresponds to the 508 * {@code id_token_encrypted_response_enc} client metadata field. 509 * 510 * @return The JWE method, {@code null} if not specified. 511 */ 512 public EncryptionMethod getIDTokenJWEEnc() { 513 514 return idTokenJWEEnc; 515 } 516 517 518 /** 519 * Sets the JSON Web Encryption (JWE) method required for the ID Tokens 520 * issued to this client. Corresponds to the 521 * {@code id_token_encrypted_response_enc} client metadata field. 522 * 523 * @param idTokenJWEEnc The JWE method, {@code null} if not specified. 524 */ 525 public void setIDTokenJWEEnc(final EncryptionMethod idTokenJWEEnc) { 526 527 this.idTokenJWEEnc = idTokenJWEEnc; 528 } 529 530 531 /** 532 * Gets the JSON Web Signature (JWS) algorithm required for the 533 * UserInfo responses to this client. Corresponds to the 534 * {@code userinfo_signed_response_alg} client metadata field. 535 * 536 * @return The JWS algorithm, {@code null} if not specified. 537 */ 538 public JWSAlgorithm getUserInfoJWSAlg() { 539 540 return userInfoJWSAlg; 541 } 542 543 544 /** 545 * Sets the JSON Web Signature (JWS) algorithm required for the 546 * UserInfo responses to this client. Corresponds to the 547 * {@code userinfo_signed_response_alg} client metadata field. 548 * 549 * @param userInfoJWSAlg The JWS algorithm, {@code null} if not 550 * specified. 551 */ 552 public void setUserInfoJWSAlg(final JWSAlgorithm userInfoJWSAlg) { 553 554 this.userInfoJWSAlg = userInfoJWSAlg; 555 } 556 557 558 /** 559 * Gets the JSON Web Encryption (JWE) algorithm required for the 560 * UserInfo responses to this client. Corresponds to the 561 * {@code userinfo_encrypted_response_alg} client metadata field. 562 * 563 * @return The JWE algorithm, {@code null} if not specified. 564 */ 565 public JWEAlgorithm getUserInfoJWEAlg() { 566 567 return userInfoJWEAlg; 568 } 569 570 571 /** 572 * Sets the JSON Web Encryption (JWE) algorithm required for the 573 * UserInfo responses to this client. Corresponds to the 574 * {@code userinfo_encrypted_response_alg} client metadata field. 575 * 576 * @param userInfoJWEAlg The JWE algorithm, {@code null} if not 577 * specified. 578 */ 579 public void setUserInfoJWEAlg(final JWEAlgorithm userInfoJWEAlg) { 580 581 this.userInfoJWEAlg = userInfoJWEAlg; 582 } 583 584 585 /** 586 * Gets the JSON Web Encryption (JWE) method required for the UserInfo 587 * responses to this client. Corresponds to the 588 * {@code userinfo_encrypted_response_enc} client metadata field. 589 * 590 * @return The JWE method, {@code null} if not specified. 591 */ 592 public EncryptionMethod getUserInfoJWEEnc() { 593 594 return userInfoJWEEnc; 595 } 596 597 598 /** 599 * Sets the JSON Web Encryption (JWE) method required for the UserInfo 600 * responses to this client. Corresponds to the 601 * {@code userinfo_encrypted_response_enc} client metadata field. 602 * 603 * @param userInfoJWEEnc The JWE method, {@code null} if not specified. 604 */ 605 public void setUserInfoJWEEnc(final EncryptionMethod userInfoJWEEnc) { 606 607 this.userInfoJWEEnc = userInfoJWEEnc; 608 } 609 610 611 /** 612 * Gets the default maximum authentication age. Corresponds to the 613 * {@code default_max_age} client metadata field. 614 * 615 * @return The default max authentication age, in seconds. If not 616 * specified 0. 617 */ 618 public int getDefaultMaxAge() { 619 620 return defaultMaxAge; 621 } 622 623 624 /** 625 * Sets the default maximum authentication age. Corresponds to the 626 * {@code default_max_age} client metadata field. 627 * 628 * @param defaultMaxAge The default max authentication age, in seconds. 629 * If not specified 0. 630 */ 631 public void setDefaultMaxAge(final int defaultMaxAge) { 632 633 this.defaultMaxAge = defaultMaxAge; 634 } 635 636 637 /** 638 * Gets the default requirement for the {@code auth_time} claim in the 639 * ID Token. Corresponds to the {@code require_auth_time} client 640 * metadata field. 641 * 642 * @return If {@code true} the {@code auth_Time} claim in the ID Token 643 * is required by default. 644 */ 645 public boolean requiresAuthTime() { 646 647 return requiresAuthTime; 648 } 649 650 651 /** 652 * Sets the default requirement for the {@code auth_time} claim in the 653 * ID Token. Corresponds to the {@code require_auth_time} client 654 * metadata field. 655 * 656 * @param requiresAuthTime If {@code true} the {@code auth_Time} claim 657 * in the ID Token is required by default. 658 */ 659 public void requiresAuthTime(final boolean requiresAuthTime) { 660 661 this.requiresAuthTime = requiresAuthTime; 662 } 663 664 665 /** 666 * Gets the default Authentication Context Class Reference (ACR) 667 * values. Corresponds to the {@code default_acr_values} client 668 * metadata field. 669 * 670 * @return The default ACR values, by order of preference, 671 * {@code null} if not specified. 672 */ 673 public List<ACR> getDefaultACRs() { 674 675 return defaultACRs; 676 } 677 678 679 /** 680 * Sets the default Authentication Context Class Reference (ACR) 681 * values. Corresponds to the {@code default_acr_values} client 682 * metadata field. 683 * 684 * @param defaultACRs The default ACRs, by order of preference, 685 * {@code null} if not specified. 686 */ 687 public void setDefaultACRs(final List<ACR> defaultACRs) { 688 689 this.defaultACRs = defaultACRs; 690 } 691 692 693 /** 694 * Gets the HTTPS URI that the authorisation server can call to 695 * initiate a login at the client. Corresponds to the 696 * {@code initiate_login_uri} client metadata field. 697 * 698 * @return The login URI, {@code null} if not specified. 699 */ 700 public URI getInitiateLoginURI() { 701 702 return initiateLoginURI; 703 } 704 705 706 /** 707 * Sets the HTTPS URI that the authorisation server can call to 708 * initiate a login at the client. Corresponds to the 709 * {@code initiate_login_uri} client metadata field. 710 * 711 * @param loginURI The login URI, {@code null} if not specified. 712 */ 713 public void setInitiateLoginURI(final URI loginURI) { 714 715 this.initiateLoginURI = loginURI; 716 } 717 718 719 /** 720 * Gets the post logout redirection URIs. Corresponds to the 721 * {@code post_logout_redirect_uris} client metadata field. 722 * 723 * @return The logout redirection URIs, {@code null} if not specified. 724 */ 725 public Set<URI> getPostLogoutRedirectionURIs() { 726 727 return postLogoutRedirectURIs; 728 } 729 730 731 /** 732 * Sets the post logout redirection URIs. Corresponds to the 733 * {@code post_logout_redirect_uris} client metadata field. 734 * 735 * @param logoutURIs The logout redirection URIs, {@code null} if not 736 * specified. 737 */ 738 public void setPostLogoutRedirectionURIs(final Set<URI> logoutURIs) { 739 740 postLogoutRedirectURIs = logoutURIs; 741 } 742 743 744 /** 745 * Applies the client metadata defaults where no values have been 746 * specified. 747 * 748 * <ul> 749 * <li>The response types default to {@code ["code"]}. 750 * <li>The grant types default to {@code "authorization_code".} 751 * <li>The client authentication method defaults to 752 * "client_secret_basic". 753 * <li>The application type defaults to 754 * {@link ApplicationType#WEB}. 755 * <li>The ID token JWS algorithm defaults to "RS256". 756 * </ul> 757 */ 758 @Override 759 public void applyDefaults() { 760 761 super.applyDefaults(); 762 763 if (applicationType == null) { 764 applicationType = ApplicationType.WEB; 765 } 766 767 if (idTokenJWSAlg == null) { 768 idTokenJWSAlg = JWSAlgorithm.RS256; 769 } 770 } 771 772 773 @Override 774 public JSONObject toJSONObject() { 775 776 JSONObject o = super.toJSONObject(false); 777 778 o.putAll(getCustomFields()); 779 780 if (applicationType != null) 781 o.put("application_type", applicationType.toString()); 782 783 if (subjectType != null) 784 o.put("subject_type", subjectType.toString()); 785 786 787 if (sectorIDURI != null) 788 o.put("sector_identifier_uri", sectorIDURI.toString()); 789 790 791 if (requestObjectURIs != null) { 792 793 JSONArray uriList = new JSONArray(); 794 795 for (URI uri: requestObjectURIs) 796 uriList.add(uri.toString()); 797 798 o.put("request_uris", uriList); 799 } 800 801 802 if (requestObjectJWSAlg != null) 803 o.put("request_object_signing_alg", requestObjectJWSAlg.getName()); 804 805 if (requestObjectJWEAlg != null) 806 o.put("request_object_encryption_alg", requestObjectJWEAlg.getName()); 807 808 if (requestObjectJWEEnc != null) 809 o.put("request_object_encryption_enc", requestObjectJWEEnc.getName()); 810 811 812 if (idTokenJWSAlg != null) 813 o.put("id_token_signed_response_alg", idTokenJWSAlg.getName()); 814 815 816 if (idTokenJWEAlg != null) 817 o.put("id_token_encrypted_response_alg", idTokenJWEAlg.getName()); 818 819 820 if (idTokenJWEEnc != null) 821 o.put("id_token_encrypted_response_enc", idTokenJWEEnc.getName()); 822 823 824 if (userInfoJWSAlg != null) 825 o.put("userinfo_signed_response_alg", userInfoJWSAlg.getName()); 826 827 828 if (userInfoJWEAlg != null) 829 o.put("userinfo_encrypted_response_alg", userInfoJWEAlg.getName()); 830 831 832 if (userInfoJWEEnc != null) 833 o.put("userinfo_encrypted_response_enc", userInfoJWEEnc.getName()); 834 835 836 if (defaultMaxAge > 0) 837 o.put("default_max_age", defaultMaxAge); 838 839 840 if (requiresAuthTime()) 841 o.put("require_auth_time", requiresAuthTime); 842 843 844 if (defaultACRs != null) { 845 846 JSONArray acrList = new JSONArray(); 847 848 for (ACR acr: defaultACRs) 849 acrList.add(acr); 850 851 o.put("default_acr_values", acrList); 852 } 853 854 855 if (initiateLoginURI != null) 856 o.put("initiate_login_uri", initiateLoginURI.toString()); 857 858 859 if (postLogoutRedirectURIs != null) { 860 861 JSONArray uriList = new JSONArray(); 862 863 for (URI uri: postLogoutRedirectURIs) 864 uriList.add(uri.toString()); 865 866 o.put("post_logout_redirect_uris", uriList); 867 } 868 869 return o; 870 } 871 872 873 /** 874 * Parses an OpenID Connect client metadata instance from the specified 875 * JSON object. 876 * 877 * @param jsonObject The JSON object to parse. Must not be 878 * {@code null}. 879 * 880 * @return The OpenID Connect client metadata. 881 * 882 * @throws ParseException If the JSON object couldn't be parsed to an 883 * OpenID Connect client metadata instance. 884 */ 885 public static OIDCClientMetadata parse(final JSONObject jsonObject) 886 throws ParseException { 887 888 ClientMetadata baseMetadata = ClientMetadata.parse(jsonObject); 889 890 OIDCClientMetadata metadata = new OIDCClientMetadata(baseMetadata); 891 892 // Parse the OIDC-specific fields from the custom OAuth 2.0 dyn 893 // reg fields 894 895 JSONObject oidcFields = baseMetadata.getCustomFields(); 896 897 try { 898 if (jsonObject.containsKey("application_type")) { 899 metadata.setApplicationType(JSONObjectUtils.getEnum(jsonObject, "application_type", ApplicationType.class)); 900 oidcFields.remove("application_type"); 901 } 902 903 if (jsonObject.containsKey("subject_type")) { 904 metadata.setSubjectType(JSONObjectUtils.getEnum(jsonObject, "subject_type", SubjectType.class)); 905 oidcFields.remove("subject_type"); 906 } 907 908 if (jsonObject.containsKey("sector_identifier_uri")) { 909 metadata.setSectorIDURI(JSONObjectUtils.getURI(jsonObject, "sector_identifier_uri")); 910 oidcFields.remove("sector_identifier_uri"); 911 } 912 913 if (jsonObject.containsKey("request_uris")) { 914 915 Set<URI> requestURIs = new LinkedHashSet<>(); 916 917 for (String uriString : JSONObjectUtils.getStringArray(jsonObject, "request_uris")) { 918 919 try { 920 requestURIs.add(new URI(uriString)); 921 922 } catch (URISyntaxException e) { 923 924 throw new ParseException("Invalid \"request_uris\" parameter"); 925 } 926 } 927 928 metadata.setRequestObjectURIs(requestURIs); 929 oidcFields.remove("request_uris"); 930 } 931 932 if (jsonObject.containsKey("request_object_signing_alg")) { 933 metadata.setRequestObjectJWSAlg(new JWSAlgorithm( 934 JSONObjectUtils.getString(jsonObject, "request_object_signing_alg"))); 935 936 oidcFields.remove("request_object_signing_alg"); 937 } 938 939 if (jsonObject.containsKey("request_object_encryption_alg")) { 940 metadata.setRequestObjectJWEAlg(new JWEAlgorithm( 941 JSONObjectUtils.getString(jsonObject, "request_object_encryption_alg"))); 942 943 oidcFields.remove("request_object_encryption_alg"); 944 } 945 946 if (jsonObject.containsKey("request_object_encryption_enc")) { 947 metadata.setRequestObjectJWEEnc(EncryptionMethod.parse( 948 JSONObjectUtils.getString(jsonObject, "request_object_encryption_enc"))); 949 950 oidcFields.remove("request_object_encryption_enc"); 951 } 952 953 if (jsonObject.containsKey("id_token_signed_response_alg")) { 954 metadata.setIDTokenJWSAlg(new JWSAlgorithm( 955 JSONObjectUtils.getString(jsonObject, "id_token_signed_response_alg"))); 956 957 oidcFields.remove("id_token_signed_response_alg"); 958 } 959 960 if (jsonObject.containsKey("id_token_encrypted_response_alg")) { 961 metadata.setIDTokenJWEAlg(new JWEAlgorithm( 962 JSONObjectUtils.getString(jsonObject, "id_token_encrypted_response_alg"))); 963 964 oidcFields.remove("id_token_encrypted_response_alg"); 965 } 966 967 if (jsonObject.containsKey("id_token_encrypted_response_enc")) { 968 metadata.setIDTokenJWEEnc(EncryptionMethod.parse( 969 JSONObjectUtils.getString(jsonObject, "id_token_encrypted_response_enc"))); 970 971 oidcFields.remove("id_token_encrypted_response_enc"); 972 } 973 974 if (jsonObject.containsKey("userinfo_signed_response_alg")) { 975 metadata.setUserInfoJWSAlg(new JWSAlgorithm( 976 JSONObjectUtils.getString(jsonObject, "userinfo_signed_response_alg"))); 977 978 oidcFields.remove("userinfo_signed_response_alg"); 979 } 980 981 if (jsonObject.containsKey("userinfo_encrypted_response_alg")) { 982 metadata.setUserInfoJWEAlg(new JWEAlgorithm( 983 JSONObjectUtils.getString(jsonObject, "userinfo_encrypted_response_alg"))); 984 985 oidcFields.remove("userinfo_encrypted_response_alg"); 986 } 987 988 if (jsonObject.containsKey("userinfo_encrypted_response_enc")) { 989 metadata.setUserInfoJWEEnc(EncryptionMethod.parse( 990 JSONObjectUtils.getString(jsonObject, "userinfo_encrypted_response_enc"))); 991 992 oidcFields.remove("userinfo_encrypted_response_enc"); 993 } 994 995 if (jsonObject.containsKey("default_max_age")) { 996 metadata.setDefaultMaxAge(JSONObjectUtils.getInt(jsonObject, "default_max_age")); 997 oidcFields.remove("default_max_age"); 998 } 999 1000 if (jsonObject.containsKey("require_auth_time")) { 1001 metadata.requiresAuthTime(JSONObjectUtils.getBoolean(jsonObject, "require_auth_time")); 1002 oidcFields.remove("require_auth_time"); 1003 } 1004 1005 if (jsonObject.containsKey("default_acr_values")) { 1006 1007 List<ACR> acrValues = new LinkedList<>(); 1008 1009 for (String acrString : JSONObjectUtils.getStringArray(jsonObject, "default_acr_values")) 1010 acrValues.add(new ACR(acrString)); 1011 1012 metadata.setDefaultACRs(acrValues); 1013 1014 oidcFields.remove("default_acr_values"); 1015 } 1016 1017 if (jsonObject.containsKey("initiate_login_uri")) { 1018 metadata.setInitiateLoginURI(JSONObjectUtils.getURI(jsonObject, "initiate_login_uri")); 1019 oidcFields.remove("initiate_login_uri"); 1020 } 1021 1022 if (jsonObject.containsKey("post_logout_redirect_uris")) { 1023 1024 Set<URI> logoutURIs = new LinkedHashSet<>(); 1025 1026 for (String uriString : JSONObjectUtils.getStringArray(jsonObject, "post_logout_redirect_uris")) { 1027 1028 try { 1029 logoutURIs.add(new URI(uriString)); 1030 1031 } catch (URISyntaxException e) { 1032 1033 throw new ParseException("Invalid \"post_logout_redirect_uris\" parameter"); 1034 } 1035 } 1036 1037 metadata.setPostLogoutRedirectionURIs(logoutURIs); 1038 oidcFields.remove("post_logout_redirect_uris"); 1039 } 1040 } catch (ParseException e) { 1041 // Insert client_client_metadata error code so that it 1042 // can be reported back to the client if we have a 1043 // registration event 1044 throw new ParseException(e.getMessage(), RegistrationError.INVALID_CLIENT_METADATA.appendDescription(": " + e.getMessage()), e.getCause()); 1045 } 1046 1047 // The remaining fields are custom 1048 metadata.setCustomFields(oidcFields); 1049 1050 return metadata; 1051 } 1052}