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