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.oauth2.sdk.client; 019 020 021import com.nimbusds.jose.EncryptionMethod; 022import com.nimbusds.jose.JWEAlgorithm; 023import com.nimbusds.jose.JWSAlgorithm; 024import com.nimbusds.jose.JWSObject; 025import com.nimbusds.jose.jwk.JWKSet; 026import com.nimbusds.jwt.SignedJWT; 027import com.nimbusds.langtag.LangTag; 028import com.nimbusds.langtag.LangTagUtils; 029import com.nimbusds.oauth2.sdk.*; 030import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod; 031import com.nimbusds.oauth2.sdk.ciba.BackChannelTokenDeliveryMode; 032import com.nimbusds.oauth2.sdk.id.Identifier; 033import com.nimbusds.oauth2.sdk.id.SoftwareID; 034import com.nimbusds.oauth2.sdk.id.SoftwareVersion; 035import com.nimbusds.oauth2.sdk.rar.AuthorizationType; 036import com.nimbusds.oauth2.sdk.util.CollectionUtils; 037import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 038import com.nimbusds.oauth2.sdk.util.StringUtils; 039import com.nimbusds.oauth2.sdk.util.URIUtils; 040import com.nimbusds.openid.connect.sdk.federation.registration.ClientRegistrationType; 041import net.minidev.json.JSONArray; 042import net.minidev.json.JSONObject; 043 044import java.net.URI; 045import java.net.URISyntaxException; 046import java.util.*; 047 048 049/** 050 * Client metadata. 051 * 052 * <p>Example client metadata, serialised to a JSON object: 053 * 054 * <pre> 055 * { 056 * "redirect_uris" : ["https://client.example.org/callback", 057 * "https://client.example.org/callback2"], 058 * "client_name" : "My Example Client", 059 * "client_name#ja-Jpan-JP" : "\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u540D", 060 * "token_endpoint_auth_method" : "client_secret_basic", 061 * "scope" : "read write dolphin", 062 * "logo_uri" : "https://client.example.org/logo.png", 063 * "jwks_uri" : "https://client.example.org/my_public_keys.jwks" 064 * } 065 * </pre> 066 * 067 * <p>Related specifications: 068 * 069 * <ul> 070 * <li>OAuth 2.0 Dynamic Client Registration Protocol (RFC 7591), section 071 * 2. 072 * <li>OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound 073 * Access Tokens (RFC 8705), sections 2.1.2 and 3.4. 074 * <li>Financial-grade API: JWT Secured Authorization Response Mode for 075 * OAuth 2.0 (JARM). 076 * <li>OAuth 2.0 Pushed Authorization Requests (RFC 9126) 077 * <li>OAuth 2.0 Rich Authorization Requests (RFC 9396), section 10. 078 * <li>OpenID Connect Client Initiated Backchannel Authentication Flow - 079 * Core 1.0 080 * <li>OpenID Connect Federation 1.0 (draft 22) 081 * </ul> 082 */ 083public class ClientMetadata { 084 085 086 /** 087 * The registered parameter names. 088 */ 089 private static final Set<String> REGISTERED_PARAMETER_NAMES; 090 091 092 /** 093 * @see RedirectURIValidator#PROHIBITED_REDIRECT_URI_SCHEMES 094 */ 095 @Deprecated 096 public static final Set<String> PROHIBITED_REDIRECT_URI_SCHEMES = RedirectURIValidator.PROHIBITED_REDIRECT_URI_SCHEMES; 097 098 099 static { 100 Set<String> p = new HashSet<>(); 101 102 p.add("redirect_uris"); 103 p.add("scope"); 104 p.add("response_types"); 105 p.add("grant_types"); 106 p.add("contacts"); 107 p.add("client_name"); 108 p.add("logo_uri"); 109 p.add("client_uri"); 110 p.add("policy_uri"); 111 p.add("tos_uri"); 112 p.add("token_endpoint_auth_method"); 113 p.add("token_endpoint_auth_signing_alg"); 114 p.add("jwks_uri"); 115 p.add("jwks"); 116 p.add("request_uris"); 117 p.add("request_object_signing_alg"); 118 p.add("request_object_encryption_alg"); 119 p.add("request_object_encryption_enc"); 120 p.add("require_pushed_authorization_requests"); 121 p.add("software_id"); 122 p.add("software_version"); 123 p.add("software_statement"); 124 p.add("tls_client_certificate_bound_access_tokens"); 125 p.add("tls_client_auth_subject_dn"); 126 p.add("tls_client_auth_san_dns"); 127 p.add("tls_client_auth_san_uri"); 128 p.add("tls_client_auth_san_ip"); 129 p.add("tls_client_auth_san_email"); 130 p.add("authorization_signed_response_alg"); 131 p.add("authorization_encrypted_response_alg"); 132 p.add("authorization_encrypted_response_enc"); 133 p.add("authorization_details_types"); 134 135 // CIBA 136 p.add("backchannel_token_delivery_mode"); 137 p.add("backchannel_client_notification_endpoint"); 138 p.add("backchannel_authentication_request_signing_alg"); 139 p.add("backchannel_user_code_parameter"); 140 141 // OIDC federation 142 p.add("organization_name"); 143 p.add("signed_jwks_uri"); 144 p.add("client_registration_types"); 145 146 REGISTERED_PARAMETER_NAMES = Collections.unmodifiableSet(p); 147 } 148 149 150 /** 151 * Redirect URIs. 152 */ 153 private Set<URI> redirectURIs; 154 155 156 /** 157 * The client OAuth 2.0 scope. 158 */ 159 private Scope scope; 160 161 162 /** 163 * The expected OAuth 2.0 response types. 164 */ 165 private Set<ResponseType> responseTypes; 166 167 168 /** 169 * The expected OAuth 2.0 grant types. 170 */ 171 private Set<GrantType> grantTypes; 172 173 174 /** 175 * Administrator email contacts for the client. 176 */ 177 private List<String> contacts; 178 179 180 /** 181 * The client name. 182 */ 183 private final Map<LangTag,String> nameEntries; 184 185 186 /** 187 * The client application logo. 188 */ 189 private final Map<LangTag,URI> logoURIEntries; 190 191 192 /** 193 * The client URI entries. 194 */ 195 private final Map<LangTag,URI> uriEntries; 196 197 198 /** 199 * The client policy for use of end-user data. 200 */ 201 private final Map<LangTag,URI> policyURIEntries; 202 203 204 /** 205 * The client terms of service. 206 */ 207 private final Map<LangTag,URI> tosURIEntries; 208 209 210 /** 211 * Token endpoint authentication method. 212 */ 213 private ClientAuthenticationMethod authMethod; 214 215 216 /** 217 * The JSON Web Signature (JWS) algorithm required for 218 * {@code private_key_jwt} and {@code client_secret_jwt} 219 * authentication at the Token endpoint. 220 */ 221 private JWSAlgorithm authJWSAlg; 222 223 224 /** 225 * URI for this client's JSON Web Key (JWK) set containing key(s) that 226 * are used in signing requests to the server and key(s) for encrypting 227 * responses. 228 */ 229 private URI jwkSetURI; 230 231 232 /** 233 * URI for this client's signed JSON Web Key (JWK) set containing 234 * key(s) that are used in signing requests to the server and key(s) 235 * for encrypting responses. Intended for use in OpenID Connect 236 * Federation 1.0. 237 */ 238 private URI signedJWKSetURI; 239 240 241 /** 242 * Client's JSON Web Key (JWK) set containing key(s) that are used in 243 * signing requests to the server and key(s) for encrypting responses. 244 * Intended as an alternative to {@link #jwkSetURI} for native clients. 245 */ 246 private JWKSet jwkSet; 247 248 249 /** 250 * Pre-registered request object URIs. 251 */ 252 private Set<URI> requestObjectURIs; 253 254 255 /** 256 * The JSON Web Signature (JWS) algorithm required for request objects 257 * sent by this client. 258 */ 259 private JWSAlgorithm requestObjectJWSAlg; 260 261 262 /** 263 * The JSON Web Encryption (JWE) algorithm required for request objects 264 * sent by this client. 265 */ 266 private JWEAlgorithm requestObjectJWEAlg; 267 268 269 /** 270 * The JSON Web Encryption (JWE) method required for request objects 271 * sent by this client. 272 */ 273 private EncryptionMethod requestObjectJWEEnc; 274 275 276 /** 277 * Identifier for the OAuth 2.0 client software. 278 */ 279 private SoftwareID softwareID; 280 281 282 /** 283 * Version identifier for the OAuth 2.0 client software. 284 */ 285 private SoftwareVersion softwareVersion; 286 287 288 /** 289 * Signed software statement. 290 */ 291 private SignedJWT softwareStatement; 292 293 294 /** 295 * Preference for TLS client certificate bound access tokens. 296 */ 297 private boolean tlsClientCertificateBoundAccessTokens = false; 298 299 300 /** 301 * The expected subject distinguished name (DN) of the client X.509 302 * certificate the in mutual TLS authentication. 303 */ 304 private String tlsClientAuthSubjectDN = null; 305 306 307 /** 308 * The expected dNSName SAN entry in the X.509 certificate, which 309 * the OAuth client will use in mutual TLS authentication. 310 */ 311 private String tlsClientAuthSanDNS = null; 312 313 314 /** 315 * The expected uniformResourceIdentifier SAN entry in the X.509 316 * certificate, which the OAuth client will use in mutual TLS 317 * authentication. 318 */ 319 private String tlsClientAuthSanURI = null; 320 321 322 /** 323 * The expected iPAddress SAN entry in the X.509 certificate, which 324 * the OAuth client will use in mutual TLS authentication. 325 */ 326 private String tlsClientAuthSanIP = null; 327 328 329 /** 330 * The expected rfc822Name SAN entry in the X.509 certificate, which 331 * the OAuth client will use in mutual TLS authentication. 332 */ 333 private String tlsClientAuthSanEmail = null; 334 335 336 /** 337 * The JWS algorithm for JWT-encoded authorisation responses. 338 */ 339 private JWSAlgorithm authzJWSAlg; 340 341 342 /** 343 * The JWE algorithm for JWT-encoded authorisation responses. 344 */ 345 private JWEAlgorithm authzJWEAlg; 346 347 348 /** 349 * The encryption method for JWT-encoded authorisation responses. 350 */ 351 private EncryptionMethod authzJWEEnc; 352 353 354 /** 355 * If {@code true} PAR is required, else not. 356 */ 357 private boolean requirePAR = false; 358 359 360 /** 361 * The authorisation details types. 362 */ 363 private List<AuthorizationType> authzTypes; 364 365 366 /** 367 * The CIBA token delivery mode. 368 */ 369 private BackChannelTokenDeliveryMode backChannelTokenDeliveryMode; 370 371 372 /** 373 * The CIBA client notification endpoint for the ping or push token 374 * delivery modes. 375 */ 376 private URI backChannelClientNotificationEndpoint; 377 378 379 /** 380 * The JWS algorithm for signed CIBA requests. 381 */ 382 private JWSAlgorithm backChannelAuthRequestJWSAlg; 383 384 385 /** 386 * Support for the {@code user_code} CIBA request parameter. 387 */ 388 private boolean backChannelUserCodeParam = false; 389 390 391 /** 392 * The supported OpenID Connect Federation 1.0 client registration 393 * types. 394 */ 395 private List<ClientRegistrationType> clientRegistrationTypes; 396 397 398 /** 399 * The organisation name in OpenID Connect Federation 1.0. 400 */ 401 private String organizationName; 402 403 404 /** 405 * The custom metadata fields. 406 */ 407 private JSONObject customFields; 408 409 410 /** 411 * Creates a new OAuth 2.0 client metadata instance. 412 */ 413 public ClientMetadata() { 414 415 nameEntries = new HashMap<>(); 416 logoURIEntries = new HashMap<>(); 417 uriEntries = new HashMap<>(); 418 policyURIEntries = new HashMap<>(); 419 tosURIEntries = new HashMap<>(); 420 customFields = new JSONObject(); 421 } 422 423 424 /** 425 * Creates a shallow copy of the specified OAuth 2.0 client metadata 426 * instance. 427 * 428 * @param metadata The client metadata to copy. Must not be 429 * {@code null}. 430 */ 431 public ClientMetadata(final ClientMetadata metadata) { 432 433 redirectURIs = metadata.getRedirectionURIs(); 434 scope = metadata.getScope(); 435 responseTypes = metadata.getResponseTypes(); 436 grantTypes = metadata.getGrantTypes(); 437 contacts = metadata.getEmailContacts(); 438 nameEntries = metadata.getNameEntries(); 439 logoURIEntries = metadata.getLogoURIEntries(); 440 uriEntries = metadata.getURIEntries(); 441 policyURIEntries = metadata.getPolicyURIEntries(); 442 tosURIEntries = metadata.getTermsOfServiceURIEntries(); 443 authMethod = metadata.getTokenEndpointAuthMethod(); 444 authJWSAlg = metadata.getTokenEndpointAuthJWSAlg(); 445 jwkSetURI = metadata.getJWKSetURI(); 446 signedJWKSetURI = metadata.getSignedJWKSetURI(); 447 jwkSet = metadata.getJWKSet(); 448 requestObjectURIs = metadata.getRequestObjectURIs(); 449 requestObjectJWSAlg = metadata.getRequestObjectJWSAlg(); 450 requestObjectJWEAlg = metadata.getRequestObjectJWEAlg(); 451 requestObjectJWEEnc = metadata.getRequestObjectJWEEnc(); 452 softwareID = metadata.getSoftwareID(); 453 softwareVersion = metadata.getSoftwareVersion(); 454 softwareStatement = metadata.getSoftwareStatement(); 455 tlsClientCertificateBoundAccessTokens = metadata.getTLSClientCertificateBoundAccessTokens(); 456 tlsClientAuthSubjectDN = metadata.getTLSClientAuthSubjectDN(); 457 tlsClientAuthSanDNS = metadata.getTLSClientAuthSanDNS(); 458 tlsClientAuthSanURI = metadata.getTLSClientAuthSanURI(); 459 tlsClientAuthSanIP = metadata.getTLSClientAuthSanIP(); 460 tlsClientAuthSanEmail = metadata.getTLSClientAuthSanEmail(); 461 authzJWSAlg = metadata.getAuthorizationJWSAlg(); 462 authzJWEAlg = metadata.getAuthorizationJWEAlg(); 463 authzJWEEnc = metadata.getAuthorizationJWEEnc(); 464 requirePAR = metadata.requiresPushedAuthorizationRequests(); 465 authzTypes = metadata.getAuthorizationDetailsTypes(); 466 backChannelTokenDeliveryMode = metadata.getBackChannelTokenDeliveryMode(); 467 backChannelClientNotificationEndpoint = metadata.getBackChannelClientNotificationEndpoint(); 468 backChannelAuthRequestJWSAlg = metadata.getBackChannelAuthRequestJWSAlg(); 469 backChannelUserCodeParam = metadata.supportsBackChannelUserCodeParam(); 470 clientRegistrationTypes = metadata.getClientRegistrationTypes(); 471 organizationName = metadata.getOrganizationName(); 472 customFields = metadata.getCustomFields(); 473 } 474 475 476 /** 477 * Gets the registered (standard) OAuth 2.0 client metadata parameter 478 * names. 479 * 480 * @return The registered parameter names, as an unmodifiable set. 481 */ 482 public static Set<String> getRegisteredParameterNames() { 483 484 return REGISTERED_PARAMETER_NAMES; 485 } 486 487 488 /** 489 * Gets the redirection URIs for this client. Corresponds to the 490 * {@code redirect_uris} client metadata field. 491 * 492 * @return The redirection URIs, {@code null} if not specified. 493 */ 494 public Set<URI> getRedirectionURIs() { 495 496 return redirectURIs; 497 } 498 499 500 /** 501 * Gets one of the redirection URIs for this client. Corresponds to the 502 * {@code redirect_uris} client metadata field. 503 * 504 * @return The redirection URI, {@code null} if not specified. 505 */ 506 public URI getRedirectionURI() { 507 508 if (redirectURIs != null && ! redirectURIs.isEmpty()) { 509 return redirectURIs.iterator().next(); 510 } else { 511 return null; 512 } 513 } 514 515 516 /** 517 * Gets the redirection URIs for this client as strings. Corresponds to 518 * the {@code redirect_uris} client metadata field. 519 * 520 * <p>This short-hand method is intended to enable string-based URI 521 * comparison. 522 * 523 * @return The redirection URIs as strings, {@code null} if not 524 * specified. 525 */ 526 public Set<String> getRedirectionURIStrings() { 527 528 if (redirectURIs == null) 529 return null; 530 531 Set<String> uriStrings = new HashSet<>(); 532 533 for (URI uri: redirectURIs) 534 uriStrings.add(uri.toString()); 535 536 return uriStrings; 537 } 538 539 540 /** 541 * Sets the redirection URIs for this client. Corresponds to the 542 * {@code redirect_uris} client metadata field. 543 * 544 * @param redirectURIs The redirection URIs, {@code null} if not 545 * specified. Valid redirection URIs must not 546 * contain a fragment. 547 */ 548 public void setRedirectionURIs(final Set<URI> redirectURIs) { 549 550 if (redirectURIs != null) { 551 // check URIs 552 for (URI uri: redirectURIs) { 553 if (uri == null) { 554 throw new IllegalArgumentException("The redirect_uri must not be null"); 555 } 556 RedirectURIValidator.ensureLegal(uri); 557 } 558 this.redirectURIs = Collections.unmodifiableSet(redirectURIs); 559 } else { 560 this.redirectURIs = null; 561 } 562 } 563 564 565 /** 566 * Sets a single redirection URI for this client. Corresponds to the 567 * {@code redirect_uris} client metadata field. 568 * 569 * @param redirectURI The redirection URIs, {@code null} if not 570 * specified. A valid redirection URI must not 571 * contain a fragment. 572 */ 573 public void setRedirectionURI(final URI redirectURI) { 574 575 setRedirectionURIs(redirectURI != null ? Collections.singleton(redirectURI) : null); 576 } 577 578 579 /** 580 * Gets the scope values that the client can use when requesting access 581 * tokens. Corresponds to the {@code scope} client metadata field. 582 * 583 * @return The scope, {@code null} if not specified. 584 */ 585 public Scope getScope() { 586 587 return scope; 588 } 589 590 591 /** 592 * Checks if the scope matadata field is set and contains the specified 593 * scope value. 594 * 595 * @param scopeValue The scope value. Must not be {@code null}. 596 * 597 * @return {@code true} if the scope value is contained, else 598 * {@code false}. 599 */ 600 public boolean hasScopeValue(final Scope.Value scopeValue) { 601 602 return scope != null && scope.contains(scopeValue); 603 } 604 605 606 /** 607 * Sets the scope values that the client can use when requesting access 608 * tokens. Corresponds to the {@code scope} client metadata field. 609 * 610 * @param scope The scope, {@code null} if not specified. 611 */ 612 public void setScope(final Scope scope) { 613 614 this.scope = scope; 615 } 616 617 618 /** 619 * Gets the expected OAuth 2.0 response types. Corresponds to the 620 * {@code response_types} client metadata field. 621 * 622 * @return The response types, {@code null} if not specified. 623 */ 624 public Set<ResponseType> getResponseTypes() { 625 626 return responseTypes; 627 } 628 629 630 /** 631 * Sets the expected OAuth 2.0 response types. Corresponds to the 632 * {@code response_types} client metadata field. 633 * 634 * @param responseTypes The response types, {@code null} if not 635 * specified. 636 */ 637 public void setResponseTypes(final Set<ResponseType> responseTypes) { 638 639 this.responseTypes = responseTypes; 640 } 641 642 643 /** 644 * Gets the expected OAuth 2.0 grant types. Corresponds to the 645 * {@code grant_types} client metadata field. 646 * 647 * @return The grant types, {@code null} if not specified. 648 */ 649 public Set<GrantType> getGrantTypes() { 650 651 return grantTypes; 652 } 653 654 655 /** 656 * Sets the expected OAuth 2.0 grant types. Corresponds to the 657 * {@code grant_types} client metadata field. 658 * 659 * @param grantTypes The grant types, {@code null} if not specified. 660 */ 661 public void setGrantTypes(final Set<GrantType> grantTypes) { 662 663 this.grantTypes = grantTypes; 664 } 665 666 667 /** 668 * Gets the administrator email contacts for the client. Corresponds to 669 * the {@code contacts} client metadata field. 670 * 671 * @return The administrator email contacts, {@code null} if not 672 * specified. 673 */ 674 public List<String> getEmailContacts() { 675 676 return contacts; 677 } 678 679 680 /** 681 * Sets the administrator email contacts for the client. Corresponds to 682 * the {@code contacts} client metadata field. 683 * 684 * @param contacts The administrator email contacts, {@code null} if 685 * not specified. 686 */ 687 public void setEmailContacts(final List<String> contacts) { 688 689 this.contacts = contacts; 690 } 691 692 693 /** 694 * Gets the client name. Corresponds to the {@code client_name} client 695 * metadata field, with no language tag. 696 * 697 * @return The client name, {@code null} if not specified. 698 */ 699 public String getName() { 700 701 return getName(null); 702 } 703 704 705 /** 706 * Gets the client name. Corresponds to the {@code client_name} client 707 * metadata field, with an optional language tag. 708 * 709 * @param langTag The language tag of the entry, {@code null} to get 710 * the non-tagged entry. 711 * 712 * @return The client name, {@code null} if not specified. 713 */ 714 public String getName(final LangTag langTag) { 715 716 return nameEntries.get(langTag); 717 } 718 719 720 /** 721 * Gets the client name entries. Corresponds to the {@code client_name} 722 * client metadata field. 723 * 724 * @return The client name entries, empty map if none. 725 */ 726 public Map<LangTag,String> getNameEntries() { 727 728 return nameEntries; 729 } 730 731 732 /** 733 * Sets the client name. Corresponds to the {@code client_name} client 734 * metadata field, with no language tag. 735 * 736 * @param name The client name, {@code null} if not specified. 737 */ 738 public void setName(final String name) { 739 740 nameEntries.put(null, name); 741 } 742 743 744 /** 745 * Sets the client name. Corresponds to the {@code client_name} client 746 * metadata field, with an optional language tag. 747 * 748 * @param name The client name. Must not be {@code null}. 749 * @param langTag The language tag, {@code null} if not specified. 750 */ 751 public void setName(final String name, final LangTag langTag) { 752 753 nameEntries.put(langTag, name); 754 } 755 756 757 /** 758 * Gets the client application logo. Corresponds to the 759 * {@code logo_uri} client metadata field, with no language 760 * tag. 761 * 762 * @return The logo URI, {@code null} if not specified. 763 */ 764 public URI getLogoURI() { 765 766 return getLogoURI(null); 767 } 768 769 770 /** 771 * Gets the client application logo. Corresponds to the 772 * {@code logo_uri} client metadata field, with an optional 773 * language tag. 774 * 775 * @param langTag The language tag, {@code null} if not specified. 776 * 777 * @return The logo URI, {@code null} if not specified. 778 */ 779 public URI getLogoURI(final LangTag langTag) { 780 781 return logoURIEntries.get(langTag); 782 } 783 784 785 /** 786 * Gets the client application logo entries. Corresponds to the 787 * {@code logo_uri} client metadata field. 788 * 789 * @return The logo URI entries, empty map if none. 790 */ 791 public Map<LangTag,URI> getLogoURIEntries() { 792 793 return logoURIEntries; 794 } 795 796 797 /** 798 * Sets the client application logo. Corresponds to the 799 * {@code logo_uri} client metadata field, with no language 800 * tag. 801 * 802 * @param logoURI The logo URI, {@code null} if not specified. 803 */ 804 public void setLogoURI(final URI logoURI) { 805 806 logoURIEntries.put(null, logoURI); 807 } 808 809 810 /** 811 * Sets the client application logo. Corresponds to the 812 * {@code logo_uri} client metadata field, with an optional 813 * language tag. 814 * 815 * @param logoURI The logo URI. Must not be {@code null}. 816 * @param langTag The language tag, {@code null} if not specified. 817 */ 818 public void setLogoURI(final URI logoURI, final LangTag langTag) { 819 820 logoURIEntries.put(langTag, logoURI); 821 } 822 823 824 /** 825 * Gets the client home page. Corresponds to the {@code client_uri} 826 * client metadata field, with no language tag. 827 * 828 * @return The client URI, {@code null} if not specified. 829 */ 830 public URI getURI() { 831 832 return getURI(null); 833 } 834 835 836 /** 837 * Gets the client home page. Corresponds to the {@code client_uri} 838 * client metadata field, with an optional language tag. 839 * 840 * @param langTag The language tag, {@code null} if not specified. 841 * 842 * @return The client URI, {@code null} if not specified. 843 */ 844 public URI getURI(final LangTag langTag) { 845 846 return uriEntries.get(langTag); 847 } 848 849 850 /** 851 * Gets the client home page entries. Corresponds to the 852 * {@code client_uri} client metadata field. 853 * 854 * @return The client URI entries, empty map if none. 855 */ 856 public Map<LangTag,URI> getURIEntries() { 857 858 return uriEntries; 859 } 860 861 862 /** 863 * Sets the client home page. Corresponds to the {@code client_uri} 864 * client metadata field, with no language tag. 865 * 866 * @param uri The client URI, {@code null} if not specified. The URI 867 * scheme must be https or http. 868 */ 869 public void setURI(final URI uri) { 870 871 URIUtils.ensureSchemeIsHTTPSorHTTP(uri); 872 uriEntries.put(null, uri); 873 } 874 875 876 /** 877 * Sets the client home page. Corresponds to the {@code client_uri} 878 * client metadata field, with an optional language tag. 879 * 880 * @param uri The URI. The URI scheme must be https or http. Must 881 * not be {@code null}. 882 * @param langTag The language tag, {@code null} if not specified. 883 */ 884 public void setURI(final URI uri, final LangTag langTag) { 885 886 URIUtils.ensureSchemeIsHTTPSorHTTP(uri); 887 uriEntries.put(langTag, uri); 888 } 889 890 891 /** 892 * Gets the client policy for use of end-user data. Corresponds to the 893 * {@code policy_uri} client metadata field, with no language 894 * tag. 895 * 896 * @return The policy URI, {@code null} if not specified. 897 */ 898 public URI getPolicyURI() { 899 900 return getPolicyURI(null); 901 } 902 903 904 /** 905 * Gets the client policy for use of end-user data. Corresponds to the 906 * {@code policy_uri} client metadata field, with an optional 907 * language tag. 908 * 909 * @param langTag The language tag, {@code null} if not specified. 910 * 911 * @return The policy URI, {@code null} if not specified. 912 */ 913 public URI getPolicyURI(final LangTag langTag) { 914 915 return policyURIEntries.get(langTag); 916 } 917 918 919 /** 920 * Gets the client policy entries for use of end-user data. 921 * Corresponds to the {@code policy_uri} client metadata field. 922 * 923 * @return The policy URI entries, empty map if none. 924 */ 925 public Map<LangTag,URI> getPolicyURIEntries() { 926 927 return policyURIEntries; 928 } 929 930 931 /** 932 * Sets the client policy for use of end-user data. Corresponds to the 933 * {@code policy_uri} client metadata field, with no language 934 * tag. 935 * 936 * @param policyURI The policy URI, {@code null} if not specified. The 937 * URI scheme must be https or http. 938 */ 939 public void setPolicyURI(final URI policyURI) { 940 941 URIUtils.ensureSchemeIsHTTPSorHTTP(policyURI); 942 policyURIEntries.put(null, policyURI); 943 } 944 945 946 /** 947 * Sets the client policy for use of end-user data. Corresponds to the 948 * {@code policy_uri} client metadata field, with an optional 949 * language tag. 950 * 951 * @param policyURI The policy URI. The URI scheme must be https or 952 * http. Must not be {@code null}. 953 * @param langTag The language tag, {@code null} if not specified. 954 */ 955 public void setPolicyURI(final URI policyURI, final LangTag langTag) { 956 957 URIUtils.ensureSchemeIsHTTPSorHTTP(policyURI); 958 policyURIEntries.put(langTag, policyURI); 959 } 960 961 962 /** 963 * Gets the client's terms of service. Corresponds to the 964 * {@code tos_uri} client metadata field, with no language 965 * tag. 966 * 967 * @return The terms of service URI, {@code null} if not specified. 968 */ 969 public URI getTermsOfServiceURI() { 970 971 return getTermsOfServiceURI(null); 972 } 973 974 975 /** 976 * Gets the client's terms of service. Corresponds to the 977 * {@code tos_uri} client metadata field, with an optional 978 * language tag. 979 * 980 * @param langTag The language tag, {@code null} if not specified. 981 * 982 * @return The terms of service URI, {@code null} if not specified. 983 */ 984 public URI getTermsOfServiceURI(final LangTag langTag) { 985 986 return tosURIEntries.get(langTag); 987 } 988 989 990 /** 991 * Gets the client's terms of service entries. Corresponds to the 992 * {@code tos_uri} client metadata field. 993 * 994 * @return The terms of service URI entries, empty map if none. 995 */ 996 public Map<LangTag,URI> getTermsOfServiceURIEntries() { 997 998 return tosURIEntries; 999 } 1000 1001 1002 /** 1003 * Sets the client's terms of service. Corresponds to the 1004 * {@code tos_uri} client metadata field, with no language 1005 * tag. 1006 * 1007 * @param tosURI The terms of service URI, {@code null} if not 1008 * specified. The URI scheme must be https or http. 1009 */ 1010 public void setTermsOfServiceURI(final URI tosURI) { 1011 1012 URIUtils.ensureSchemeIsHTTPSorHTTP(tosURI); 1013 tosURIEntries.put(null, tosURI); 1014 } 1015 1016 1017 /** 1018 * Sets the client's terms of service. Corresponds to the 1019 * {@code tos_uri} client metadata field, with an optional 1020 * language tag. 1021 * 1022 * @param tosURI The terms of service URI. The URI scheme must not be 1023 * https or http. Must not be {@code null}. 1024 * @param langTag The language tag, {@code null} if not specified. 1025 */ 1026 public void setTermsOfServiceURI(final URI tosURI, final LangTag langTag) { 1027 1028 URIUtils.ensureSchemeIsHTTPSorHTTP(tosURI); 1029 tosURIEntries.put(langTag, tosURI); 1030 } 1031 1032 1033 /** 1034 * Gets the Token endpoint authentication method. Corresponds to the 1035 * {@code token_endpoint_auth_method} client metadata field. 1036 * 1037 * @return The Token endpoint authentication method, {@code null} if 1038 * not specified. 1039 */ 1040 public ClientAuthenticationMethod getTokenEndpointAuthMethod() { 1041 1042 return authMethod; 1043 } 1044 1045 1046 /** 1047 * Sets the Token endpoint authentication method. Corresponds to the 1048 * {@code token_endpoint_auth_method} client metadata field. 1049 * 1050 * @param authMethod The Token endpoint authentication method, 1051 * {@code null} if not specified. 1052 */ 1053 public void setTokenEndpointAuthMethod(final ClientAuthenticationMethod authMethod) { 1054 1055 this.authMethod = authMethod; 1056 } 1057 1058 1059 /** 1060 * Gets the JSON Web Signature (JWS) algorithm required for 1061 * {@code private_key_jwt} and {@code client_secret_jwt} 1062 * authentication at the Token endpoint. Corresponds to the 1063 * {@code token_endpoint_auth_signing_alg} client metadata field. 1064 * 1065 * @return The JWS algorithm, {@code null} if not specified. 1066 */ 1067 public JWSAlgorithm getTokenEndpointAuthJWSAlg() { 1068 1069 return authJWSAlg; 1070 } 1071 1072 1073 /** 1074 * Sets the JSON Web Signature (JWS) algorithm required for 1075 * {@code private_key_jwt} and {@code client_secret_jwt} 1076 * authentication at the Token endpoint. Corresponds to the 1077 * {@code token_endpoint_auth_signing_alg} client metadata field. 1078 * 1079 * @param authJWSAlg The JWS algorithm, {@code null} if not specified. 1080 */ 1081 public void setTokenEndpointAuthJWSAlg(final JWSAlgorithm authJWSAlg) { 1082 1083 this.authJWSAlg = authJWSAlg; 1084 } 1085 1086 1087 /** 1088 * Gets the URI for this client's JSON Web Key (JWK) set containing 1089 * key(s) that are used in signing requests to the server and key(s) 1090 * for encrypting responses. Corresponds to the {@code jwks_uri} client 1091 * metadata field. 1092 * 1093 * @return The JWK set URI, {@code null} if not specified. 1094 */ 1095 public URI getJWKSetURI() { 1096 1097 return jwkSetURI; 1098 } 1099 1100 1101 /** 1102 * Sets the URI for this client's JSON Web Key (JWK) set containing 1103 * key(s) that are used in signing requests to the server and key(s) 1104 * for encrypting responses. Corresponds to the {@code jwks_uri} client 1105 * metadata field. 1106 * 1107 * @param jwkSetURI The JWK set URI, {@code null} if not specified. 1108 */ 1109 public void setJWKSetURI(final URI jwkSetURI) { 1110 1111 this.jwkSetURI = jwkSetURI; 1112 } 1113 1114 1115 /** 1116 * Gets the URI for this client's signed JSON Web Key (JWK) set 1117 * containing key(s) that are used in signing requests to the server 1118 * and key(s) for encrypting responses. Corresponds to the 1119 * {@code signed_jwks_uri} client metadata field. Intended for use in 1120 * OpenID Connect Federation 1.0. 1121 * 1122 * @return The signed JWK set URI, {@code null} if not specified. 1123 */ 1124 public URI getSignedJWKSetURI() { 1125 1126 return signedJWKSetURI; 1127 } 1128 1129 1130 /** 1131 * Sets the URI for this client's signed JSON Web Key (JWK) set 1132 * containing key(s) that are used in signing requests to the server 1133 * and key(s) for encrypting responses. Corresponds to the 1134 * {@code signed_jwks_uri} client metadata field. Intended for use in 1135 * OpenID Connect Federation 1.0. 1136 * 1137 * @param signedJWKSetURI The signed JWK set URI, {@code null} if not 1138 * specified. 1139 */ 1140 public void setSignedJWKSetURI(final URI signedJWKSetURI) { 1141 1142 this.signedJWKSetURI = signedJWKSetURI; 1143 } 1144 1145 1146 /** 1147 * Gets this client's JSON Web Key (JWK) set containing key(s) that are 1148 * used in signing requests to the server and key(s) for encrypting 1149 * responses. Intended as an alternative to {@link #getJWKSetURI} for 1150 * native clients. Corresponds to the {@code jwks} client metadata 1151 * field. 1152 * 1153 * @return The JWK set, {@code null} if not specified. 1154 */ 1155 public JWKSet getJWKSet() { 1156 1157 return jwkSet; 1158 } 1159 1160 1161 /** 1162 * Sets this client's JSON Web Key (JWK) set containing key(s) that are 1163 * used in signing requests to the server and key(s) for encrypting 1164 * responses. Intended as an alternative to {@link #getJWKSetURI} for 1165 * native clients. Corresponds to the {@code jwks} client metadata 1166 * field. 1167 * 1168 * @param jwkSet The JWK set, {@code null} if not specified. 1169 */ 1170 public void setJWKSet(final JWKSet jwkSet) { 1171 1172 this.jwkSet = jwkSet; 1173 } 1174 1175 1176 /** 1177 * Gets the pre-registered request object URIs. Corresponds to the 1178 * {@code request_uris} client metadata field. 1179 * 1180 * @return The request object URIs, {@code null} if not specified. 1181 */ 1182 public Set<URI> getRequestObjectURIs() { 1183 1184 return requestObjectURIs; 1185 } 1186 1187 1188 /** 1189 * Sets the pre-registered request object URIs. Corresponds to the 1190 * {@code request_uris} client metadata field. 1191 * 1192 * @param requestObjectURIs The request object URIs, {@code null} if 1193 * not specified. 1194 */ 1195 public void setRequestObjectURIs(final Set<URI> requestObjectURIs) { 1196 1197 this.requestObjectURIs = requestObjectURIs; 1198 } 1199 1200 1201 /** 1202 * Gets the JSON Web Signature (JWS) algorithm required for request 1203 * objects sent by this client. Corresponds to the 1204 * {@code request_object_signing_alg} client metadata field. 1205 * 1206 * @return The JWS algorithm, {@code null} if not specified. 1207 */ 1208 public JWSAlgorithm getRequestObjectJWSAlg() { 1209 1210 return requestObjectJWSAlg; 1211 } 1212 1213 1214 /** 1215 * Sets the JSON Web Signature (JWS) algorithm required for request 1216 * objects sent by this client. Corresponds to the 1217 * {@code request_object_signing_alg} client metadata field. 1218 * 1219 * @param requestObjectJWSAlg The JWS algorithm, {@code null} if not 1220 * specified. 1221 */ 1222 public void setRequestObjectJWSAlg(final JWSAlgorithm requestObjectJWSAlg) { 1223 1224 this.requestObjectJWSAlg = requestObjectJWSAlg; 1225 } 1226 1227 1228 /** 1229 * Gets the JSON Web Encryption (JWE) algorithm required for request 1230 * objects sent by this client. Corresponds to the 1231 * {@code request_object_encryption_alg} client metadata field. 1232 * 1233 * @return The JWE algorithm, {@code null} if not specified. 1234 */ 1235 public JWEAlgorithm getRequestObjectJWEAlg() { 1236 1237 return requestObjectJWEAlg; 1238 } 1239 1240 1241 /** 1242 * Sets the JSON Web Encryption (JWE) algorithm required for request 1243 * objects sent by this client. Corresponds to the 1244 * {@code request_object_encryption_alg} client metadata field. 1245 * 1246 * @param requestObjectJWEAlg The JWE algorithm, {@code null} if not 1247 * specified. 1248 */ 1249 public void setRequestObjectJWEAlg(final JWEAlgorithm requestObjectJWEAlg) { 1250 1251 this.requestObjectJWEAlg = requestObjectJWEAlg; 1252 } 1253 1254 1255 /** 1256 * Gets the JSON Web Encryption (JWE) method required for request 1257 * objects sent by this client. Corresponds to the 1258 * {@code request_object_encryption_enc} client metadata field. 1259 * 1260 * @return The JWE method, {@code null} if not specified. 1261 */ 1262 public EncryptionMethod getRequestObjectJWEEnc() { 1263 1264 return requestObjectJWEEnc; 1265 } 1266 1267 1268 /** 1269 * Sets the JSON Web Encryption (JWE) method required for request 1270 * objects sent by this client. Corresponds to the 1271 * {@code request_object_encryption_enc} client metadata field. 1272 * 1273 * @param requestObjectJWEEnc The JWE method, {@code null} if not 1274 * specified. 1275 */ 1276 public void setRequestObjectJWEEnc(final EncryptionMethod requestObjectJWEEnc) { 1277 1278 this.requestObjectJWEEnc = requestObjectJWEEnc; 1279 } 1280 1281 1282 /** 1283 * Gets the identifier for the OAuth 2.0 client software. Corresponds 1284 * to the {@code software_id} client metadata field. 1285 * 1286 * @return The software identifier, {@code null} if not specified. 1287 */ 1288 public SoftwareID getSoftwareID() { 1289 1290 return softwareID; 1291 } 1292 1293 1294 /** 1295 * Sets the identifier for the OAuth 2.0 client software. Corresponds 1296 * to the {@code software_id} client metadata field. 1297 * 1298 * @param softwareID The software identifier, {@code null} if not 1299 * specified. 1300 */ 1301 public void setSoftwareID(final SoftwareID softwareID) { 1302 1303 this.softwareID = softwareID; 1304 } 1305 1306 1307 /** 1308 * Gets the version identifier for the OAuth 2.0 client software. 1309 * Corresponds to the {@code software_version} client metadata field. 1310 * 1311 * @return The version identifier, {@code null} if not specified. 1312 */ 1313 public SoftwareVersion getSoftwareVersion() { 1314 1315 return softwareVersion; 1316 } 1317 1318 1319 /** 1320 * Sets the version identifier for the OAuth 2.0 client software. 1321 * Corresponds to the {@code software_version} client metadata field. 1322 * 1323 * @param softwareVersion The version identifier, {@code null} if not 1324 * specified. 1325 */ 1326 public void setSoftwareVersion(final SoftwareVersion softwareVersion) { 1327 1328 this.softwareVersion = softwareVersion; 1329 } 1330 1331 1332 /** 1333 * Gets the software statement. Corresponds to the 1334 * {@code software_statement} client metadata field. 1335 * 1336 * @return The signed software statement, {@code null} if not 1337 * specified. 1338 */ 1339 public SignedJWT getSoftwareStatement() { 1340 1341 return softwareStatement; 1342 } 1343 1344 1345 /** 1346 * Sets the software statement. Corresponds to the 1347 * {@code software_statement} client metadata field. 1348 * 1349 * @param softwareStatement The signed software statement, {@code null} 1350 * if not specified. 1351 */ 1352 public void setSoftwareStatement(final SignedJWT softwareStatement) { 1353 1354 if (softwareStatement != null && softwareStatement.getState().equals(JWSObject.State.UNSIGNED)) { 1355 throw new IllegalArgumentException("The software statement must be signed"); 1356 } 1357 1358 this.softwareStatement = softwareStatement; 1359 } 1360 1361 1362 /** 1363 * Sets the preference for TLS client certificate bound access tokens. 1364 * Corresponds to the 1365 * {@code tls_client_certificate_bound_access_tokens} client metadata 1366 * field. 1367 * 1368 * @return {@code true} indicates a preference for TLS client 1369 * certificate bound access tokens, {@code false} if none. 1370 */ 1371 public boolean getTLSClientCertificateBoundAccessTokens() { 1372 1373 return tlsClientCertificateBoundAccessTokens; 1374 } 1375 1376 1377 /** 1378 * Gets the preference for TLS client certificate bound access tokens. 1379 * Corresponds to the 1380 * {@code tls_client_certificate_bound_access_tokens} client metadata 1381 * field. 1382 * 1383 * @param tlsClientCertBoundTokens {@code true} indicates a preference 1384 * for TLS client certificate bound 1385 * access tokens, {@code false} if 1386 * none. 1387 */ 1388 public void setTLSClientCertificateBoundAccessTokens(final boolean tlsClientCertBoundTokens) { 1389 1390 tlsClientCertificateBoundAccessTokens = tlsClientCertBoundTokens; 1391 } 1392 1393 1394 /** 1395 * Sets the preference for TLS client certificate bound access tokens. 1396 * Corresponds to the 1397 * {@code tls_client_certificate_bound_access_tokens} client metadata 1398 * field. 1399 * 1400 * @return {@code true} indicates a preference for TLS client 1401 * certificate bound access tokens, {@code false} if none. 1402 */ 1403 @Deprecated 1404 public boolean getMutualTLSSenderConstrainedAccessTokens() { 1405 1406 return tlsClientCertificateBoundAccessTokens; 1407 } 1408 1409 1410 /** 1411 * Gets the preference for TLS client certificate bound access tokens. 1412 * Corresponds to the 1413 * {@code tls_client_certificate_bound_access_tokens} client metadata 1414 * field. 1415 * 1416 * @param tlsSenderAccessTokens {@code true} indicates a preference for 1417 * TLS client certificate bound access 1418 * tokens, {@code false} if none. 1419 */ 1420 @Deprecated 1421 public void setMutualTLSSenderConstrainedAccessTokens(final boolean tlsSenderAccessTokens) { 1422 1423 tlsClientCertificateBoundAccessTokens = tlsSenderAccessTokens; 1424 } 1425 1426 1427 /** 1428 * Gets the expected subject distinguished name (DN) of the client 1429 * X.509 certificate in mutual TLS authentication. Corresponds to the 1430 * {@code tls_client_auth_subject_dn} client metadata field. 1431 * 1432 * @return The expected subject distinguished name (DN) of the client 1433 * X.509 certificate, {@code null} if not specified. 1434 */ 1435 public String getTLSClientAuthSubjectDN() { 1436 1437 return tlsClientAuthSubjectDN; 1438 } 1439 1440 1441 /** 1442 * Sets the expected subject distinguished name (DN) of the client 1443 * X.509 certificate in mutual TLS authentication. Corresponds to the 1444 * {@code tls_client_auth_subject_dn} client metadata field. 1445 * 1446 * @param subjectDN The expected subject distinguished name (DN) of the 1447 * client X.509 certificate, {@code null} if not 1448 * specified. 1449 */ 1450 public void setTLSClientAuthSubjectDN(final String subjectDN) { 1451 1452 this.tlsClientAuthSubjectDN = subjectDN; 1453 } 1454 1455 1456 /** 1457 * Gets the expected dNSName SAN entry in the X.509 certificate, which 1458 * the OAuth client will use in mutual TLS authentication. Corresponds 1459 * to the {@code tls_client_auth_san_dns} client metadata field. 1460 * 1461 * @return The expected dNSName SAN entry in the X.509 certificate, 1462 * {@code null} if not specified. 1463 */ 1464 public String getTLSClientAuthSanDNS() { 1465 1466 return tlsClientAuthSanDNS; 1467 } 1468 1469 1470 /** 1471 * Sets the expected dNSName SAN entry in the X.509 certificate, which 1472 * the OAuth client will use in mutual TLS authentication. Corresponds 1473 * to the {@code tls_client_auth_san_dns} client metadata field. 1474 * 1475 * @param dns The expected dNSName SAN entry in the X.509 certificate, 1476 * {@code null} if not specified. 1477 */ 1478 public void setTLSClientAuthSanDNS(final String dns) { 1479 1480 this.tlsClientAuthSanDNS = dns; 1481 } 1482 1483 1484 /** 1485 * Gets the expected uniformResourceIdentifier SAN entry in the X.509 1486 * certificate, which the OAuth client will use in mutual TLS 1487 * authentication. Corresponds to the {@code tls_client_auth_san_uri} 1488 * client metadata field. 1489 * 1490 * @return The expected uniformResourceIdentifier SAN entry in the X.509 1491 * certificate, {@code null} if not specified. 1492 */ 1493 public String getTLSClientAuthSanURI() { 1494 1495 return tlsClientAuthSanURI; 1496 } 1497 1498 1499 /** 1500 * Sets the expected uniformResourceIdentifier SAN entry in the X.509 1501 * certificate, which the OAuth client will use in mutual TLS 1502 * authentication. Corresponds to the {@code tls_client_auth_san_uri} 1503 * client metadata field. 1504 * 1505 * @param uri The expected uniformResourceIdentifier SAN entry in the X.509 1506 * certificate, {@code null} if not specified. 1507 */ 1508 public void setTLSClientAuthSanURI(final String uri) { 1509 1510 this.tlsClientAuthSanURI = uri; 1511 } 1512 1513 1514 /** 1515 * Gets the expected iPAddress SAN entry in the X.509 certificate, which 1516 * the OAuth client will use in mutual TLS authentication. Corresponds 1517 * to the {@code tls_client_auth_san_ip} client metadata field. 1518 * 1519 * @return The expected iPAddress SAN entry in the X.509 certificate, 1520 * {@code null} if not specified. 1521 */ 1522 public String getTLSClientAuthSanIP() { 1523 1524 return tlsClientAuthSanIP; 1525 } 1526 1527 1528 /** 1529 * Sets the expected iPAddress SAN entry in the X.509 certificate, which 1530 * the OAuth client will use in mutual TLS authentication. Corresponds 1531 * to the {@code tls_client_auth_san_ip} client metadata field. 1532 * 1533 * @param ip The expected iPAddress SAN entry in the X.509 1534 * certificate, {@code null} if not specified. 1535 */ 1536 public void setTLSClientAuthSanIP(final String ip) { 1537 1538 this.tlsClientAuthSanIP = ip; 1539 } 1540 1541 1542 /** 1543 * Gets the expected rfc822Name SAN entry in the X.509 certificate, which 1544 * the OAuth client will use in mutual TLS authentication. Corresponds 1545 * to the {@code tls_client_auth_san_email} client metadata field. 1546 * 1547 * @return The expected rfc822Name SAN entry in the X.509 certificate, 1548 * {@code null} if not specified. 1549 */ 1550 public String getTLSClientAuthSanEmail() { 1551 1552 return tlsClientAuthSanEmail; 1553 } 1554 1555 1556 /** 1557 * Sets the expected rfc822Name SAN entry in the X.509 certificate, which 1558 * the OAuth client will use in mutual TLS authentication. Corresponds 1559 * to the {@code tls_client_auth_san_email} client metadata field. 1560 * 1561 * @param email The expected rfc822Name SAN entry in the X.509 1562 * certificate, {@code null} if not specified. 1563 */ 1564 public void setTLSClientAuthSanEmail(final String email) { 1565 1566 this.tlsClientAuthSanEmail = email; 1567 } 1568 1569 1570 /** 1571 * Ensures that for {@code tls_client_auth} a certificate field for the 1572 * subject is specified. See 1573 * https://www.rfc-editor.org/rfc/rfc8705.html#section-2.1.2 1574 */ 1575 private void ensureExactlyOneCertSubjectFieldForTLSClientAuth() 1576 throws IllegalStateException { 1577 1578 if (! ClientAuthenticationMethod.TLS_CLIENT_AUTH.equals(getTokenEndpointAuthMethod())) { 1579 // Not tls_client_auth, ignore 1580 return; 1581 } 1582 1583 if (tlsClientAuthSubjectDN == null && tlsClientAuthSanDNS == null && tlsClientAuthSanURI == null && tlsClientAuthSanIP == null && tlsClientAuthSanEmail == null) { 1584 throw new IllegalStateException("A certificate field must be specified to indicate the subject in tls_client_auth: " + 1585 "tls_client_auth_subject_dn, tls_client_auth_san_dns, tls_client_auth_san_uri, tls_client_auth_san_ip or tls_client_auth_san_email"); 1586 } 1587 1588 String exceptionMessage = "Exactly one certificate field must be specified to indicate the subject in tls_client_auth: " + 1589 "tls_client_auth_subject_dn, tls_client_auth_san_dns, tls_client_auth_san_uri, tls_client_auth_san_ip or tls_client_auth_san_email"; 1590 1591 if (tlsClientAuthSubjectDN != null) { 1592 if (tlsClientAuthSanDNS != null || tlsClientAuthSanURI != null || tlsClientAuthSanIP != null || tlsClientAuthSanEmail != null) { 1593 throw new IllegalStateException(exceptionMessage); 1594 } 1595 } 1596 1597 if (tlsClientAuthSanDNS != null) { 1598 if (tlsClientAuthSanURI != null || tlsClientAuthSanIP != null || tlsClientAuthSanEmail != null) { 1599 throw new IllegalStateException(exceptionMessage); 1600 } 1601 } 1602 1603 if (tlsClientAuthSanURI != null) { 1604 if (tlsClientAuthSanIP != null || tlsClientAuthSanEmail != null) { 1605 throw new IllegalStateException(exceptionMessage); 1606 } 1607 } 1608 1609 if (tlsClientAuthSanIP != null) { 1610 if (tlsClientAuthSanEmail != null) { 1611 throw new IllegalStateException(exceptionMessage); 1612 } 1613 } 1614 } 1615 1616 1617 /** 1618 * Gets the JWS algorithm for JWT-encoded authorisation responses. 1619 * Corresponds to the {@code authorization_signed_response_alg} client 1620 * metadata field. 1621 * 1622 * @return The JWS algorithm, {@code null} if not specified. 1623 */ 1624 public JWSAlgorithm getAuthorizationJWSAlg() { 1625 1626 return authzJWSAlg; 1627 } 1628 1629 1630 /** 1631 * Sets the JWS algorithm for JWT-encoded authorisation responses. 1632 * Corresponds to the {@code authorization_signed_response_alg} client 1633 * metadata field. 1634 * 1635 * @param authzJWSAlg The JWS algorithm, {@code null} if not specified. 1636 * Must not be {@code "none"}. 1637 */ 1638 public void setAuthorizationJWSAlg(final JWSAlgorithm authzJWSAlg) { 1639 1640 if (new JWSAlgorithm("none").equals(authzJWSAlg)) { 1641 // Prevent passing none as JWS alg 1642 throw new IllegalArgumentException("The JWS algorithm must not be \"none\""); 1643 } 1644 1645 this.authzJWSAlg = authzJWSAlg; 1646 } 1647 1648 1649 /** 1650 * Gets the JWE algorithm for JWT-encoded authorisation responses. 1651 * Corresponds to the {@code authorization_encrypted_response_alg} 1652 * client metadata field. 1653 * 1654 * @return The JWE algorithm, {@code null} if not specified. 1655 */ 1656 public JWEAlgorithm getAuthorizationJWEAlg() { 1657 1658 return authzJWEAlg; 1659 } 1660 1661 1662 /** 1663 * Sets the JWE algorithm for JWT-encoded authorisation responses. 1664 * Corresponds to the {@code authorization_encrypted_response_alg} 1665 * client metadata field. 1666 * 1667 * @param authzJWEAlg The JWE algorithm, {@code null} if not specified. 1668 */ 1669 public void setAuthorizationJWEAlg(final JWEAlgorithm authzJWEAlg) { 1670 1671 this.authzJWEAlg = authzJWEAlg; 1672 } 1673 1674 1675 /** 1676 * Sets the encryption method for JWT-encoded authorisation responses. 1677 * Corresponds to the {@code authorization_encrypted_response_enc} 1678 * client metadata field. 1679 * 1680 * @return The encryption method, {@code null} if specified. 1681 */ 1682 public EncryptionMethod getAuthorizationJWEEnc() { 1683 1684 return authzJWEEnc; 1685 } 1686 1687 1688 /** 1689 * Sets the encryption method for JWT-encoded authorisation responses. 1690 * Corresponds to the {@code authorization_encrypted_response_enc} 1691 * client metadata field. 1692 * 1693 * @param authzJWEEnc The encryption method, {@code null} if specified. 1694 */ 1695 public void setAuthorizationJWEEnc(final EncryptionMethod authzJWEEnc) { 1696 1697 this.authzJWEEnc = authzJWEEnc; 1698 } 1699 1700 1701 /** 1702 * Gets the requirement for pushed authorisation requests (PAR). 1703 * Corresponds to the {@code pushed_authorization_request_endpoint} 1704 * client metadata field. 1705 * 1706 * @return {@code true} if PAR is required, else {@code false}. 1707 */ 1708 public boolean requiresPushedAuthorizationRequests() { 1709 1710 return requirePAR; 1711 } 1712 1713 1714 /** 1715 * Sets the requirement for pushed authorisation requests (PAR). 1716 * Corresponds to the {@code pushed_authorization_request_endpoint} 1717 * client metadata field. 1718 * 1719 * @param requirePAR {@code true} if PAR is required, else 1720 * {@code false}. 1721 */ 1722 public void requiresPushedAuthorizationRequests(final boolean requirePAR) { 1723 1724 this.requirePAR = requirePAR; 1725 } 1726 1727 1728 /** 1729 * Gets the authorisation details types for Rich Authorisation Requests 1730 * (RAR). Corresponds to the {@code authorization_details_types} 1731 * metadata field. 1732 * 1733 * @return The authorisation types, {@code null} if not specified. 1734 */ 1735 public List<AuthorizationType> getAuthorizationDetailsTypes() { 1736 1737 return this.authzTypes; 1738 } 1739 1740 1741 /** 1742 * Sets the authorisation details types for Rich Authorisation Requests 1743 * (RAR). Corresponds to the {@code authorization_details_types} 1744 * metadata field. 1745 * 1746 * @param authzTypes The authorisation types, {@code null} if not 1747 * specified. 1748 */ 1749 public void setAuthorizationDetailsTypes(final List<AuthorizationType> authzTypes) { 1750 1751 this.authzTypes = authzTypes; 1752 } 1753 1754 1755 /** 1756 * Gets the CIBA token delivery mode. Corresponds to the 1757 * {@code backchannel_token_delivery_mode} metadata field. 1758 * 1759 * @return The CIBA token delivery mode, {@code null} if not 1760 * specified. 1761 */ 1762 public BackChannelTokenDeliveryMode getBackChannelTokenDeliveryMode() { 1763 1764 return backChannelTokenDeliveryMode; 1765 } 1766 1767 1768 /** 1769 * Sets the CIBA token delivery mode. Corresponds to the 1770 * {@code backchannel_token_delivery_mode} metadata field. 1771 * 1772 * @param backChannelTokenDeliveryMode The CIBA token delivery mode, 1773 * {@code null} if not specified. 1774 */ 1775 public void setBackChannelTokenDeliveryMode(final BackChannelTokenDeliveryMode backChannelTokenDeliveryMode) { 1776 1777 this.backChannelTokenDeliveryMode = backChannelTokenDeliveryMode; 1778 } 1779 1780 1781 /** 1782 * Gets the CIBA client notification endpoint URI for the ping or push 1783 * delivery modes. Corresponds to the 1784 * {@code backchannel_client_notification_endpoint} metadata field. 1785 * 1786 * @return The CIBA client notification endpoint URI, {@code null} if 1787 * not specified. 1788 */ 1789 public URI getBackChannelClientNotificationEndpoint() { 1790 1791 return backChannelClientNotificationEndpoint; 1792 } 1793 1794 1795 /** 1796 * Sets the CIBA client notification endpoint URI for the ping or push 1797 * delivery modes. Corresponds to the 1798 * {@code backchannel_client_notification_endpoint} metadata field. 1799 * 1800 * @param backChannelClientNotificationEndpoint The CIBA client 1801 * notification endpoint 1802 * URI, {@code null} if 1803 * not specified. 1804 */ 1805 public void setBackChannelClientNotificationEndpoint(final URI backChannelClientNotificationEndpoint) { 1806 1807 this.backChannelClientNotificationEndpoint = backChannelClientNotificationEndpoint; 1808 } 1809 1810 1811 /** 1812 * Gets the JWS algorithm for CIBA requests. Corresponds to the 1813 * {@code backchannel_authentication_request_signing_alg} metadata 1814 * field. 1815 * 1816 * @return The JWS algorithm for CIBA requests, {@code null} if not 1817 * specified. 1818 */ 1819 public JWSAlgorithm getBackChannelAuthRequestJWSAlg() { 1820 1821 return backChannelAuthRequestJWSAlg; 1822 } 1823 1824 1825 /** 1826 * Sets the JWS algorithm for CIBA requests. Corresponds to the 1827 * {@code backchannel_authentication_request_signing_alg} metadata 1828 * field. 1829 * 1830 * @param backChannelAuthRequestJWSAlg The JWS algorithm for CIBA 1831 * requests, {@code null} if not 1832 * specified. 1833 */ 1834 public void setBackChannelAuthRequestJWSAlg(final JWSAlgorithm backChannelAuthRequestJWSAlg) { 1835 1836 this.backChannelAuthRequestJWSAlg = backChannelAuthRequestJWSAlg; 1837 } 1838 1839 1840 /** 1841 * Gets the support for the {@code user_code} CIBA request parameter. 1842 * Corresponds to the {@code backchannel_user_code_parameter} metadata 1843 * field. 1844 * 1845 * @return {@code true} if the {@code user_code} parameter is 1846 * supported, else {@code false}. 1847 */ 1848 public boolean supportsBackChannelUserCodeParam() { 1849 1850 return backChannelUserCodeParam; 1851 } 1852 1853 1854 /** 1855 * Sets the support for the {@code user_code} CIBA request parameter. 1856 * Corresponds to the {@code backchannel_user_code_parameter} metadata 1857 * field. 1858 * 1859 * @param backChannelUserCodeParam {@code true} if the 1860 * {@code user_code} parameter is 1861 * supported, else {@code false}. 1862 */ 1863 public void setSupportsBackChannelUserCodeParam(final boolean backChannelUserCodeParam) { 1864 1865 this.backChannelUserCodeParam = backChannelUserCodeParam; 1866 } 1867 1868 1869 /** 1870 * Gets the supported OpenID Connect Federation 1.0 client registration 1871 * types. Corresponds to the {@code client_registration_types} metadata 1872 * field. 1873 * 1874 * @return The supported registration types, {@code null} if not 1875 * specified. 1876 */ 1877 public List<ClientRegistrationType> getClientRegistrationTypes() { 1878 1879 return clientRegistrationTypes; 1880 } 1881 1882 1883 /** 1884 * Sets the supported OpenID Connect Federation 1.0 client registration 1885 * types. Corresponds to the {@code client_registration_types} metadata 1886 * field. 1887 * 1888 * @param regTypes The supported registration types, {@code null} if 1889 * not specified. 1890 */ 1891 public void setClientRegistrationTypes(final List<ClientRegistrationType> regTypes) { 1892 1893 this.clientRegistrationTypes = regTypes; 1894 } 1895 1896 1897 /** 1898 * Gets the organisation name in OpenID Connect Federation 1.0. 1899 * Corresponds to the {@code organization_name} metadata field. 1900 * 1901 * @return The organisation name, {@code null} if not specified. 1902 */ 1903 public String getOrganizationName() { 1904 1905 return organizationName; 1906 } 1907 1908 1909 /** 1910 * Sets the organisation name in OpenID Connect Federation 1.0. 1911 * Corresponds to the {@code organization_name} metadata field. 1912 * 1913 * @param organizationName The organisation name, {@code null} if not 1914 * specified. 1915 */ 1916 public void setOrganizationName(final String organizationName) { 1917 1918 this.organizationName = organizationName; 1919 } 1920 1921 1922 /** 1923 * Gets the specified custom metadata field. 1924 * 1925 * @param name The field name. Must not be {@code null}. 1926 * 1927 * @return The field value, typically serialisable to a JSON entity, 1928 * {@code null} if none. 1929 */ 1930 public Object getCustomField(final String name) { 1931 1932 return customFields.get(name); 1933 } 1934 1935 1936 /** 1937 * Gets the custom metadata fields. 1938 * 1939 * @return The custom metadata fields, as a JSON object, empty object 1940 * if none. 1941 */ 1942 public JSONObject getCustomFields() { 1943 1944 return customFields; 1945 } 1946 1947 1948 /** 1949 * Sets the specified custom metadata field. 1950 * 1951 * @param name The field name. Must not be {@code null}. 1952 * @param value The field value. Should serialise to a JSON entity. 1953 */ 1954 public void setCustomField(final String name, final Object value) { 1955 1956 customFields.put(name, value); 1957 } 1958 1959 1960 /** 1961 * Sets the custom metadata fields. 1962 * 1963 * @param customFields The custom metadata fields, as a JSON object, 1964 * empty object if none. Must not be {@code null}. 1965 */ 1966 public void setCustomFields(final JSONObject customFields) { 1967 1968 if (customFields == null) 1969 throw new IllegalArgumentException("The custom fields JSON object must not be null"); 1970 1971 this.customFields = customFields; 1972 } 1973 1974 1975 /** 1976 * Applies the client metadata defaults where no values have been 1977 * specified. 1978 * 1979 * <ul> 1980 * <li>The response types default to {@code ["code"]}. 1981 * <li>The grant types default to {@code ["authorization_code"]}. 1982 * <li>The client authentication method defaults to 1983 * "client_secret_basic", unless the grant type is "implicit" 1984 * only. 1985 * <li>The encryption method for JWT-encoded authorisation 1986 * responses defaults to {@code A128CBC-HS256} if a JWE 1987 * algorithm is set. 1988 * </ul> 1989 */ 1990 public void applyDefaults() { 1991 1992 if (responseTypes == null) { 1993 responseTypes = new HashSet<>(); 1994 responseTypes.add(ResponseType.getDefault()); 1995 } 1996 1997 if (grantTypes == null) { 1998 grantTypes = new HashSet<>(); 1999 grantTypes.add(GrantType.AUTHORIZATION_CODE); 2000 } 2001 2002 if (authMethod == null) { 2003 2004 if (grantTypes.contains(GrantType.IMPLICIT) && grantTypes.size() == 1) { 2005 authMethod = ClientAuthenticationMethod.NONE; 2006 } else { 2007 authMethod = ClientAuthenticationMethod.getDefault(); 2008 } 2009 } 2010 2011 if (authzJWEAlg != null && authzJWEEnc == null) { 2012 authzJWEEnc = EncryptionMethod.A128CBC_HS256; 2013 } 2014 } 2015 2016 2017 /** 2018 * Returns the JSON object representation of this client metadata, 2019 * including any custom fields. 2020 * 2021 * @return The JSON object. 2022 */ 2023 public JSONObject toJSONObject() { 2024 2025 return toJSONObject(true); 2026 } 2027 2028 2029 /** 2030 * Returns the JSON object representation of this client metadata. 2031 * 2032 * @param includeCustomFields {@code true} to include any custom 2033 * metadata fields, {@code false} to omit 2034 * them. 2035 * 2036 * @return The JSON object. 2037 */ 2038 public JSONObject toJSONObject(final boolean includeCustomFields) { 2039 2040 ensureExactlyOneCertSubjectFieldForTLSClientAuth(); 2041 2042 JSONObject o; 2043 2044 if (includeCustomFields) 2045 o = new JSONObject(customFields); 2046 else 2047 o = new JSONObject(); 2048 2049 2050 if (redirectURIs != null) 2051 o.put("redirect_uris", URIUtils.toStringList(redirectURIs)); 2052 2053 2054 if (scope != null) 2055 o.put("scope", scope.toString()); 2056 2057 2058 if (responseTypes != null) { 2059 2060 JSONArray rtList = new JSONArray(); 2061 2062 for (ResponseType rt: responseTypes) 2063 rtList.add(rt.toString()); 2064 2065 o.put("response_types", rtList); 2066 } 2067 2068 2069 if (grantTypes != null) { 2070 2071 JSONArray grantList = new JSONArray(); 2072 2073 for (GrantType grant: grantTypes) 2074 grantList.add(grant.toString()); 2075 2076 o.put("grant_types", grantList); 2077 } 2078 2079 2080 if (contacts != null) { 2081 o.put("contacts", contacts); 2082 } 2083 2084 2085 if (! nameEntries.isEmpty()) { 2086 2087 for (Map.Entry<LangTag,String> entry: nameEntries.entrySet()) { 2088 2089 LangTag langTag = entry.getKey(); 2090 String name = entry.getValue(); 2091 2092 if (name == null) 2093 continue; 2094 2095 if (langTag == null) 2096 o.put("client_name", entry.getValue()); 2097 else 2098 o.put("client_name#" + langTag, entry.getValue()); 2099 } 2100 } 2101 2102 2103 if (! logoURIEntries.isEmpty()) { 2104 2105 for (Map.Entry<LangTag,URI> entry: logoURIEntries.entrySet()) { 2106 2107 LangTag langTag = entry.getKey(); 2108 URI uri = entry.getValue(); 2109 2110 if (uri == null) 2111 continue; 2112 2113 if (langTag == null) 2114 o.put("logo_uri", entry.getValue().toString()); 2115 else 2116 o.put("logo_uri#" + langTag, entry.getValue().toString()); 2117 } 2118 } 2119 2120 2121 if (! uriEntries.isEmpty()) { 2122 2123 for (Map.Entry<LangTag,URI> entry: uriEntries.entrySet()) { 2124 2125 LangTag langTag = entry.getKey(); 2126 URI uri = entry.getValue(); 2127 2128 if (uri == null) 2129 continue; 2130 2131 if (langTag == null) 2132 o.put("client_uri", entry.getValue().toString()); 2133 else 2134 o.put("client_uri#" + langTag, entry.getValue().toString()); 2135 } 2136 } 2137 2138 2139 if (! policyURIEntries.isEmpty()) { 2140 2141 for (Map.Entry<LangTag,URI> entry: policyURIEntries.entrySet()) { 2142 2143 LangTag langTag = entry.getKey(); 2144 URI uri = entry.getValue(); 2145 2146 if (uri == null) 2147 continue; 2148 2149 if (langTag == null) 2150 o.put("policy_uri", entry.getValue().toString()); 2151 else 2152 o.put("policy_uri#" + langTag, entry.getValue().toString()); 2153 } 2154 } 2155 2156 2157 if (! tosURIEntries.isEmpty()) { 2158 2159 for (Map.Entry<LangTag,URI> entry: tosURIEntries.entrySet()) { 2160 2161 LangTag langTag = entry.getKey(); 2162 URI uri = entry.getValue(); 2163 2164 if (uri == null) 2165 continue; 2166 2167 if (langTag == null) 2168 o.put("tos_uri", entry.getValue().toString()); 2169 else 2170 o.put("tos_uri#" + langTag, entry.getValue().toString()); 2171 } 2172 } 2173 2174 2175 if (authMethod != null) 2176 o.put("token_endpoint_auth_method", authMethod.toString()); 2177 2178 2179 if (authJWSAlg != null) 2180 o.put("token_endpoint_auth_signing_alg", authJWSAlg.getName()); 2181 2182 2183 if (jwkSetURI != null) 2184 o.put("jwks_uri", jwkSetURI.toString()); 2185 2186 2187 if (jwkSet != null) 2188 o.put("jwks", JSONObjectUtils.toJSONObject(jwkSet.toPublicJWKSet())); // prevent private keys from leaking 2189 2190 2191 if (requestObjectURIs != null) 2192 o.put("request_uris", URIUtils.toStringList(requestObjectURIs)); 2193 2194 if (requestObjectJWSAlg != null) 2195 o.put("request_object_signing_alg", requestObjectJWSAlg.getName()); 2196 2197 if (requestObjectJWEAlg != null) 2198 o.put("request_object_encryption_alg", requestObjectJWEAlg.getName()); 2199 2200 if (requestObjectJWEEnc != null) 2201 o.put("request_object_encryption_enc", requestObjectJWEEnc.getName()); 2202 2203 2204 if (softwareID != null) 2205 o.put("software_id", softwareID.getValue()); 2206 2207 if (softwareVersion != null) 2208 o.put("software_version", softwareVersion.getValue()); 2209 2210 if (softwareStatement != null) 2211 o.put("software_statement", softwareStatement.serialize()); 2212 2213 if (getTLSClientCertificateBoundAccessTokens()) { 2214 o.put("tls_client_certificate_bound_access_tokens", tlsClientCertificateBoundAccessTokens); 2215 } 2216 2217 if (tlsClientAuthSubjectDN != null) 2218 o.put("tls_client_auth_subject_dn", tlsClientAuthSubjectDN); 2219 2220 if (tlsClientAuthSanDNS != null) 2221 o.put("tls_client_auth_san_dns", tlsClientAuthSanDNS); 2222 2223 if (tlsClientAuthSanURI != null) 2224 o.put("tls_client_auth_san_uri", tlsClientAuthSanURI); 2225 2226 if (tlsClientAuthSanIP != null) 2227 o.put("tls_client_auth_san_ip", tlsClientAuthSanIP); 2228 2229 if (tlsClientAuthSanEmail != null) 2230 o.put("tls_client_auth_san_email", tlsClientAuthSanEmail); 2231 2232 if (authzJWSAlg != null) { 2233 o.put("authorization_signed_response_alg", authzJWSAlg.getName()); 2234 } 2235 2236 if (authzJWEAlg != null) { 2237 o.put("authorization_encrypted_response_alg", authzJWEAlg.getName()); 2238 } 2239 2240 if (authzJWEEnc != null) { 2241 o.put("authorization_encrypted_response_enc", authzJWEEnc.getName()); 2242 } 2243 2244 // PAR 2245 if (requirePAR) { 2246 o.put("require_pushed_authorization_requests", true); 2247 } 2248 2249 // RAR 2250 if (authzTypes != null) { 2251 o.put("authorization_details_types", Identifier.toStringList(authzTypes)); 2252 } 2253 2254 // CIBA 2255 2256 if (backChannelTokenDeliveryMode != null) { 2257 o.put("backchannel_token_delivery_mode", backChannelTokenDeliveryMode.getValue()); 2258 } 2259 2260 if (backChannelClientNotificationEndpoint != null) { 2261 o.put("backchannel_client_notification_endpoint", backChannelClientNotificationEndpoint.toString()); 2262 } 2263 2264 if (backChannelAuthRequestJWSAlg != null) { 2265 o.put("backchannel_authentication_request_signing_alg", backChannelAuthRequestJWSAlg.getName()); 2266 } 2267 2268 if (backChannelUserCodeParam) { 2269 o.put("backchannel_user_code_parameter", true); 2270 } 2271 2272 // Federation 2273 if (CollectionUtils.isNotEmpty(clientRegistrationTypes)) { 2274 o.put("client_registration_types", Identifier.toStringList(clientRegistrationTypes)); 2275 } 2276 if (organizationName != null) { 2277 o.put("organization_name", organizationName); 2278 } 2279 if (signedJWKSetURI != null) { 2280 o.put("signed_jwks_uri", signedJWKSetURI.toString()); 2281 } 2282 2283 return o; 2284 } 2285 2286 2287 @Override 2288 public String toString() { 2289 return toJSONObject().toJSONString(); 2290 } 2291 2292 2293 /** 2294 * Parses an client metadata instance from the specified JSON object. 2295 * 2296 * @param jsonObject The JSON object to parse. Must not be 2297 * {@code null}. 2298 * 2299 * @return The client metadata. 2300 * 2301 * @throws ParseException If the JSON object couldn't be parsed to a 2302 * client metadata instance. 2303 */ 2304 public static ClientMetadata parse(final JSONObject jsonObject) 2305 throws ParseException { 2306 2307 // Copy JSON object, then parse 2308 return parseFromModifiableJSONObject(new JSONObject(jsonObject)); 2309 } 2310 2311 2312 /** 2313 * Parses an client metadata instance from the specified JSON object. 2314 * 2315 * @param jsonObject The JSON object to parse, will be modified by 2316 * the parse routine. Must not be {@code null}. 2317 * 2318 * @return The client metadata. 2319 * 2320 * @throws ParseException If the JSON object couldn't be parsed to a 2321 * client metadata instance. 2322 */ 2323 private static ClientMetadata parseFromModifiableJSONObject(final JSONObject jsonObject) 2324 throws ParseException { 2325 2326 ClientMetadata metadata = new ClientMetadata(); 2327 2328 if (jsonObject.get("redirect_uris") != null) { 2329 2330 Set<URI> redirectURIs = new LinkedHashSet<>(); 2331 2332 for (String uriString: JSONObjectUtils.getStringArray(jsonObject, "redirect_uris")) { 2333 URI uri; 2334 try { 2335 uri = new URI(uriString); 2336 } catch (URISyntaxException e) { 2337 throw new ParseException("Invalid redirect_uris parameter: " + e.getMessage(), RegistrationError.INVALID_REDIRECT_URI.appendDescription(": " + e.getMessage())); 2338 } 2339 redirectURIs.add(uri); 2340 } 2341 try { 2342 metadata.setRedirectionURIs(redirectURIs); 2343 } catch (IllegalArgumentException e) { 2344 throw new ParseException("Invalid redirect_uris parameter: " + e.getMessage(), RegistrationError.INVALID_REDIRECT_URI.appendDescription(": " + e.getMessage())); 2345 } 2346 jsonObject.remove("redirect_uris"); 2347 } 2348 2349 try { 2350 2351 if (jsonObject.get("scope") != null) { 2352 metadata.setScope(Scope.parse(JSONObjectUtils.getString(jsonObject, "scope"))); 2353 jsonObject.remove("scope"); 2354 } 2355 2356 2357 if (jsonObject.get("response_types") != null) { 2358 2359 Set<ResponseType> responseTypes = new LinkedHashSet<>(); 2360 2361 for (String rt : JSONObjectUtils.getStringArray(jsonObject, "response_types")) { 2362 2363 responseTypes.add(ResponseType.parse(rt)); 2364 } 2365 2366 metadata.setResponseTypes(responseTypes); 2367 jsonObject.remove("response_types"); 2368 } 2369 2370 2371 if (jsonObject.get("grant_types") != null) { 2372 2373 Set<GrantType> grantTypes = new LinkedHashSet<>(); 2374 2375 for (String grant : JSONObjectUtils.getStringArray(jsonObject, "grant_types")) { 2376 2377 grantTypes.add(GrantType.parse(grant)); 2378 } 2379 2380 metadata.setGrantTypes(grantTypes); 2381 jsonObject.remove("grant_types"); 2382 } 2383 2384 2385 if (jsonObject.get("contacts") != null) { 2386 metadata.setEmailContacts(JSONObjectUtils.getStringList(jsonObject, "contacts")); 2387 jsonObject.remove("contacts"); 2388 } 2389 2390 2391 // Find lang-tagged client_name params 2392 Map<LangTag, Object> matches = LangTagUtils.find("client_name", jsonObject); 2393 2394 for (Map.Entry<LangTag, Object> entry : matches.entrySet()) { 2395 2396 try { 2397 metadata.setName((String) entry.getValue(), entry.getKey()); 2398 2399 } catch (ClassCastException e) { 2400 2401 throw new ParseException("Invalid client_name (language tag) parameter"); 2402 } 2403 2404 removeMember(jsonObject, "client_name", entry.getKey()); 2405 } 2406 2407 2408 matches = LangTagUtils.find("logo_uri", jsonObject); 2409 2410 for (Map.Entry<LangTag, Object> entry : matches.entrySet()) { 2411 2412 if (entry.getValue() == null) continue; 2413 2414 try { 2415 metadata.setLogoURI(new URI((String) entry.getValue()), entry.getKey()); 2416 } catch (Exception e) { 2417 throw new ParseException("Invalid logo_uri (language tag) parameter"); 2418 } 2419 2420 removeMember(jsonObject, "logo_uri", entry.getKey()); 2421 } 2422 2423 2424 matches = LangTagUtils.find("client_uri", jsonObject); 2425 2426 for (Map.Entry<LangTag, Object> entry : matches.entrySet()) { 2427 2428 if (entry.getValue() == null) continue; 2429 2430 try { 2431 metadata.setURI(new URI((String) entry.getValue()), entry.getKey()); 2432 } catch (Exception e) { 2433 throw new ParseException("Invalid client_uri (language tag) parameter: " + e.getMessage()); 2434 } 2435 2436 removeMember(jsonObject, "client_uri", entry.getKey()); 2437 } 2438 2439 2440 matches = LangTagUtils.find("policy_uri", jsonObject); 2441 2442 for (Map.Entry<LangTag, Object> entry : matches.entrySet()) { 2443 2444 if (entry.getValue() == null) continue; 2445 2446 try { 2447 metadata.setPolicyURI(new URI((String) entry.getValue()), entry.getKey()); 2448 } catch (Exception e) { 2449 throw new ParseException("Invalid policy_uri (language tag) parameter: " + e.getMessage()); 2450 } 2451 2452 removeMember(jsonObject, "policy_uri", entry.getKey()); 2453 } 2454 2455 2456 matches = LangTagUtils.find("tos_uri", jsonObject); 2457 2458 for (Map.Entry<LangTag, Object> entry : matches.entrySet()) { 2459 2460 if (entry.getValue() == null) continue; 2461 2462 try { 2463 metadata.setTermsOfServiceURI(new URI((String) entry.getValue()), entry.getKey()); 2464 } catch (Exception e) { 2465 throw new ParseException("Invalid tos_uri (language tag) parameter: " + e.getMessage()); 2466 } 2467 2468 removeMember(jsonObject, "tos_uri", entry.getKey()); 2469 } 2470 2471 2472 if (jsonObject.get("token_endpoint_auth_method") != null) { 2473 metadata.setTokenEndpointAuthMethod(ClientAuthenticationMethod.parse( 2474 JSONObjectUtils.getString(jsonObject, "token_endpoint_auth_method"))); 2475 2476 jsonObject.remove("token_endpoint_auth_method"); 2477 } 2478 2479 2480 if (jsonObject.get("token_endpoint_auth_signing_alg") != null) { 2481 metadata.setTokenEndpointAuthJWSAlg(JWSAlgorithm.parse( 2482 JSONObjectUtils.getString(jsonObject, "token_endpoint_auth_signing_alg"))); 2483 2484 jsonObject.remove("token_endpoint_auth_signing_alg"); 2485 } 2486 2487 2488 if (jsonObject.get("jwks_uri") != null) { 2489 metadata.setJWKSetURI(JSONObjectUtils.getURI(jsonObject, "jwks_uri")); 2490 jsonObject.remove("jwks_uri"); 2491 } 2492 2493 if (jsonObject.get("jwks") != null) { 2494 2495 try { 2496 metadata.setJWKSet(JWKSet.parse(JSONObjectUtils.getJSONObject(jsonObject, "jwks"))); 2497 2498 } catch (java.text.ParseException e) { 2499 throw new ParseException("Illegal JWK set: " + e.getMessage(), e); 2500 } 2501 2502 jsonObject.remove("jwks"); 2503 } 2504 2505 if (jsonObject.get("request_uris") != null) { 2506 2507 Set<URI> requestURIs = new LinkedHashSet<>(); 2508 2509 for (String uriString : JSONObjectUtils.getStringArray(jsonObject, "request_uris")) { 2510 2511 try { 2512 requestURIs.add(new URI(uriString)); 2513 2514 } catch (URISyntaxException e) { 2515 2516 throw new ParseException("Invalid request_uris parameter"); 2517 } 2518 } 2519 2520 metadata.setRequestObjectURIs(requestURIs); 2521 jsonObject.remove("request_uris"); 2522 } 2523 2524 if (jsonObject.get("request_object_signing_alg") != null) { 2525 metadata.setRequestObjectJWSAlg(JWSAlgorithm.parse( 2526 JSONObjectUtils.getString(jsonObject, "request_object_signing_alg"))); 2527 2528 jsonObject.remove("request_object_signing_alg"); 2529 } 2530 2531 if (jsonObject.get("request_object_encryption_alg") != null) { 2532 metadata.setRequestObjectJWEAlg(JWEAlgorithm.parse( 2533 JSONObjectUtils.getString(jsonObject, "request_object_encryption_alg"))); 2534 2535 jsonObject.remove("request_object_encryption_alg"); 2536 } 2537 2538 if (jsonObject.get("request_object_encryption_enc") != null) { 2539 metadata.setRequestObjectJWEEnc(EncryptionMethod.parse( 2540 JSONObjectUtils.getString(jsonObject, "request_object_encryption_enc"))); 2541 2542 jsonObject.remove("request_object_encryption_enc"); 2543 } 2544 2545 if (jsonObject.get("software_id") != null) { 2546 metadata.setSoftwareID(new SoftwareID(JSONObjectUtils.getString(jsonObject, "software_id"))); 2547 jsonObject.remove("software_id"); 2548 } 2549 2550 if (jsonObject.get("software_version") != null) { 2551 // Normalize to string, in non-compliant OB profiles 2552 metadata.setSoftwareVersion(new SoftwareVersion(jsonObject.get("software_version").toString())); 2553 jsonObject.remove("software_version"); 2554 } 2555 2556 if (jsonObject.get("software_statement") != null) { 2557 try { 2558 metadata.setSoftwareStatement(SignedJWT.parse(JSONObjectUtils.getString(jsonObject, "software_statement"))); 2559 } catch (java.text.ParseException e) { 2560 throw new ParseException("Invalid software_statement JWT: " + e.getMessage()); 2561 } 2562 jsonObject.remove("software_statement"); 2563 } 2564 2565 if (jsonObject.get("tls_client_certificate_bound_access_tokens") != null) { 2566 metadata.setTLSClientCertificateBoundAccessTokens(JSONObjectUtils.getBoolean(jsonObject, "tls_client_certificate_bound_access_tokens")); 2567 jsonObject.remove("tls_client_certificate_bound_access_tokens"); 2568 } 2569 2570 if (jsonObject.get("tls_client_auth_subject_dn") != null) { 2571 metadata.setTLSClientAuthSubjectDN(JSONObjectUtils.getString(jsonObject, "tls_client_auth_subject_dn")); 2572 jsonObject.remove("tls_client_auth_subject_dn"); 2573 } 2574 2575 if (jsonObject.get("tls_client_auth_san_dns") != null) { 2576 metadata.setTLSClientAuthSanDNS(JSONObjectUtils.getString(jsonObject, "tls_client_auth_san_dns")); 2577 jsonObject.remove("tls_client_auth_san_dns"); 2578 } 2579 2580 if (jsonObject.get("tls_client_auth_san_uri") != null) { 2581 metadata.setTLSClientAuthSanURI(JSONObjectUtils.getString(jsonObject, "tls_client_auth_san_uri")); 2582 jsonObject.remove("tls_client_auth_san_uri"); 2583 } 2584 2585 if (jsonObject.get("tls_client_auth_san_ip") != null) { 2586 metadata.setTLSClientAuthSanIP(JSONObjectUtils.getString(jsonObject, "tls_client_auth_san_ip")); 2587 jsonObject.remove("tls_client_auth_san_ip"); 2588 } 2589 2590 if (jsonObject.get("tls_client_auth_san_email") != null) { 2591 metadata.setTLSClientAuthSanEmail(JSONObjectUtils.getString(jsonObject, "tls_client_auth_san_email")); 2592 jsonObject.remove("tls_client_auth_san_email"); 2593 } 2594 2595 metadata.ensureExactlyOneCertSubjectFieldForTLSClientAuth(); 2596 2597 if (jsonObject.get("authorization_signed_response_alg") != null) { 2598 metadata.setAuthorizationJWSAlg(JWSAlgorithm.parse(JSONObjectUtils.getString(jsonObject, "authorization_signed_response_alg"))); 2599 jsonObject.remove("authorization_signed_response_alg"); 2600 } 2601 2602 if (jsonObject.get("authorization_encrypted_response_alg") != null) { 2603 metadata.setAuthorizationJWEAlg(JWEAlgorithm.parse(JSONObjectUtils.getString(jsonObject, "authorization_encrypted_response_alg"))); 2604 jsonObject.remove("authorization_encrypted_response_alg"); 2605 } 2606 2607 if (jsonObject.get("authorization_encrypted_response_enc") != null) { 2608 metadata.setAuthorizationJWEEnc(EncryptionMethod.parse(JSONObjectUtils.getString(jsonObject, "authorization_encrypted_response_enc"))); 2609 jsonObject.remove("authorization_encrypted_response_enc"); 2610 } 2611 2612 // PAR 2613 if (jsonObject.get("require_pushed_authorization_requests") != null) { 2614 metadata.requiresPushedAuthorizationRequests(JSONObjectUtils.getBoolean(jsonObject, "require_pushed_authorization_requests")); 2615 jsonObject.remove("require_pushed_authorization_requests"); 2616 } 2617 2618 // RAR 2619 if (jsonObject.get("authorization_details_types") != null) { 2620 List<AuthorizationType> authzTypes = new LinkedList<>(); 2621 for (String v: JSONObjectUtils.getStringList(jsonObject, "authorization_details_types")) { 2622 if (StringUtils.isNotBlank(v)) { 2623 authzTypes.add(new AuthorizationType(v)); 2624 } 2625 } 2626 metadata.setAuthorizationDetailsTypes(authzTypes); 2627 jsonObject.remove("authorization_details_types"); 2628 } 2629 2630 // CIBA 2631 2632 if (jsonObject.get("backchannel_token_delivery_mode") != null) { 2633 metadata.setBackChannelTokenDeliveryMode(BackChannelTokenDeliveryMode.parse(JSONObjectUtils.getString(jsonObject, "backchannel_token_delivery_mode"))); 2634 jsonObject.remove("backchannel_token_delivery_mode"); 2635 } 2636 2637 if (jsonObject.get("backchannel_client_notification_endpoint") != null) { 2638 metadata.setBackChannelClientNotificationEndpoint(JSONObjectUtils.getURI(jsonObject, "backchannel_client_notification_endpoint")); 2639 jsonObject.remove("backchannel_client_notification_endpoint"); 2640 } 2641 2642 if (jsonObject.get("backchannel_authentication_request_signing_alg") != null) { 2643 metadata.setBackChannelAuthRequestJWSAlg(JWSAlgorithm.parse(JSONObjectUtils.getString(jsonObject, "backchannel_authentication_request_signing_alg"))); 2644 jsonObject.remove("backchannel_authentication_request_signing_alg"); 2645 } 2646 2647 if (jsonObject.get("backchannel_user_code_parameter") != null) { 2648 metadata.setSupportsBackChannelUserCodeParam(JSONObjectUtils.getBoolean(jsonObject, "backchannel_user_code_parameter")); 2649 jsonObject.remove("backchannel_user_code_parameter"); 2650 } 2651 2652 2653 // Federation 2654 2655 if (jsonObject.get("client_registration_types") != null) { 2656 List<ClientRegistrationType> types = new LinkedList<>(); 2657 for (String v: JSONObjectUtils.getStringList(jsonObject, "client_registration_types")) { 2658 types.add(new ClientRegistrationType(v)); 2659 } 2660 metadata.setClientRegistrationTypes(types); 2661 jsonObject.remove("client_registration_types"); 2662 } 2663 2664 if (jsonObject.get("organization_name") != null) { 2665 metadata.setOrganizationName(JSONObjectUtils.getString(jsonObject, "organization_name")); 2666 jsonObject.remove("organization_name"); 2667 } 2668 2669 if (jsonObject.get("signed_jwks_uri") != null) { 2670 metadata.setSignedJWKSetURI(JSONObjectUtils.getURI(jsonObject, "signed_jwks_uri")); 2671 jsonObject.remove("signed_jwks_uri"); 2672 } 2673 2674 } catch (ParseException | IllegalStateException e) { 2675 // Insert client_client_metadata error code so that it 2676 // can be reported back to the client if we have a 2677 // registration event 2678 throw new ParseException( 2679 e.getMessage(), 2680 RegistrationError.INVALID_CLIENT_METADATA.appendDescription(ErrorObject.removeIllegalChars(": " + e.getMessage())), 2681 e.getCause() 2682 ); 2683 } 2684 2685 // Remove any remaining top-level client information fields 2686 for (String paramName: ClientInformation.getRegisteredParameterNames()) { 2687 jsonObject.remove(paramName); 2688 } 2689 // The remaining fields are custom 2690 metadata.customFields = jsonObject; 2691 2692 return metadata; 2693 } 2694 2695 2696 /** 2697 * Removes a JSON object member with the specified base name and 2698 * optional language tag. 2699 * 2700 * @param jsonObject The JSON object. Must not be {@code null}. 2701 * @param name The base member name. Must not be {@code null}. 2702 * @param langTag The language tag, {@code null} if none. 2703 */ 2704 private static void removeMember(final JSONObject jsonObject, final String name, final LangTag langTag) { 2705 2706 if (langTag == null) 2707 jsonObject.remove(name); 2708 else 2709 jsonObject.remove(name + "#" + langTag); 2710 } 2711}