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