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