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