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