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