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