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