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