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