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