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