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.as; 019 020 021import java.io.IOException; 022import java.net.MalformedURLException; 023import java.net.URI; 024import java.net.URISyntaxException; 025import java.net.URL; 026import java.util.*; 027 028import com.nimbusds.jose.Algorithm; 029import com.nimbusds.jose.EncryptionMethod; 030import com.nimbusds.jose.JWEAlgorithm; 031import com.nimbusds.jose.JWSAlgorithm; 032import com.nimbusds.langtag.LangTag; 033import com.nimbusds.langtag.LangTagException; 034import com.nimbusds.oauth2.sdk.*; 035import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod; 036import com.nimbusds.oauth2.sdk.http.HTTPRequest; 037import com.nimbusds.oauth2.sdk.http.HTTPResponse; 038import com.nimbusds.oauth2.sdk.id.Issuer; 039import com.nimbusds.oauth2.sdk.pkce.CodeChallengeMethod; 040import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 041import com.nimbusds.oauth2.sdk.util.OrderedJSONObject; 042import net.minidev.json.JSONObject; 043 044 045/** 046 * OAuth 2.0 Authorisation Server (AS) metadata. 047 * 048 * <p>Related specifications: 049 * 050 * <ul> 051 * <li>OAuth 2.0 Authorization Server Metadata 052 * (draft-ietf-oauth-discovery-10) 053 * <li>OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound 054 * * Access Tokens (draft-ietf-oauth-mtls-07) 055 * </ul> 056 */ 057public class AuthorizationServerMetadata { 058 059 /** 060 * The registered parameter names. 061 */ 062 private static final Set<String> REGISTERED_PARAMETER_NAMES; 063 064 065 static { 066 Set<String> p = new HashSet<>(); 067 p.add("issuer"); 068 p.add("authorization_endpoint"); 069 p.add("token_endpoint"); 070 p.add("registration_endpoint"); 071 p.add("jwks_uri"); 072 p.add("scopes_supported"); 073 p.add("response_types_supported"); 074 p.add("response_modes_supported"); 075 p.add("grant_types_supported"); 076 p.add("code_challenge_methods_supported"); 077 p.add("token_endpoint_auth_methods_supported"); 078 p.add("token_endpoint_auth_signing_alg_values_supported"); 079 p.add("request_object_signing_alg_values_supported"); 080 p.add("request_object_encryption_alg_values_supported"); 081 p.add("request_object_encryption_enc_values_supported"); 082 p.add("ui_locales_supported"); 083 p.add("service_documentation"); 084 p.add("op_policy_uri"); 085 p.add("op_tos_uri"); 086 p.add("introspection_endpoint"); 087 p.add("introspection_endpoint_auth_methods_supported"); 088 p.add("introspection_endpoint_auth_signing_alg_values_supported"); 089 p.add("revocation_endpoint"); 090 p.add("revocation_endpoint_auth_methods_supported"); 091 p.add("revocation_endpoint_auth_signing_alg_values_supported"); 092 p.add("mutual_tls_sender_constrained_access_tokens"); 093 REGISTERED_PARAMETER_NAMES = Collections.unmodifiableSet(p); 094 } 095 096 097 /** 098 * Gets the registered OpenID Connect provider metadata parameter 099 * names. 100 * 101 * @return The registered OpenID Connect provider metadata parameter 102 * names, as an unmodifiable set. 103 */ 104 public static Set<String> getRegisteredParameterNames() { 105 106 return REGISTERED_PARAMETER_NAMES; 107 } 108 109 110 /** 111 * The issuer. 112 */ 113 private final Issuer issuer; 114 115 116 /** 117 * The authorisation endpoint. 118 */ 119 private URI authzEndpoint; 120 121 122 /** 123 * The token endpoint. 124 */ 125 private URI tokenEndpoint; 126 127 128 /** 129 * The registration endpoint. 130 */ 131 private URI regEndpoint; 132 133 134 /** 135 * The token introspection endpoint. 136 */ 137 private URI introspectionEndpoint; 138 139 140 /** 141 * The token revocation endpoint. 142 */ 143 private URI revocationEndpoint; 144 145 146 /** 147 * The JWK set URI. 148 */ 149 private URI jwkSetURI; 150 151 152 /** 153 * The supported scope values. 154 */ 155 private Scope scope; 156 157 158 /** 159 * The supported response types. 160 */ 161 private List<ResponseType> rts; 162 163 164 /** 165 * The supported response modes. 166 */ 167 private List<ResponseMode> rms; 168 169 170 /** 171 * The supported grant types. 172 */ 173 private List<GrantType> gts; 174 175 176 /** 177 * The supported code challenge methods for PKCE. 178 */ 179 private List<CodeChallengeMethod> codeChallengeMethods; 180 181 182 /** 183 * The supported token endpoint authentication methods. 184 */ 185 private List<ClientAuthenticationMethod> tokenEndpointAuthMethods; 186 187 188 /** 189 * The supported JWS algorithms for the {@code private_key_jwt} and 190 * {@code client_secret_jwt} token endpoint authentication methods. 191 */ 192 private List<JWSAlgorithm> tokenEndpointJWSAlgs; 193 194 195 /** 196 * The supported introspection endpoint authentication methods. 197 */ 198 private List<ClientAuthenticationMethod> introspectionEndpointAuthMethods; 199 200 201 /** 202 * The supported JWS algorithms for the {@code private_key_jwt} and 203 * {@code client_secret_jwt} introspection endpoint authentication 204 * methods. 205 */ 206 private List<JWSAlgorithm> introspectionEndpointJWSAlgs; 207 208 209 /** 210 * The supported revocation endpoint authentication methods. 211 */ 212 private List<ClientAuthenticationMethod> revocationEndpointAuthMethods; 213 214 215 /** 216 * The supported JWS algorithms for the {@code private_key_jwt} and 217 * {@code client_secret_jwt} revocation endpoint authentication 218 * methods. 219 */ 220 private List<JWSAlgorithm> revocationEndpointJWSAlgs; 221 222 223 /** 224 * The supported JWS algorithms for request objects. 225 */ 226 private List<JWSAlgorithm> requestObjectJWSAlgs; 227 228 229 /** 230 * The supported JWE algorithms for request objects. 231 */ 232 private List<JWEAlgorithm> requestObjectJWEAlgs; 233 234 235 /** 236 * The supported encryption methods for request objects. 237 */ 238 private List<EncryptionMethod> requestObjectJWEEncs; 239 240 241 /** 242 * If {@code true} the {@code request} parameter is supported, else 243 * not. 244 */ 245 private boolean requestParamSupported = false; 246 247 248 /** 249 * If {@code true} the {@code request_uri} parameter is supported, else 250 * not. 251 */ 252 private boolean requestURIParamSupported = true; 253 254 255 /** 256 * If {@code true} the {@code request_uri} parameters must be 257 * pre-registered with the provider, else not. 258 */ 259 private boolean requireRequestURIReg = false; 260 261 262 /** 263 * The supported UI locales. 264 */ 265 private List<LangTag> uiLocales; 266 267 268 /** 269 * The service documentation URI. 270 */ 271 private URI serviceDocsURI; 272 273 274 /** 275 * The provider's policy regarding relying party use of data. 276 */ 277 private URI policyURI; 278 279 280 /** 281 * The provider's terms of service. 282 */ 283 private URI tosURI; 284 285 286 /** 287 * If {@code true} the 288 * {@code mutual_tls_sender_constrained_access_tokens} if set, else 289 * not. 290 */ 291 private boolean mutualTLSSenderConstrainedAccessTokens = false; 292 293 294 /** 295 * Custom (not-registered) parameters. 296 */ 297 private final JSONObject customParameters = new JSONObject(); 298 299 300 /** 301 * Creates a new OAuth 2.0 Authorisation Server (AS) metadata instance. 302 * 303 * @param issuer The issuer identifier. Must be an URI using the https 304 * scheme with no query or fragment component. Must not 305 * be {@code null}. 306 */ 307 public AuthorizationServerMetadata(final Issuer issuer) { 308 309 URI uri; 310 try { 311 uri = new URI(issuer.getValue()); 312 } catch (URISyntaxException e) { 313 throw new IllegalArgumentException("The issuer identifier must be a URI: " + e.getMessage(), e); 314 } 315 316 if (uri.getRawQuery() != null) 317 throw new IllegalArgumentException("The issuer URI must be without a query component"); 318 319 if (uri.getRawFragment() != null) 320 throw new IllegalArgumentException("The issuer URI must be without a fragment component"); 321 322 this.issuer = issuer; 323 } 324 325 326 /** 327 * Gets the issuer identifier. Corresponds to the {@code issuer} 328 * metadata field. 329 * 330 * @return The issuer identifier. 331 */ 332 public Issuer getIssuer() { 333 334 return issuer; 335 } 336 337 338 /** 339 * Gets the authorisation endpoint URI. Corresponds the 340 * {@code authorization_endpoint} metadata field. 341 * 342 * @return The authorisation endpoint URI, {@code null} if not 343 * specified. 344 */ 345 public URI getAuthorizationEndpointURI() { 346 347 return authzEndpoint; 348 } 349 350 351 /** 352 * Sets the authorisation endpoint URI. Corresponds the 353 * {@code authorization_endpoint} metadata field. 354 * 355 * @param authzEndpoint The authorisation endpoint URI, {@code null} if 356 * not specified. 357 */ 358 public void setAuthorizationEndpointURI(final URI authzEndpoint) { 359 360 this.authzEndpoint = authzEndpoint; 361 } 362 363 364 /** 365 * Gets the token endpoint URI. Corresponds the {@code token_endpoint} 366 * metadata field. 367 * 368 * @return The token endpoint URI, {@code null} if not specified. 369 */ 370 public URI getTokenEndpointURI() { 371 372 return tokenEndpoint; 373 } 374 375 376 /** 377 * Sts the token endpoint URI. Corresponds the {@code token_endpoint} 378 * metadata field. 379 * 380 * @param tokenEndpoint The token endpoint URI, {@code null} if not 381 * specified. 382 */ 383 public void setTokenEndpointURI(final URI tokenEndpoint) { 384 385 this.tokenEndpoint = tokenEndpoint; 386 } 387 388 389 /** 390 * Gets the client registration endpoint URI. Corresponds to the 391 * {@code registration_endpoint} metadata field. 392 * 393 * @return The client registration endpoint URI, {@code null} if not 394 * specified. 395 */ 396 public URI getRegistrationEndpointURI() { 397 398 return regEndpoint; 399 } 400 401 402 /** 403 * Sets the client registration endpoint URI. Corresponds to the 404 * {@code registration_endpoint} metadata field. 405 * 406 * @param regEndpoint The client registration endpoint URI, 407 * {@code null} if not specified. 408 */ 409 public void setRegistrationEndpointURI(final URI regEndpoint) { 410 411 this.regEndpoint = regEndpoint; 412 } 413 414 415 /** 416 * Gets the token introspection endpoint URI. Corresponds to the 417 * {@code introspection_endpoint} metadata field. 418 * 419 * @return The token introspection endpoint URI, {@code null} if not 420 * specified. 421 */ 422 public URI getIntrospectionEndpointURI() { 423 424 return introspectionEndpoint; 425 } 426 427 428 /** 429 * Sets the token introspection endpoint URI. Corresponds to the 430 * {@code introspection_endpoint} metadata field. 431 * 432 * @param introspectionEndpoint The token introspection endpoint URI, 433 * {@code null} if not specified. 434 */ 435 public void setIntrospectionEndpointURI(final URI introspectionEndpoint) { 436 437 this.introspectionEndpoint = introspectionEndpoint; 438 } 439 440 441 /** 442 * Gets the token revocation endpoint URI. Corresponds to the 443 * {@code revocation_endpoint} metadata field. 444 * 445 * @return The token revocation endpoint URI, {@code null} if not 446 * specified. 447 */ 448 public URI getRevocationEndpointURI() { 449 450 return revocationEndpoint; 451 } 452 453 454 /** 455 * Sets the token revocation endpoint URI. Corresponds to the 456 * {@code revocation_endpoint} metadata field. 457 * 458 * @param revocationEndpoint The token revocation endpoint URI, 459 * {@code null} if not specified. 460 */ 461 public void setRevocationEndpointURI(final URI revocationEndpoint) { 462 463 this.revocationEndpoint = revocationEndpoint; 464 } 465 466 467 /** 468 * Gets the JSON Web Key (JWK) set URI. Corresponds to the 469 * {@code jwks_uri} metadata field. 470 * 471 * @return The JWK set URI, {@code null} if not specified. 472 */ 473 public URI getJWKSetURI() { 474 475 return jwkSetURI; 476 } 477 478 479 /** 480 * Sets the JSON Web Key (JWT) set URI. Corresponds to the 481 * {@code jwks_uri} metadata field. 482 * 483 * @param jwkSetURI The JWK set URI, {@code null} if not specified. 484 */ 485 public void setJWKSetURI(final URI jwkSetURI) { 486 487 this.jwkSetURI = jwkSetURI; 488 } 489 490 491 /** 492 * Gets the supported scope values. Corresponds to the 493 * {@code scopes_supported} metadata field. 494 * 495 * @return The supported scope values, {@code null} if not specified. 496 */ 497 public Scope getScopes() { 498 499 return scope; 500 } 501 502 503 /** 504 * Sets the supported scope values. Corresponds to the 505 * {@code scopes_supported} metadata field. 506 * 507 * @param scope The supported scope values, {@code null} if not 508 * specified. 509 */ 510 public void setScopes(final Scope scope) { 511 512 this.scope = scope; 513 } 514 515 516 /** 517 * Gets the supported response type values. Corresponds to the 518 * {@code response_types_supported} metadata field. 519 * 520 * @return The supported response type values, {@code null} if not 521 * specified. 522 */ 523 public List<ResponseType> getResponseTypes() { 524 525 return rts; 526 } 527 528 529 /** 530 * Sets the supported response type values. Corresponds to the 531 * {@code response_types_supported} metadata field. 532 * 533 * @param rts The supported response type values, {@code null} if not 534 * specified. 535 */ 536 public void setResponseTypes(final List<ResponseType> rts) { 537 538 this.rts = rts; 539 } 540 541 542 /** 543 * Gets the supported response mode values. Corresponds to the 544 * {@code response_modes_supported}. 545 * 546 * @return The supported response mode values, {@code null} if not 547 * specified. 548 */ 549 public List<ResponseMode> getResponseModes() { 550 551 return rms; 552 } 553 554 555 /** 556 * Sets the supported response mode values. Corresponds to the 557 * {@code response_modes_supported}. 558 * 559 * @param rms The supported response mode values, {@code null} if not 560 * specified. 561 */ 562 public void setResponseModes(final List<ResponseMode> rms) { 563 564 this.rms = rms; 565 } 566 567 568 /** 569 * Gets the supported OAuth 2.0 grant types. Corresponds to the 570 * {@code grant_types_supported} metadata field. 571 * 572 * @return The supported grant types, {@code null} if not specified. 573 */ 574 public List<GrantType> getGrantTypes() { 575 576 return gts; 577 } 578 579 580 /** 581 * Sets the supported OAuth 2.0 grant types. Corresponds to the 582 * {@code grant_types_supported} metadata field. 583 * 584 * @param gts The supported grant types, {@code null} if not specified. 585 */ 586 public void setGrantTypes(final List<GrantType> gts) { 587 588 this.gts = gts; 589 } 590 591 592 /** 593 * Gets the supported authorisation code challenge methods for PKCE. 594 * Corresponds to the {@code code_challenge_methods_supported} metadata 595 * field. 596 * 597 * @return The supported code challenge methods, {@code null} if not 598 * specified. 599 */ 600 public List<CodeChallengeMethod> getCodeChallengeMethods() { 601 602 return codeChallengeMethods; 603 } 604 605 606 /** 607 * Gets the supported authorisation code challenge methods for PKCE. 608 * Corresponds to the {@code code_challenge_methods_supported} metadata 609 * field. 610 * 611 * @param codeChallengeMethods The supported code challenge methods, 612 * {@code null} if not specified. 613 */ 614 public void setCodeChallengeMethods(final List<CodeChallengeMethod> codeChallengeMethods) { 615 616 this.codeChallengeMethods = codeChallengeMethods; 617 } 618 619 620 /** 621 * Gets the supported token endpoint authentication methods. 622 * Corresponds to the {@code token_endpoint_auth_methods_supported} 623 * metadata field. 624 * 625 * @return The supported token endpoint authentication methods, 626 * {@code null} if not specified. 627 */ 628 public List<ClientAuthenticationMethod> getTokenEndpointAuthMethods() { 629 630 return tokenEndpointAuthMethods; 631 } 632 633 634 /** 635 * Sets the supported token endpoint authentication methods. 636 * Corresponds to the {@code token_endpoint_auth_methods_supported} 637 * metadata field. 638 * 639 * @param authMethods The supported token endpoint authentication 640 * methods, {@code null} if not specified. 641 */ 642 public void setTokenEndpointAuthMethods(final List<ClientAuthenticationMethod> authMethods) { 643 644 this.tokenEndpointAuthMethods = authMethods; 645 } 646 647 648 /** 649 * Gets the supported JWS algorithms for the {@code private_key_jwt} 650 * and {@code client_secret_jwt} token endpoint authentication methods. 651 * Corresponds to the 652 * {@code token_endpoint_auth_signing_alg_values_supported} metadata 653 * field. 654 * 655 * @return The supported JWS algorithms, {@code null} if not specified. 656 */ 657 public List<JWSAlgorithm> getTokenEndpointJWSAlgs() { 658 659 return tokenEndpointJWSAlgs; 660 } 661 662 663 /** 664 * Sets the supported JWS algorithms for the {@code private_key_jwt} 665 * and {@code client_secret_jwt} token endpoint authentication methods. 666 * Corresponds to the 667 * {@code token_endpoint_auth_signing_alg_values_supported} metadata 668 * field. 669 * 670 * @param jwsAlgs The supported JWS algorithms, {@code null} if not 671 * specified. Must not contain the {@code none} 672 * algorithm. 673 */ 674 public void setTokenEndpointJWSAlgs(final List<JWSAlgorithm> jwsAlgs) { 675 676 if (jwsAlgs != null && jwsAlgs.contains(Algorithm.NONE)) 677 throw new IllegalArgumentException("The \"none\" algorithm is not accepted"); 678 679 this.tokenEndpointJWSAlgs = jwsAlgs; 680 } 681 682 683 /** 684 * Gets the supported introspection endpoint authentication methods. 685 * Corresponds to the 686 * {@code introspection_endpoint_auth_methods_supported} metadata 687 * field. 688 * 689 * @return The supported introspection endpoint authentication methods, 690 * {@code null} if not specified. 691 */ 692 public List<ClientAuthenticationMethod> getIntrospectionEndpointAuthMethods() { 693 return introspectionEndpointAuthMethods; 694 } 695 696 697 /** 698 * Sets the supported introspection endpoint authentication methods. 699 * Corresponds to the 700 * {@code introspection_endpoint_auth_methods_supported} metadata 701 * field. 702 * 703 * @param authMethods The supported introspection endpoint 704 * authentication methods, {@code null} if not 705 * specified. 706 */ 707 public void setIntrospectionEndpointAuthMethods(final List<ClientAuthenticationMethod> authMethods) { 708 709 this.introspectionEndpointAuthMethods = authMethods; 710 } 711 712 713 /** 714 * Gets the supported JWS algorithms for the {@code private_key_jwt} 715 * and {@code client_secret_jwt} introspection endpoint authentication 716 * methods. Corresponds to the 717 * {@code introspection_endpoint_auth_signing_alg_values_supported} 718 * metadata field. 719 * 720 * @return The supported JWS algorithms, {@code null} if not specified. 721 */ 722 public List<JWSAlgorithm> getIntrospectionEndpointJWSAlgs() { 723 724 return introspectionEndpointJWSAlgs; 725 } 726 727 728 /** 729 * Sets the supported JWS algorithms for the {@code private_key_jwt} 730 * and {@code client_secret_jwt} introspection endpoint authentication 731 * methods. Corresponds to the 732 * {@code introspection_endpoint_auth_signing_alg_values_supported} 733 * metadata field. 734 * 735 * @param jwsAlgs The supported JWS algorithms, {@code null} if not 736 * specified. Must not contain the {@code none} 737 * algorithm. 738 */ 739 public void setIntrospectionEndpointJWSAlgs(final List<JWSAlgorithm> jwsAlgs) { 740 741 if (jwsAlgs != null && jwsAlgs.contains(Algorithm.NONE)) 742 throw new IllegalArgumentException("The \"none\" algorithm is not accepted"); 743 744 introspectionEndpointJWSAlgs = jwsAlgs; 745 } 746 747 748 /** 749 * Gets the supported revocation endpoint authentication methods. 750 * Corresponds to the 751 * {@code revocation_endpoint_auth_methods_supported} metadata field. 752 * 753 * @return The supported revocation endpoint authentication methods, 754 * {@code null} if not specified. 755 */ 756 public List<ClientAuthenticationMethod> getRevocationEndpointAuthMethods() { 757 758 return revocationEndpointAuthMethods; 759 } 760 761 762 /** 763 * Sets the supported revocation endpoint authentication methods. 764 * Corresponds to the 765 * {@code revocation_endpoint_auth_methods_supported} metadata field. 766 * 767 * @param authMethods The supported revocation endpoint authentication 768 * methods, {@code null} if not specified. 769 */ 770 public void setRevocationEndpointAuthMethods(final List<ClientAuthenticationMethod> authMethods) { 771 772 revocationEndpointAuthMethods = authMethods; 773 } 774 775 776 /** 777 * Gets the supported JWS algorithms for the {@code private_key_jwt} 778 * and {@code client_secret_jwt} revocation endpoint authentication 779 * methods. Corresponds to the 780 * {@code revocation_endpoint_auth_signing_alg_values_supported} 781 * metadata field. 782 * 783 * @return The supported JWS algorithms, {@code null} if not specified. 784 */ 785 public List<JWSAlgorithm> getRevocationEndpointJWSAlgs() { 786 787 return revocationEndpointJWSAlgs; 788 } 789 790 791 /** 792 * Sets the supported JWS algorithms for the {@code private_key_jwt} 793 * and {@code client_secret_jwt} revocation endpoint authentication 794 * methods. Corresponds to the 795 * {@code revocation_endpoint_auth_signing_alg_values_supported} 796 * metadata field. 797 * 798 * @param jwsAlgs The supported JWS algorithms, {@code null} if not 799 * specified. Must not contain the {@code none} 800 * algorithm. 801 */ 802 public void setRevocationEndpointJWSAlgs(final List<JWSAlgorithm> jwsAlgs) { 803 804 if (jwsAlgs != null && jwsAlgs.contains(Algorithm.NONE)) 805 throw new IllegalArgumentException("The \"none\" algorithm is not accepted"); 806 807 revocationEndpointJWSAlgs = jwsAlgs; 808 } 809 810 811 /** 812 * Gets the supported JWS algorithms for request objects. Corresponds 813 * to the {@code request_object_signing_alg_values_supported} metadata 814 * field. 815 * 816 * @return The supported JWS algorithms, {@code null} if not specified. 817 */ 818 public List<JWSAlgorithm> getRequestObjectJWSAlgs() { 819 820 return requestObjectJWSAlgs; 821 } 822 823 824 /** 825 * Sets the supported JWS algorithms for request objects. Corresponds 826 * to the {@code request_object_signing_alg_values_supported} metadata 827 * field. 828 * 829 * @param requestObjectJWSAlgs The supported JWS algorithms, 830 * {@code null} if not specified. 831 */ 832 public void setRequestObjectJWSAlgs(final List<JWSAlgorithm> requestObjectJWSAlgs) { 833 834 this.requestObjectJWSAlgs = requestObjectJWSAlgs; 835 } 836 837 838 /** 839 * Gets the supported JWE algorithms for request objects. Corresponds 840 * to the {@code request_object_encryption_alg_values_supported} 841 * metadata field. 842 * 843 * @return The supported JWE algorithms, {@code null} if not specified. 844 */ 845 public List<JWEAlgorithm> getRequestObjectJWEAlgs() { 846 847 return requestObjectJWEAlgs; 848 } 849 850 851 /** 852 * Sets the supported JWE algorithms for request objects. Corresponds 853 * to the {@code request_object_encryption_alg_values_supported} 854 * metadata field. 855 * 856 * @param requestObjectJWEAlgs The supported JWE algorithms, 857 * {@code null} if not specified. 858 */ 859 public void setRequestObjectJWEAlgs(final List<JWEAlgorithm> requestObjectJWEAlgs) { 860 861 this.requestObjectJWEAlgs = requestObjectJWEAlgs; 862 } 863 864 865 /** 866 * Gets the supported encryption methods for request objects. 867 * Corresponds to the 868 * {@code request_object_encryption_enc_values_supported} metadata 869 * field. 870 * 871 * @return The supported encryption methods, {@code null} if not 872 * specified. 873 */ 874 public List<EncryptionMethod> getRequestObjectJWEEncs() { 875 876 return requestObjectJWEEncs; 877 } 878 879 880 /** 881 * Sets the supported encryption methods for request objects. 882 * Corresponds to the 883 * {@code request_object_encryption_enc_values_supported} metadata 884 * field. 885 * 886 * @param requestObjectJWEEncs The supported encryption methods, 887 * {@code null} if not specified. 888 */ 889 public void setRequestObjectJWEEncs(final List<EncryptionMethod> requestObjectJWEEncs) { 890 891 this.requestObjectJWEEncs = requestObjectJWEEncs; 892 } 893 894 895 /** 896 * Gets the support for the {@code request} authorisation request 897 * parameter. Corresponds to the {@code request_parameter_supported} 898 * metadata field. 899 * 900 * @return {@code true} if the {@code reqeust} parameter is supported, 901 * else {@code false}. 902 */ 903 public boolean supportsRequestParam() { 904 905 return requestParamSupported; 906 } 907 908 909 /** 910 * Sets the support for the {@code request} authorisation request 911 * parameter. Corresponds to the {@code request_parameter_supported} 912 * metadata field. 913 * 914 * @param requestParamSupported {@code true} if the {@code reqeust} 915 * parameter is supported, else 916 * {@code false}. 917 */ 918 public void setSupportsRequestParam(final boolean requestParamSupported) { 919 920 this.requestParamSupported = requestParamSupported; 921 } 922 923 924 /** 925 * Gets the support for the {@code request_uri} authorisation request 926 * parameter. Corresponds the {@code request_uri_parameter_supported} 927 * metadata field. 928 * 929 * @return {@code true} if the {@code request_uri} parameter is 930 * supported, else {@code false}. 931 */ 932 public boolean supportsRequestURIParam() { 933 934 return requestURIParamSupported; 935 } 936 937 938 /** 939 * Sets the support for the {@code request_uri} authorisation request 940 * parameter. Corresponds the {@code request_uri_parameter_supported} 941 * metadata field. 942 * 943 * @param requestURIParamSupported {@code true} if the 944 * {@code request_uri} parameter is 945 * supported, else {@code false}. 946 */ 947 public void setSupportsRequestURIParam(final boolean requestURIParamSupported) { 948 949 this.requestURIParamSupported = requestURIParamSupported; 950 } 951 952 953 /** 954 * Gets the requirement for the {@code request_uri} parameter 955 * pre-registration. Corresponds to the 956 * {@code require_request_uri_registration} metadata field. 957 * 958 * @return {@code true} if the {@code request_uri} parameter values 959 * must be pre-registered, else {@code false}. 960 */ 961 public boolean requiresRequestURIRegistration() { 962 963 return requireRequestURIReg; 964 } 965 966 967 /** 968 * Sets the requirement for the {@code request_uri} parameter 969 * pre-registration. Corresponds to the 970 * {@code require_request_uri_registration} metadata field. 971 * 972 * @param requireRequestURIReg {@code true} if the {@code request_uri} 973 * parameter values must be pre-registered, 974 * else {@code false}. 975 */ 976 public void setRequiresRequestURIRegistration(final boolean requireRequestURIReg) { 977 978 this.requireRequestURIReg = requireRequestURIReg; 979 } 980 981 982 /** 983 * Gets the supported UI locales. Corresponds to the 984 * {@code ui_locales_supported} metadata field. 985 * 986 * @return The supported UI locales, {@code null} if not specified. 987 */ 988 public List<LangTag> getUILocales() { 989 990 return uiLocales; 991 } 992 993 994 /** 995 * Sets the supported UI locales. Corresponds to the 996 * {@code ui_locales_supported} metadata field. 997 * 998 * @param uiLocales The supported UI locales, {@code null} if not 999 * specified. 1000 */ 1001 public void setUILocales(final List<LangTag> uiLocales) { 1002 1003 this.uiLocales = uiLocales; 1004 } 1005 1006 1007 /** 1008 * Gets the service documentation URI. Corresponds to the 1009 * {@code service_documentation} metadata field. 1010 * 1011 * @return The service documentation URI, {@code null} if not 1012 * specified. 1013 */ 1014 public URI getServiceDocsURI() { 1015 1016 return serviceDocsURI; 1017 } 1018 1019 1020 /** 1021 * Sets the service documentation URI. Corresponds to the 1022 * {@code service_documentation} metadata field. 1023 * 1024 * @param serviceDocsURI The service documentation URI, {@code null} if 1025 * not specified. 1026 */ 1027 public void setServiceDocsURI(final URI serviceDocsURI) { 1028 1029 this.serviceDocsURI = serviceDocsURI; 1030 } 1031 1032 1033 /** 1034 * Gets the provider's policy regarding relying party use of data. 1035 * Corresponds to the {@code op_policy_uri} metadata field. 1036 * 1037 * @return The policy URI, {@code null} if not specified. 1038 */ 1039 public URI getPolicyURI() { 1040 1041 return policyURI; 1042 } 1043 1044 1045 /** 1046 * Sets the provider's policy regarding relying party use of data. 1047 * Corresponds to the {@code op_policy_uri} metadata field. 1048 * 1049 * @param policyURI The policy URI, {@code null} if not specified. 1050 */ 1051 public void setPolicyURI(final URI policyURI) { 1052 1053 this.policyURI = policyURI; 1054 } 1055 1056 1057 /** 1058 * Gets the provider's terms of service. Corresponds to the 1059 * {@code op_tos_uri} metadata field. 1060 * 1061 * @return The terms of service URI, {@code null} if not specified. 1062 */ 1063 public URI getTermsOfServiceURI() { 1064 1065 return tosURI; 1066 } 1067 1068 1069 /** 1070 * Sets the provider's terms of service. Corresponds to the 1071 * {@code op_tos_uri} metadata field. 1072 * 1073 * @param tosURI The terms of service URI, {@code null} if not 1074 * specified. 1075 */ 1076 public void setTermsOfServiceURI(final URI tosURI) { 1077 1078 this.tosURI = tosURI; 1079 } 1080 1081 1082 /** 1083 * Gets the support for mutual TLS sender constrained access tokens. 1084 * Corresponds to the 1085 * {@code mutual_tls_sender_constrained_access_tokens} metadata field. 1086 * 1087 * @return {@code true} if mutual TLS sender constrained access tokens 1088 * are supported, else {@code false}. 1089 */ 1090 public boolean supportsMutualTLSSenderConstrainedAccessTokens() { 1091 1092 return mutualTLSSenderConstrainedAccessTokens; 1093 } 1094 1095 1096 /** 1097 * Sets the support for mutual TLS sender constrained access tokens. 1098 * Corresponds to the 1099 * {@code mutual_tls_sender_constrained_access_tokens} metadata field. 1100 * 1101 * @param mutualTLSSenderConstrainedAccessTokens {@code true} if mutual 1102 * TLS sender constrained 1103 * access tokens are 1104 * supported, else 1105 * {@code false}. 1106 */ 1107 public void setSupportsMutualTLSSenderConstrainedAccessTokens(final boolean mutualTLSSenderConstrainedAccessTokens) { 1108 1109 this.mutualTLSSenderConstrainedAccessTokens = mutualTLSSenderConstrainedAccessTokens; 1110 } 1111 1112 1113 /** 1114 * Gets the specified custom (not registered) parameter. 1115 * 1116 * @param name The parameter name. Must not be {@code null}. 1117 * 1118 * @return The parameter value, {@code null} if not specified. 1119 */ 1120 public Object getCustomParameter(final String name) { 1121 1122 return customParameters.get(name); 1123 } 1124 1125 1126 /** 1127 * Gets the specified custom (not registered) URI parameter. 1128 * 1129 * @param name The parameter name. Must not be {@code null}. 1130 * 1131 * @return The parameter URI value, {@code null} if not specified. 1132 */ 1133 public URI getCustomURIParameter(final String name) { 1134 1135 try { 1136 return JSONObjectUtils.getURI(customParameters, name); 1137 } catch (ParseException e) { 1138 return null; 1139 } 1140 } 1141 1142 1143 /** 1144 * Sets the specified custom (not registered) parameter. 1145 * 1146 * @param name The parameter name. Must not be {@code null}. 1147 * @param value The parameter value, {@code null} if not specified. 1148 */ 1149 public void setCustomParameter(final String name, final Object value) { 1150 1151 if (REGISTERED_PARAMETER_NAMES.contains(name)) { 1152 throw new IllegalArgumentException("The " + name + " parameter is registered"); 1153 } 1154 1155 customParameters.put(name, value); 1156 } 1157 1158 1159 /** 1160 * Gets the custom (not registered) parameters. 1161 * 1162 * @return The custom parameters, empty JSON object if none. 1163 */ 1164 public JSONObject getCustomParameters() { 1165 1166 return customParameters; 1167 } 1168 1169 1170 /** 1171 * Applies the OAuth 2.0 Authorisation Server metadata defaults where 1172 * no values have been specified. 1173 * 1174 * <ul> 1175 * <li>The response modes default to {@code ["query", "fragment"]}. 1176 * <li>The grant types default to {@code ["authorization_code", 1177 * "implicit"]}. 1178 * <li>The token endpoint authentication methods default to 1179 * {@code ["client_secret_basic"]}. 1180 * </ul> 1181 */ 1182 public void applyDefaults() { 1183 1184 if (rms == null) { 1185 rms = new ArrayList<>(2); 1186 rms.add(ResponseMode.QUERY); 1187 rms.add(ResponseMode.FRAGMENT); 1188 } 1189 1190 if (gts == null) { 1191 gts = new ArrayList<>(2); 1192 gts.add(GrantType.AUTHORIZATION_CODE); 1193 gts.add(GrantType.IMPLICIT); 1194 } 1195 } 1196 1197 1198 /** 1199 * Returns the JSON object representation of this OpenID Connect 1200 * provider metadata. 1201 * 1202 * @return The JSON object representation. 1203 */ 1204 public JSONObject toJSONObject() { 1205 1206 JSONObject o = new OrderedJSONObject(); 1207 1208 // Mandatory fields 1209 o.put("issuer", issuer.getValue()); 1210 1211 1212 // Optional fields 1213 if (jwkSetURI != null) 1214 o.put("jwks_uri", jwkSetURI.toString()); 1215 1216 if (authzEndpoint != null) 1217 o.put("authorization_endpoint", authzEndpoint.toString()); 1218 1219 if (tokenEndpoint != null) 1220 o.put("token_endpoint", tokenEndpoint.toString()); 1221 1222 if (regEndpoint != null) 1223 o.put("registration_endpoint", regEndpoint.toString()); 1224 1225 if (introspectionEndpoint != null) 1226 o.put("introspection_endpoint", introspectionEndpoint.toString()); 1227 1228 if (revocationEndpoint != null) 1229 o.put("revocation_endpoint", revocationEndpoint.toString()); 1230 1231 if (scope != null) 1232 o.put("scopes_supported", scope.toStringList()); 1233 1234 List<String> stringList; 1235 1236 if (rts != null) { 1237 1238 stringList = new ArrayList<>(rts.size()); 1239 1240 for (ResponseType rt: rts) 1241 stringList.add(rt.toString()); 1242 1243 o.put("response_types_supported", stringList); 1244 } 1245 1246 if (rms != null) { 1247 1248 stringList = new ArrayList<>(rms.size()); 1249 1250 for (ResponseMode rm: rms) 1251 stringList.add(rm.getValue()); 1252 1253 o.put("response_modes_supported", stringList); 1254 } 1255 1256 if (gts != null) { 1257 1258 stringList = new ArrayList<>(gts.size()); 1259 1260 for (GrantType gt: gts) 1261 stringList.add(gt.toString()); 1262 1263 o.put("grant_types_supported", stringList); 1264 } 1265 1266 if (codeChallengeMethods != null) { 1267 1268 stringList = new ArrayList<>(codeChallengeMethods.size()); 1269 1270 for (CodeChallengeMethod m: codeChallengeMethods) 1271 stringList.add(m.getValue()); 1272 1273 o.put("code_challenge_methods_supported", stringList); 1274 } 1275 1276 1277 if (tokenEndpointAuthMethods != null) { 1278 1279 stringList = new ArrayList<>(tokenEndpointAuthMethods.size()); 1280 1281 for (ClientAuthenticationMethod m: tokenEndpointAuthMethods) 1282 stringList.add(m.getValue()); 1283 1284 o.put("token_endpoint_auth_methods_supported", stringList); 1285 } 1286 1287 if (tokenEndpointJWSAlgs != null) { 1288 1289 stringList = new ArrayList<>(tokenEndpointJWSAlgs.size()); 1290 1291 for (JWSAlgorithm alg: tokenEndpointJWSAlgs) 1292 stringList.add(alg.getName()); 1293 1294 o.put("token_endpoint_auth_signing_alg_values_supported", stringList); 1295 } 1296 1297 if (introspectionEndpointAuthMethods != null) { 1298 1299 stringList = new ArrayList<>(introspectionEndpointAuthMethods.size()); 1300 1301 for (ClientAuthenticationMethod m: introspectionEndpointAuthMethods) 1302 stringList.add(m.getValue()); 1303 1304 o.put("introspection_endpoint_auth_methods_supported", stringList); 1305 } 1306 1307 if (introspectionEndpointJWSAlgs != null) { 1308 1309 stringList = new ArrayList<>(introspectionEndpointJWSAlgs.size()); 1310 1311 for (JWSAlgorithm alg: introspectionEndpointJWSAlgs) 1312 stringList.add(alg.getName()); 1313 1314 o.put("introspection_endpoint_auth_signing_alg_values_supported", stringList); 1315 } 1316 1317 if (revocationEndpointAuthMethods != null) { 1318 1319 stringList = new ArrayList<>(revocationEndpointAuthMethods.size()); 1320 1321 for (ClientAuthenticationMethod m: revocationEndpointAuthMethods) 1322 stringList.add(m.getValue()); 1323 1324 o.put("revocation_endpoint_auth_methods_supported", stringList); 1325 } 1326 1327 if (revocationEndpointJWSAlgs != null) { 1328 1329 stringList = new ArrayList<>(revocationEndpointJWSAlgs.size()); 1330 1331 for (JWSAlgorithm alg: revocationEndpointJWSAlgs) 1332 stringList.add(alg.getName()); 1333 1334 o.put("revocation_endpoint_auth_signing_alg_values_supported", stringList); 1335 } 1336 1337 if (requestObjectJWSAlgs != null) { 1338 1339 stringList = new ArrayList<>(requestObjectJWSAlgs.size()); 1340 1341 for (JWSAlgorithm alg: requestObjectJWSAlgs) 1342 stringList.add(alg.getName()); 1343 1344 o.put("request_object_signing_alg_values_supported", stringList); 1345 } 1346 1347 if (requestObjectJWEAlgs != null) { 1348 1349 stringList = new ArrayList<>(requestObjectJWEAlgs.size()); 1350 1351 for (JWEAlgorithm alg: requestObjectJWEAlgs) 1352 stringList.add(alg.getName()); 1353 1354 o.put("request_object_encryption_alg_values_supported", stringList); 1355 } 1356 1357 if (requestObjectJWEEncs != null) { 1358 1359 stringList = new ArrayList<>(requestObjectJWEEncs.size()); 1360 1361 for (EncryptionMethod m: requestObjectJWEEncs) 1362 stringList.add(m.getName()); 1363 1364 o.put("request_object_encryption_enc_values_supported", stringList); 1365 } 1366 1367 if (uiLocales != null) { 1368 1369 stringList = new ArrayList<>(uiLocales.size()); 1370 1371 for (LangTag l: uiLocales) 1372 stringList.add(l.toString()); 1373 1374 o.put("ui_locales_supported", stringList); 1375 } 1376 1377 if (serviceDocsURI != null) 1378 o.put("service_documentation", serviceDocsURI.toString()); 1379 1380 if (policyURI != null) 1381 o.put("op_policy_uri", policyURI.toString()); 1382 1383 if (tosURI != null) 1384 o.put("op_tos_uri", tosURI.toString()); 1385 1386 o.put("request_parameter_supported", requestParamSupported); 1387 o.put("request_uri_parameter_supported", requestURIParamSupported); 1388 o.put("require_request_uri_registration", requireRequestURIReg); 1389 1390 o.put("mutual_tls_sender_constrained_access_tokens", mutualTLSSenderConstrainedAccessTokens); 1391 1392 // Append any custom (not registered) parameters 1393 o.putAll(customParameters); 1394 1395 return o; 1396 } 1397 1398 1399 @Override 1400 public String toString() { 1401 return toJSONObject().toJSONString(); 1402 } 1403 1404 1405 /** 1406 * Parses an OAuth 2.0 Authorisation Server metadata from the specified 1407 * JSON object. 1408 * 1409 * @param jsonObject The JSON object to parse. Must not be 1410 * {@code null}. 1411 * 1412 * @return The OAuth 2.0 Authorisation Server metadata. 1413 * 1414 * @throws ParseException If the JSON object couldn't be parsed to an 1415 * OAuth 2.0 Authorisation Server metadata. 1416 */ 1417 public static AuthorizationServerMetadata parse(final JSONObject jsonObject) 1418 throws ParseException { 1419 1420 // Parse issuer and subject_types_supported first 1421 1422 Issuer issuer = new Issuer(JSONObjectUtils.getURI(jsonObject, "issuer").toString()); 1423 1424 AuthorizationServerMetadata as; 1425 1426 try { 1427 as = new AuthorizationServerMetadata(issuer); // validates issuer syntax 1428 } catch (IllegalArgumentException e) { 1429 throw new ParseException(e.getMessage(), e); 1430 } 1431 1432 // Endpoints 1433 if (jsonObject.get("authorization_endpoint") != null) 1434 as.authzEndpoint = JSONObjectUtils.getURI(jsonObject, "authorization_endpoint"); 1435 1436 if (jsonObject.get("token_endpoint") != null) 1437 as.tokenEndpoint = JSONObjectUtils.getURI(jsonObject, "token_endpoint"); 1438 1439 if (jsonObject.get("registration_endpoint") != null) 1440 as.regEndpoint = JSONObjectUtils.getURI(jsonObject, "registration_endpoint"); 1441 1442 if (jsonObject.get("jwks_uri") != null) 1443 as.jwkSetURI = JSONObjectUtils.getURI(jsonObject, "jwks_uri"); 1444 1445 if (jsonObject.get("introspection_endpoint") != null) 1446 as.introspectionEndpoint = JSONObjectUtils.getURI(jsonObject, "introspection_endpoint"); 1447 1448 if (jsonObject.get("revocation_endpoint") != null) 1449 as.revocationEndpoint = JSONObjectUtils.getURI(jsonObject, "revocation_endpoint"); 1450 1451 // AS capabilities 1452 if (jsonObject.get("scopes_supported") != null) { 1453 1454 as.scope = new Scope(); 1455 1456 for (String v: JSONObjectUtils.getStringArray(jsonObject, "scopes_supported")) { 1457 1458 if (v != null) 1459 as.scope.add(new Scope.Value(v)); 1460 } 1461 } 1462 1463 if (jsonObject.get("response_types_supported") != null) { 1464 1465 as.rts = new ArrayList<>(); 1466 1467 for (String v: JSONObjectUtils.getStringArray(jsonObject, "response_types_supported")) { 1468 1469 if (v != null) 1470 as.rts.add(ResponseType.parse(v)); 1471 } 1472 } 1473 1474 if (jsonObject.get("response_modes_supported") != null) { 1475 1476 as.rms = new ArrayList<>(); 1477 1478 for (String v: JSONObjectUtils.getStringArray(jsonObject, "response_modes_supported")) { 1479 1480 if (v != null) 1481 as.rms.add(new ResponseMode(v)); 1482 } 1483 } 1484 1485 if (jsonObject.get("grant_types_supported") != null) { 1486 1487 as.gts = new ArrayList<>(); 1488 1489 for (String v: JSONObjectUtils.getStringArray(jsonObject, "grant_types_supported")) { 1490 1491 if (v != null) 1492 as.gts.add(GrantType.parse(v)); 1493 } 1494 } 1495 1496 if (jsonObject.get("code_challenge_methods_supported") != null) { 1497 1498 as.codeChallengeMethods = new ArrayList<>(); 1499 1500 for (String v: JSONObjectUtils.getStringArray(jsonObject, "code_challenge_methods_supported")) { 1501 1502 if (v != null) 1503 as.codeChallengeMethods.add(CodeChallengeMethod.parse(v)); 1504 } 1505 } 1506 1507 if (jsonObject.get("token_endpoint_auth_methods_supported") != null) { 1508 1509 as.tokenEndpointAuthMethods = new ArrayList<>(); 1510 1511 for (String v: JSONObjectUtils.getStringArray(jsonObject, "token_endpoint_auth_methods_supported")) { 1512 1513 if (v != null) 1514 as.tokenEndpointAuthMethods.add(ClientAuthenticationMethod.parse(v)); 1515 } 1516 } 1517 1518 if (jsonObject.get("token_endpoint_auth_signing_alg_values_supported") != null) { 1519 1520 as.tokenEndpointJWSAlgs = new ArrayList<>(); 1521 1522 for (String v: JSONObjectUtils.getStringArray(jsonObject, "token_endpoint_auth_signing_alg_values_supported")) { 1523 1524 if (v != null && v.equals(Algorithm.NONE.getName())) 1525 throw new ParseException("The none algorithm is not accepted"); 1526 1527 if (v != null) 1528 as.tokenEndpointJWSAlgs.add(JWSAlgorithm.parse(v)); 1529 } 1530 } 1531 1532 if (jsonObject.get("introspection_endpoint_auth_methods_supported") != null) { 1533 1534 as.introspectionEndpointAuthMethods = new ArrayList<>(); 1535 1536 for (String v: JSONObjectUtils.getStringArray(jsonObject, "introspection_endpoint_auth_methods_supported")) { 1537 1538 if (v != null) 1539 as.introspectionEndpointAuthMethods.add(ClientAuthenticationMethod.parse(v)); 1540 } 1541 } 1542 1543 if (jsonObject.get("introspection_endpoint_auth_signing_alg_values_supported") != null) { 1544 1545 as.introspectionEndpointJWSAlgs = new ArrayList<>(); 1546 1547 for (String v: JSONObjectUtils.getStringArray(jsonObject, "introspection_endpoint_auth_signing_alg_values_supported")) { 1548 1549 if (v != null && v.equals(Algorithm.NONE.getName())) 1550 throw new ParseException("The none algorithm is not accepted"); 1551 1552 if (v != null) 1553 as.introspectionEndpointJWSAlgs.add(JWSAlgorithm.parse(v)); 1554 } 1555 } 1556 1557 if (jsonObject.get("revocation_endpoint_auth_methods_supported") != null) { 1558 1559 as.revocationEndpointAuthMethods = new ArrayList<>(); 1560 1561 for (String v: JSONObjectUtils.getStringArray(jsonObject, "revocation_endpoint_auth_methods_supported")) { 1562 1563 if (v != null) 1564 as.revocationEndpointAuthMethods.add(ClientAuthenticationMethod.parse(v)); 1565 } 1566 } 1567 1568 if (jsonObject.get("revocation_endpoint_auth_signing_alg_values_supported") != null) { 1569 1570 as.revocationEndpointJWSAlgs = new ArrayList<>(); 1571 1572 for (String v: JSONObjectUtils.getStringArray(jsonObject, "revocation_endpoint_auth_signing_alg_values_supported")) { 1573 1574 if (v != null && v.equals(Algorithm.NONE.getName())) 1575 throw new ParseException("The none algorithm is not accepted"); 1576 1577 if (v != null) 1578 as.revocationEndpointJWSAlgs.add(JWSAlgorithm.parse(v)); 1579 } 1580 } 1581 1582 1583 // Request object 1584 1585 if (jsonObject.get("request_object_signing_alg_values_supported") != null) { 1586 1587 as.requestObjectJWSAlgs = new ArrayList<>(); 1588 1589 for (String v: JSONObjectUtils.getStringArray(jsonObject, "request_object_signing_alg_values_supported")) { 1590 1591 if (v != null) 1592 as.requestObjectJWSAlgs.add(JWSAlgorithm.parse(v)); 1593 } 1594 } 1595 1596 1597 if (jsonObject.get("request_object_encryption_alg_values_supported") != null) { 1598 1599 as.requestObjectJWEAlgs = new ArrayList<>(); 1600 1601 for (String v: JSONObjectUtils.getStringArray(jsonObject, "request_object_encryption_alg_values_supported")) { 1602 1603 if (v != null) 1604 as.requestObjectJWEAlgs.add(JWEAlgorithm.parse(v)); 1605 } 1606 } 1607 1608 1609 if (jsonObject.get("request_object_encryption_enc_values_supported") != null) { 1610 1611 as.requestObjectJWEEncs = new ArrayList<>(); 1612 1613 for (String v: JSONObjectUtils.getStringArray(jsonObject, "request_object_encryption_enc_values_supported")) { 1614 1615 if (v != null) 1616 as.requestObjectJWEEncs.add(EncryptionMethod.parse(v)); 1617 } 1618 } 1619 1620 1621 // Misc 1622 1623 if (jsonObject.get("ui_locales_supported") != null) { 1624 1625 as.uiLocales = new ArrayList<>(); 1626 1627 for (String v : JSONObjectUtils.getStringArray(jsonObject, "ui_locales_supported")) { 1628 1629 if (v != null) { 1630 1631 try { 1632 as.uiLocales.add(LangTag.parse(v)); 1633 1634 } catch (LangTagException e) { 1635 1636 throw new ParseException("Invalid ui_locales_supported field: " + e.getMessage(), e); 1637 } 1638 } 1639 } 1640 } 1641 1642 if (jsonObject.get("service_documentation") != null) 1643 as.serviceDocsURI = JSONObjectUtils.getURI(jsonObject, "service_documentation"); 1644 1645 if (jsonObject.get("op_policy_uri") != null) 1646 as.policyURI = JSONObjectUtils.getURI(jsonObject, "op_policy_uri"); 1647 1648 if (jsonObject.get("op_tos_uri") != null) 1649 as.tosURI = JSONObjectUtils.getURI(jsonObject, "op_tos_uri"); 1650 1651 if (jsonObject.get("request_parameter_supported") != null) 1652 as.requestParamSupported = JSONObjectUtils.getBoolean(jsonObject, "request_parameter_supported"); 1653 1654 if (jsonObject.get("request_uri_parameter_supported") != null) 1655 as.requestURIParamSupported = JSONObjectUtils.getBoolean(jsonObject, "request_uri_parameter_supported"); 1656 1657 if (jsonObject.get("require_request_uri_registration") != null) 1658 as.requireRequestURIReg = JSONObjectUtils.getBoolean(jsonObject, "require_request_uri_registration"); 1659 1660 if (jsonObject.get("mutual_tls_sender_constrained_access_tokens") != null) 1661 as.mutualTLSSenderConstrainedAccessTokens = JSONObjectUtils.getBoolean(jsonObject, "mutual_tls_sender_constrained_access_tokens"); 1662 1663 // Parse custom (not registered) parameters 1664 JSONObject customParams = new JSONObject(jsonObject); 1665 customParams.keySet().removeAll(REGISTERED_PARAMETER_NAMES); 1666 for (Map.Entry<String,Object> customEntry: customParams.entrySet()) { 1667 as.setCustomParameter(customEntry.getKey(), customEntry.getValue()); 1668 } 1669 1670 return as; 1671 } 1672 1673 1674 /** 1675 * Parses an OAuth 2.0 Authorisation Server metadata from the specified 1676 * JSON object string. 1677 * 1678 * @param s The JSON object sting to parse. Must not be {@code null}. 1679 * 1680 * @return The OAuth 2.0 Authorisation Server metadata. 1681 * 1682 * @throws ParseException If the JSON object string couldn't be parsed 1683 * to an OAuth 2.0 Authorisation Server 1684 * metadata. 1685 */ 1686 public static AuthorizationServerMetadata parse(final String s) 1687 throws ParseException { 1688 1689 return parse(JSONObjectUtils.parse(s)); 1690 } 1691 1692 1693 /** 1694 * Resolves OAuth 2.0 authorisation server metadata from the specified 1695 * issuer identifier. The metadata is downloaded by HTTP GET from 1696 * {@code [issuer-url]/.well-known/oauth-authorization-server}. 1697 * 1698 * @param issuer The issuer identifier. Must represent a valid HTTPS or 1699 * HTTP URL. Must not be {@code null}. 1700 * 1701 * @return The OAuth 2.0 authorisation server metadata. 1702 * 1703 * @throws GeneralException If the issuer identifier or the downloaded 1704 * metadata are invalid. 1705 * @throws IOException On a HTTP exception. 1706 */ 1707 public static AuthorizationServerMetadata resolve(final Issuer issuer) 1708 throws GeneralException, IOException { 1709 1710 return resolve(issuer, 0, 0); 1711 } 1712 1713 1714 /** 1715 * Resolves OAuth 2.0 authorisation server metadata from the specified 1716 * issuer identifier. The metadata is downloaded by HTTP GET from 1717 * {@code [issuer-url]/.well-known/oauth-authorization-server}. 1718 * 1719 * @param issuer The issuer identifier. Must represent a valid 1720 * HTTPS or HTTP URL. Must not be {@code null}. 1721 * @param connectTimeout The HTTP connect timeout, in milliseconds. 1722 * Zero implies no timeout. Must not be negative. 1723 * @param readTimeout The HTTP response read timeout, in 1724 * milliseconds. Zero implies no timeout. Must 1725 * not be negative. 1726 * 1727 * @return The OAuth 2.0 authorisation server metadata. 1728 * 1729 * @throws GeneralException If the issuer identifier or the downloaded 1730 * metadata are invalid. 1731 * @throws IOException On a HTTP exception. 1732 */ 1733 public static AuthorizationServerMetadata resolve(final Issuer issuer, 1734 final int connectTimeout, 1735 final int readTimeout) 1736 throws GeneralException, IOException { 1737 1738 URL configURL; 1739 1740 try { 1741 URL issuerURL = new URL(issuer.getValue()); 1742 1743 // Validate but don't insist on HTTPS 1744 if (issuerURL.getQuery() != null && ! issuerURL.getQuery().trim().isEmpty()) { 1745 throw new GeneralException("The issuer identifier must not contain a query component"); 1746 } 1747 1748 if (issuerURL.getPath() != null && issuerURL.getPath().endsWith("/")) { 1749 configURL = new URL(issuerURL + ".well-known/oauth-authorization-server"); 1750 } else { 1751 configURL = new URL(issuerURL + "/.well-known/oauth-authorization-server"); 1752 } 1753 1754 } catch (MalformedURLException e) { 1755 throw new GeneralException("The issuer identifier doesn't represent a valid URL: " + e.getMessage(), e); 1756 } 1757 1758 HTTPRequest httpRequest = new HTTPRequest(HTTPRequest.Method.GET, configURL); 1759 httpRequest.setConnectTimeout(connectTimeout); 1760 httpRequest.setReadTimeout(readTimeout); 1761 1762 HTTPResponse httpResponse = httpRequest.send(); 1763 1764 if (httpResponse.getStatusCode() != 200) { 1765 throw new IOException("Couldn't download OAuth 2.0 Authorization Server metadata from " + configURL + 1766 ": Status code " + httpResponse.getStatusCode()); 1767 } 1768 1769 JSONObject jsonObject = httpResponse.getContentAsJSONObject(); 1770 1771 AuthorizationServerMetadata as = AuthorizationServerMetadata.parse(jsonObject); 1772 1773 if (! issuer.equals(as.issuer)) { 1774 throw new GeneralException("The returned issuer doesn't match the expected: " + as.getIssuer()); 1775 } 1776 1777 return as; 1778 } 1779}