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