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.openid.connect.sdk.op; 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 com.nimbusds.openid.connect.sdk.Display; 043import com.nimbusds.openid.connect.sdk.SubjectType; 044import com.nimbusds.openid.connect.sdk.claims.ACR; 045import com.nimbusds.openid.connect.sdk.claims.ClaimType; 046import net.minidev.json.JSONObject; 047 048 049/** 050 * OpenID Connect provider metadata. 051 * 052 * <p>Related specifications: 053 * 054 * <ul> 055 * <li>OpenID Connect Discovery 1.0, section 3. 056 * <li>OpenID Connect Session Management 1.0, section 2.1 (draft 28). 057 * <li>OpenID Connect Front-Channel Logout 1.0, section 3 (draft 02). 058 * <li>OpenID Connect Back-Channel Logout 1.0, section 2.1 (draft 04). 059 * </ul> 060 */ 061public class OIDCProviderMetadata { 062 063 064 /** 065 * The registered parameter names. 066 */ 067 private static final Set<String> REGISTERED_PARAMETER_NAMES; 068 069 070 static { 071 Set<String> p = new HashSet<>(); 072 073 p.add("issuer"); 074 p.add("authorization_endpoint"); 075 p.add("token_endpoint"); 076 p.add("userinfo_endpoint"); 077 p.add("registration_endpoint"); 078 p.add("check_session_iframe"); 079 p.add("end_session_endpoint"); 080 p.add("jwks_uri"); 081 p.add("scopes_supported"); 082 p.add("response_types_supported"); 083 p.add("response_modes_supported"); 084 p.add("grant_types_supported"); 085 p.add("code_challenge_methods_supported"); 086 p.add("acr_values_supported"); 087 p.add("subject_types_supported"); 088 p.add("token_endpoint_auth_methods_supported"); 089 p.add("token_endpoint_auth_signing_alg_values_supported"); 090 p.add("request_object_signing_alg_values_supported"); 091 p.add("request_object_encryption_alg_values_supported"); 092 p.add("request_object_encryption_enc_values_supported"); 093 p.add("id_token_signing_alg_values_supported"); 094 p.add("id_token_encryption_alg_values_supported"); 095 p.add("id_token_encryption_enc_values_supported"); 096 p.add("userinfo_signing_alg_values_supported"); 097 p.add("userinfo_encryption_alg_values_supported"); 098 p.add("userinfo_encryption_enc_values_supported"); 099 p.add("display_values_supported"); 100 p.add("claim_types_supported"); 101 p.add("claims_supported"); 102 p.add("claims_locales_supported"); 103 p.add("ui_locales_supported"); 104 p.add("service_documentation"); 105 p.add("op_policy_uri"); 106 p.add("op_tos_uri"); 107 p.add("claims_parameter_supported"); 108 p.add("request_parameter_supported"); 109 p.add("request_uri_parameter_supported"); 110 p.add("require_request_uri_registration"); 111 p.add("introspection_endpoint"); 112 p.add("revocation_endpoint"); 113 p.add("backchannel_logout_supported"); 114 p.add("backchannel_logout_session_supported"); 115 p.add("frontchannel_logout_supported"); 116 p.add("frontchannel_logout_session_supported"); 117 REGISTERED_PARAMETER_NAMES = Collections.unmodifiableSet(p); 118 } 119 120 121 /** 122 * The issuer. 123 */ 124 private final Issuer issuer; 125 126 127 /** 128 * The authorisation endpoint. 129 */ 130 private URI authzEndpoint; 131 132 133 /** 134 * The token endpoint. 135 */ 136 private URI tokenEndpoint; 137 138 139 /** 140 * The UserInfo endpoint. 141 */ 142 private URI userInfoEndpoint; 143 144 145 /** 146 * The registration endpoint. 147 */ 148 private URI regEndpoint; 149 150 151 /** 152 * The token introspection endpoint. 153 */ 154 private URI introspectionEndpoint; 155 156 157 /** 158 * The token revocation endpoint. 159 */ 160 private URI revocationEndpoint; 161 162 163 /** 164 * The cross-origin check session iframe. 165 */ 166 private URI checkSessionIframe; 167 168 169 /** 170 * The logout endpoint. 171 */ 172 private URI endSessionEndpoint; 173 174 175 /** 176 * The JWK set URI. 177 */ 178 private final URI jwkSetURI; 179 180 181 /** 182 * The supported scope values. 183 */ 184 private Scope scope; 185 186 187 /** 188 * The supported response types. 189 */ 190 private List<ResponseType> rts; 191 192 193 /** 194 * The supported response modes. 195 */ 196 private List<ResponseMode> rms; 197 198 199 /** 200 * The supported grant types. 201 */ 202 private List<GrantType> gts; 203 204 205 /** 206 * The supported code challenge methods for PKCE. 207 */ 208 private List<CodeChallengeMethod> codeChallengeMethods; 209 210 211 /** 212 * The supported ACRs. 213 */ 214 private List<ACR> acrValues; 215 216 217 /** 218 * The supported subject types. 219 */ 220 private final List<SubjectType> subjectTypes; 221 222 223 /** 224 * The supported token endpoint authentication methods. 225 */ 226 private List<ClientAuthenticationMethod> tokenEndpointAuthMethods; 227 228 229 /** 230 * The supported JWS algorithms for the {@code private_key_jwt} and 231 * {@code client_secret_jwt} token endpoint authentication methods. 232 */ 233 private List<JWSAlgorithm> tokenEndpointJWSAlgs; 234 235 236 /** 237 * The supported JWS algorithms for OpenID Connect request objects. 238 */ 239 private List<JWSAlgorithm> requestObjectJWSAlgs; 240 241 242 /** 243 * The supported JWE algorithms for OpenID Connect request objects. 244 */ 245 private List<JWEAlgorithm> requestObjectJWEAlgs; 246 247 248 /** 249 * The supported encryption methods for OpenID Connect request objects. 250 */ 251 private List<EncryptionMethod> requestObjectJWEEncs; 252 253 254 /** 255 * The supported ID token JWS algorithms. 256 */ 257 private List<JWSAlgorithm> idTokenJWSAlgs; 258 259 260 /** 261 * The supported ID token JWE algorithms. 262 */ 263 private List<JWEAlgorithm> idTokenJWEAlgs; 264 265 266 /** 267 * The supported ID token encryption methods. 268 */ 269 private List<EncryptionMethod> idTokenJWEEncs; 270 271 272 /** 273 * The supported UserInfo JWS algorithms. 274 */ 275 private List<JWSAlgorithm> userInfoJWSAlgs; 276 277 278 /** 279 * The supported UserInfo JWE algorithms. 280 */ 281 private List<JWEAlgorithm> userInfoJWEAlgs; 282 283 284 /** 285 * The supported UserInfo encryption methods. 286 */ 287 private List<EncryptionMethod> userInfoJWEEncs; 288 289 290 /** 291 * The supported displays. 292 */ 293 private List<Display> displays; 294 295 296 /** 297 * The supported claim types. 298 */ 299 private List<ClaimType> claimTypes; 300 301 302 /** 303 * The supported claims names. 304 */ 305 private List<String> claims; 306 307 308 /** 309 * The supported claims locales. 310 */ 311 private List<LangTag> claimsLocales; 312 313 314 /** 315 * The supported UI locales. 316 */ 317 private List<LangTag> uiLocales; 318 319 320 /** 321 * The service documentation URI. 322 */ 323 private URI serviceDocsURI; 324 325 326 /** 327 * The provider's policy regarding relying party use of data. 328 */ 329 private URI policyURI; 330 331 332 /** 333 * The provider's terms of service. 334 */ 335 private URI tosURI; 336 337 338 /** 339 * If {@code true} the {@code claims} parameter is supported, else not. 340 */ 341 private boolean claimsParamSupported = false; 342 343 344 /** 345 * If {@code true} the {@code request} parameter is supported, else 346 * not. 347 */ 348 private boolean requestParamSupported = false; 349 350 351 /** 352 * If {@code true} the {@code request_uri} parameter is supported, else 353 * not. 354 */ 355 private boolean requestURIParamSupported = true; 356 357 358 /** 359 * If {@code true} the {@code request_uri} parameters must be 360 * pre-registered with the provider, else not. 361 */ 362 private boolean requireRequestURIReg = false; 363 364 365 /** 366 * If {@code true} the {@code frontchannel_logout_supported} parameter 367 * is set, else not. 368 */ 369 private boolean frontChannelLogoutSupported = false; 370 371 372 /** 373 * If {@code true} the {@code frontchannel_logout_session_supported} 374 * parameter is set, else not. 375 */ 376 private boolean frontChannelLogoutSessionSupported = false; 377 378 379 /** 380 * If {@code true} the {@code backchannel_logout_supported} parameter 381 * is set, else not. 382 */ 383 private boolean backChannelLogoutSupported = false; 384 385 386 /** 387 * If {@code true} the {@code backchannel_logout_session_supported} 388 * parameter is set, else not. 389 */ 390 private boolean backChannelLogoutSessionSupported = false; 391 392 393 /** 394 * Custom (not-registered) parameters. 395 */ 396 private final JSONObject customParameters = new JSONObject(); 397 398 399 /** 400 * Creates a new OpenID Connect provider metadata instance. 401 * 402 * @param issuer The issuer identifier. Must be an URI using the 403 * https scheme with no query or fragment 404 * component. Must not be {@code null}. 405 * @param subjectTypes The supported subject types. At least one must 406 * be specified. Must not be {@code null}. 407 */ 408 public OIDCProviderMetadata(final Issuer issuer, 409 final List<SubjectType> subjectTypes, 410 final URI jwkSetURI) { 411 412 URI url; 413 414 try { 415 url = new URI(issuer.getValue()); 416 417 } catch (URISyntaxException e) { 418 419 throw new IllegalArgumentException("The issuer identifier must be a URI: " + e.getMessage(), e); 420 } 421 422 if (url.getRawQuery() != null) 423 throw new IllegalArgumentException("The issuer URI must be without a query component"); 424 425 if (url.getRawFragment() != null) 426 throw new IllegalArgumentException("The issuer URI must be without a fragment component "); 427 428 this.issuer = issuer; 429 430 431 if (subjectTypes.size() < 1) 432 throw new IllegalArgumentException("At least one supported subject type must be specified"); 433 434 this.subjectTypes = subjectTypes; 435 436 if (jwkSetURI == null) 437 throw new IllegalArgumentException("The public JWK set URI must not be null"); 438 439 this.jwkSetURI = jwkSetURI; 440 } 441 442 443 /** 444 * Gets the registered OpenID Connect provider metadata parameter 445 * names. 446 * 447 * @return The registered OpenID Connect provider metadata parameter 448 * names, as an unmodifiable set. 449 */ 450 public static Set<String> getRegisteredParameterNames() { 451 452 return REGISTERED_PARAMETER_NAMES; 453 } 454 455 456 /** 457 * Gets the issuer identifier. Corresponds to the {@code issuer} 458 * metadata field. 459 * 460 * @return The issuer identifier. 461 */ 462 public Issuer getIssuer() { 463 464 return issuer; 465 } 466 467 468 /** 469 * Gets the authorisation endpoint URI. Corresponds the 470 * {@code authorization_endpoint} metadata field. 471 * 472 * @return The authorisation endpoint URI, {@code null} if not 473 * specified. 474 */ 475 public URI getAuthorizationEndpointURI() { 476 477 return authzEndpoint; 478 } 479 480 481 /** 482 * Sets the authorisation endpoint URI. Corresponds the 483 * {@code authorization_endpoint} metadata field. 484 * 485 * @param authzEndpoint The authorisation endpoint URI, {@code null} if 486 * not specified. 487 */ 488 public void setAuthorizationEndpointURI(final URI authzEndpoint) { 489 490 this.authzEndpoint = authzEndpoint; 491 } 492 493 494 /** 495 * Gets the token endpoint URI. Corresponds the {@code token_endpoint} 496 * metadata field. 497 * 498 * @return The token endpoint URI, {@code null} if not specified. 499 */ 500 public URI getTokenEndpointURI() { 501 502 return tokenEndpoint; 503 } 504 505 506 /** 507 * Sts the token endpoint URI. Corresponds the {@code token_endpoint} 508 * metadata field. 509 * 510 * @param tokenEndpoint The token endpoint URI, {@code null} if not 511 * specified. 512 */ 513 public void setTokenEndpointURI(final URI tokenEndpoint) { 514 515 this.tokenEndpoint = tokenEndpoint; 516 } 517 518 519 /** 520 * Gets the UserInfo endpoint URI. Corresponds the 521 * {@code userinfo_endpoint} metadata field. 522 * 523 * @return The UserInfo endpoint URI, {@code null} if not specified. 524 */ 525 public URI getUserInfoEndpointURI() { 526 527 return userInfoEndpoint; 528 } 529 530 531 /** 532 * Sets the UserInfo endpoint URI. Corresponds the 533 * {@code userinfo_endpoint} metadata field. 534 * 535 * @param userInfoEndpoint The UserInfo endpoint URI, {@code null} if 536 * not specified. 537 */ 538 public void setUserInfoEndpointURI(final URI userInfoEndpoint) { 539 540 this.userInfoEndpoint = userInfoEndpoint; 541 } 542 543 544 /** 545 * Gets the client registration endpoint URI. Corresponds to the 546 * {@code registration_endpoint} metadata field. 547 * 548 * @return The client registration endpoint URI, {@code null} if not 549 * specified. 550 */ 551 public URI getRegistrationEndpointURI() { 552 553 return regEndpoint; 554 } 555 556 557 /** 558 * Sets the client registration endpoint URI. Corresponds to the 559 * {@code registration_endpoint} metadata field. 560 * 561 * @param regEndpoint The client registration endpoint URI, 562 * {@code null} if not specified. 563 */ 564 public void setRegistrationEndpointURI(final URI regEndpoint) { 565 566 this.regEndpoint = regEndpoint; 567 } 568 569 570 /** 571 * Gets the token introspection endpoint URI. Corresponds to the 572 * {@code introspection_endpoint} metadata field. 573 * 574 * @return The token introspection endpoint URI, {@code null} if not 575 * specified. 576 */ 577 public URI getIntrospectionEndpointURI() { 578 579 return introspectionEndpoint; 580 } 581 582 583 /** 584 * Sets the token introspection endpoint URI. Corresponds to the 585 * {@code introspection_endpoint} metadata field. 586 * 587 * @param introspectionEndpoint The token introspection endpoint URI, 588 * {@code null} if not specified. 589 */ 590 public void setIntrospectionEndpointURI(final URI introspectionEndpoint) { 591 592 this.introspectionEndpoint = introspectionEndpoint; 593 } 594 595 596 /** 597 * Gets the token revocation endpoint URI. Corresponds to the 598 * {@code revocation_endpoint} metadata field. 599 * 600 * @return The token revocation endpoint URI, {@code null} if not 601 * specified. 602 */ 603 public URI getRevocationEndpointURI() { 604 605 return revocationEndpoint; 606 } 607 608 609 /** 610 * Sets the token revocation endpoint URI. Corresponds to the 611 * {@code revocation_endpoint} metadata field. 612 * 613 * @param revocationEndpoint The token revocation endpoint URI, 614 * {@code null} if not specified. 615 */ 616 public void setRevocationEndpointURI(final URI revocationEndpoint) { 617 618 this.revocationEndpoint = revocationEndpoint; 619 } 620 621 622 /** 623 * Gets the cross-origin check session iframe URI. Corresponds to the 624 * {@code check_session_iframe} metadata field. 625 * 626 * @return The check session iframe URI, {@code null} if not specified. 627 */ 628 public URI getCheckSessionIframeURI() { 629 630 return checkSessionIframe; 631 } 632 633 634 /** 635 * Sets the cross-origin check session iframe URI. Corresponds to the 636 * {@code check_session_iframe} metadata field. 637 * 638 * @param checkSessionIframe The check session iframe URI, {@code null} 639 * if not specified. 640 */ 641 public void setCheckSessionIframeURI(final URI checkSessionIframe) { 642 643 this.checkSessionIframe = checkSessionIframe; 644 } 645 646 647 /** 648 * Gets the logout endpoint URI. Corresponds to the 649 * {@code end_session_endpoint} metadata field. 650 * 651 * @return The logoout endpoint URI, {@code null} if not specified. 652 */ 653 public URI getEndSessionEndpointURI() { 654 655 return endSessionEndpoint; 656 } 657 658 659 /** 660 * Sets the logout endpoint URI. Corresponds to the 661 * {@code end_session_endpoint} metadata field. 662 * 663 * @param endSessionEndpoint The logoout endpoint URI, {@code null} if 664 * not specified. 665 */ 666 public void setEndSessionEndpointURI(final URI endSessionEndpoint) { 667 668 this.endSessionEndpoint = endSessionEndpoint; 669 } 670 671 672 /** 673 * Gets the JSON Web Key (JWK) set URI. Corresponds to the 674 * {@code jwks_uri} metadata field. 675 * 676 * @return The JWK set URI. 677 */ 678 public URI getJWKSetURI() { 679 680 return jwkSetURI; 681 } 682 683 684 /** 685 * Gets the supported scope values. Corresponds to the 686 * {@code scopes_supported} metadata field. 687 * 688 * @return The supported scope values, {@code null} if not specified. 689 */ 690 public Scope getScopes() { 691 692 return scope; 693 } 694 695 696 /** 697 * Sets the supported scope values. Corresponds to the 698 * {@code scopes_supported} metadata field. 699 * 700 * @param scope The supported scope values, {@code null} if not 701 * specified. 702 */ 703 public void setScopes(final Scope scope) { 704 705 this.scope = scope; 706 } 707 708 709 /** 710 * Gets the supported response type values. Corresponds to the 711 * {@code response_types_supported} metadata field. 712 * 713 * @return The supported response type values, {@code null} if not 714 * specified. 715 */ 716 public List<ResponseType> getResponseTypes() { 717 718 return rts; 719 } 720 721 722 /** 723 * Sets the supported response type values. Corresponds to the 724 * {@code response_types_supported} metadata field. 725 * 726 * @param rts The supported response type values, {@code null} if not 727 * specified. 728 */ 729 public void setResponseTypes(final List<ResponseType> rts) { 730 731 this.rts = rts; 732 } 733 734 735 /** 736 * Gets the supported response mode values. Corresponds to the 737 * {@code response_modes_supported}. 738 * 739 * @return The supported response mode values, {@code null} if not 740 * specified. 741 */ 742 public List<ResponseMode> getResponseModes() { 743 744 return rms; 745 } 746 747 748 /** 749 * Sets the supported response mode values. Corresponds to the 750 * {@code response_modes_supported}. 751 * 752 * @param rms The supported response mode values, {@code null} if not 753 * specified. 754 */ 755 public void setResponseModes(final List<ResponseMode> rms) { 756 757 this.rms = rms; 758 } 759 760 761 /** 762 * Gets the supported OAuth 2.0 grant types. Corresponds to the 763 * {@code grant_types_supported} metadata field. 764 * 765 * @return The supported grant types, {@code null} if not specified. 766 */ 767 public List<GrantType> getGrantTypes() { 768 769 return gts; 770 } 771 772 773 /** 774 * Sets the supported OAuth 2.0 grant types. Corresponds to the 775 * {@code grant_types_supported} metadata field. 776 * 777 * @param gts The supported grant types, {@code null} if not specified. 778 */ 779 public void setGrantTypes(final List<GrantType> gts) { 780 781 this.gts = gts; 782 } 783 784 785 /** 786 * Gets the supported authorisation code challenge methods for PKCE. 787 * Corresponds to the {@code code_challenge_methods_supported} metadata 788 * field. 789 * 790 * @return The supported code challenge methods, {@code null} if not 791 * specified. 792 */ 793 public List<CodeChallengeMethod> getCodeChallengeMethods() { 794 795 return codeChallengeMethods; 796 } 797 798 799 /** 800 * Gets the supported authorisation code challenge methods for PKCE. 801 * Corresponds to the {@code code_challenge_methods_supported} metadata 802 * field. 803 * 804 * @param codeChallengeMethods The supported code challenge methods, 805 * {@code null} if not specified. 806 */ 807 public void setCodeChallengeMethods(final List<CodeChallengeMethod> codeChallengeMethods) { 808 809 this.codeChallengeMethods = codeChallengeMethods; 810 } 811 812 /** 813 * Gets the supported Authentication Context Class References (ACRs). 814 * Corresponds to the {@code acr_values_supported} metadata field. 815 * 816 * @return The supported ACRs, {@code null} if not specified. 817 */ 818 public List<ACR> getACRs() { 819 820 return acrValues; 821 } 822 823 824 /** 825 * Sets the supported Authentication Context Class References (ACRs). 826 * Corresponds to the {@code acr_values_supported} metadata field. 827 * 828 * @param acrValues The supported ACRs, {@code null} if not specified. 829 */ 830 public void setACRs(final List<ACR> acrValues) { 831 832 this.acrValues = acrValues; 833 } 834 835 836 /** 837 * Gets the supported subject types. Corresponds to the 838 * {@code subject_types_supported} metadata field. 839 * 840 * @return The supported subject types. 841 */ 842 public List<SubjectType> getSubjectTypes() { 843 844 return subjectTypes; 845 } 846 847 848 /** 849 * Gets the supported token endpoint authentication methods. 850 * Corresponds to the {@code token_endpoint_auth_methods_supported} 851 * metadata field. 852 * 853 * @return The supported token endpoint authentication methods, 854 * {@code null} if not specified. 855 */ 856 public List<ClientAuthenticationMethod> getTokenEndpointAuthMethods() { 857 858 return tokenEndpointAuthMethods; 859 } 860 861 862 /** 863 * Sets the supported token endpoint authentication methods. 864 * Corresponds to the {@code token_endpoint_auth_methods_supported} 865 * metadata field. 866 * 867 * @param tokenEndpointAuthMethods The supported token endpoint 868 * authentication methods, {@code null} 869 * if not specified. 870 */ 871 public void setTokenEndpointAuthMethods(final List<ClientAuthenticationMethod> tokenEndpointAuthMethods) { 872 873 this.tokenEndpointAuthMethods = tokenEndpointAuthMethods; 874 } 875 876 877 /** 878 * Gets the supported JWS algorithms for the {@code private_key_jwt} 879 * and {@code client_secret_jwt} token endpoint authentication methods. 880 * Corresponds to the 881 * {@code token_endpoint_auth_signing_alg_values_supported} metadata 882 * field. 883 * 884 * @return The supported JWS algorithms, {@code null} if not specified. 885 */ 886 public List<JWSAlgorithm> getTokenEndpointJWSAlgs() { 887 888 return tokenEndpointJWSAlgs; 889 } 890 891 892 /** 893 * Sets the supported JWS algorithms for the {@code private_key_jwt} 894 * and {@code client_secret_jwt} token endpoint authentication methods. 895 * Corresponds to the 896 * {@code token_endpoint_auth_signing_alg_values_supported} metadata 897 * field. 898 * 899 * @param tokenEndpointJWSAlgs The supported JWS algorithms, 900 * {@code null} if not specified. Must not 901 * contain the {@code none} algorithm. 902 */ 903 public void setTokenEndpointJWSAlgs(final List<JWSAlgorithm> tokenEndpointJWSAlgs) { 904 905 if (tokenEndpointJWSAlgs != null && tokenEndpointJWSAlgs.contains(Algorithm.NONE)) 906 throw new IllegalArgumentException("The none algorithm is not accepted"); 907 908 this.tokenEndpointJWSAlgs = tokenEndpointJWSAlgs; 909 } 910 911 912 /** 913 * Gets the supported JWS algorithms for OpenID Connect request 914 * objects. Corresponds to the 915 * {@code request_object_signing_alg_values_supported} metadata field. 916 * 917 * @return The supported JWS algorithms, {@code null} if not specified. 918 */ 919 public List<JWSAlgorithm> getRequestObjectJWSAlgs() { 920 921 return requestObjectJWSAlgs; 922 } 923 924 925 /** 926 * Sets the supported JWS algorithms for OpenID Connect request 927 * objects. Corresponds to the 928 * {@code request_object_signing_alg_values_supported} metadata field. 929 * 930 * @param requestObjectJWSAlgs The supported JWS algorithms, 931 * {@code null} if not specified. 932 */ 933 public void setRequestObjectJWSAlgs(final List<JWSAlgorithm> requestObjectJWSAlgs) { 934 935 this.requestObjectJWSAlgs = requestObjectJWSAlgs; 936 } 937 938 939 /** 940 * Gets the supported JWE algorithms for OpenID Connect request 941 * objects. Corresponds to the 942 * {@code request_object_encryption_alg_values_supported} metadata 943 * field. 944 * 945 * @return The supported JWE algorithms, {@code null} if not specified. 946 */ 947 public List<JWEAlgorithm> getRequestObjectJWEAlgs() { 948 949 return requestObjectJWEAlgs; 950 } 951 952 953 /** 954 * Sets the supported JWE algorithms for OpenID Connect request 955 * objects. Corresponds to the 956 * {@code request_object_encryption_alg_values_supported} metadata 957 * field. 958 * 959 * @param requestObjectJWEAlgs The supported JWE algorithms, 960 * {@code null} if not specified. 961 */ 962 public void setRequestObjectJWEAlgs(final List<JWEAlgorithm> requestObjectJWEAlgs) { 963 964 this.requestObjectJWEAlgs = requestObjectJWEAlgs; 965 } 966 967 968 /** 969 * Gets the supported encryption methods for OpenID Connect request 970 * objects. Corresponds to the 971 * {@code request_object_encryption_enc_values_supported} metadata 972 * field. 973 * 974 * @return The supported encryption methods, {@code null} if not 975 * specified. 976 */ 977 public List<EncryptionMethod> getRequestObjectJWEEncs() { 978 979 return requestObjectJWEEncs; 980 } 981 982 983 /** 984 * Sets the supported encryption methods for OpenID Connect request 985 * objects. Corresponds to the 986 * {@code request_object_encryption_enc_values_supported} metadata 987 * field. 988 * 989 * @param requestObjectJWEEncs The supported encryption methods, 990 * {@code null} if not specified. 991 */ 992 public void setRequestObjectJWEEncs(final List<EncryptionMethod> requestObjectJWEEncs) { 993 994 this.requestObjectJWEEncs = requestObjectJWEEncs; 995 } 996 997 998 /** 999 * Gets the supported JWS algorithms for ID tokens. Corresponds to the 1000 * {@code id_token_signing_alg_values_supported} metadata field. 1001 * 1002 * @return The supported JWS algorithms, {@code null} if not specified. 1003 */ 1004 public List<JWSAlgorithm> getIDTokenJWSAlgs() { 1005 1006 return idTokenJWSAlgs; 1007 } 1008 1009 1010 /** 1011 * Sets the supported JWS algorithms for ID tokens. Corresponds to the 1012 * {@code id_token_signing_alg_values_supported} metadata field. 1013 * 1014 * @param idTokenJWSAlgs The supported JWS algorithms, {@code null} if 1015 * not specified. 1016 */ 1017 public void setIDTokenJWSAlgs(final List<JWSAlgorithm> idTokenJWSAlgs) { 1018 1019 this.idTokenJWSAlgs = idTokenJWSAlgs; 1020 } 1021 1022 1023 /** 1024 * Gets the supported JWE algorithms for ID tokens. Corresponds to the 1025 * {@code id_token_encryption_alg_values_supported} metadata field. 1026 * 1027 * @return The supported JWE algorithms, {@code null} if not specified. 1028 */ 1029 public List<JWEAlgorithm> getIDTokenJWEAlgs() { 1030 1031 return idTokenJWEAlgs; 1032 } 1033 1034 1035 /** 1036 * Sets the supported JWE algorithms for ID tokens. Corresponds to the 1037 * {@code id_token_encryption_alg_values_supported} metadata field. 1038 * 1039 * @param idTokenJWEAlgs The supported JWE algorithms, {@code null} if 1040 * not specified. 1041 */ 1042 public void setIDTokenJWEAlgs(final List<JWEAlgorithm> idTokenJWEAlgs) { 1043 1044 this.idTokenJWEAlgs = idTokenJWEAlgs; 1045 } 1046 1047 1048 /** 1049 * Gets the supported encryption methods for ID tokens. Corresponds to 1050 * the {@code id_token_encryption_enc_values_supported} metadata field. 1051 * 1052 * @return The supported encryption methods, {@code null} if not 1053 * specified. 1054 */ 1055 public List<EncryptionMethod> getIDTokenJWEEncs() { 1056 1057 return idTokenJWEEncs; 1058 } 1059 1060 1061 /** 1062 * Sets the supported encryption methods for ID tokens. Corresponds to 1063 * the {@code id_token_encryption_enc_values_supported} metadata field. 1064 * 1065 * @param idTokenJWEEncs The supported encryption methods, {@code null} 1066 * if not specified. 1067 */ 1068 public void setIDTokenJWEEncs(final List<EncryptionMethod> idTokenJWEEncs) { 1069 1070 this.idTokenJWEEncs = idTokenJWEEncs; 1071 } 1072 1073 1074 /** 1075 * Gets the supported JWS algorithms for UserInfo JWTs. Corresponds to 1076 * the {@code userinfo_signing_alg_values_supported} metadata field. 1077 * 1078 * @return The supported JWS algorithms, {@code null} if not specified. 1079 */ 1080 public List<JWSAlgorithm> getUserInfoJWSAlgs() { 1081 1082 return userInfoJWSAlgs; 1083 } 1084 1085 1086 /** 1087 * Sets the supported JWS algorithms for UserInfo JWTs. Corresponds to 1088 * the {@code userinfo_signing_alg_values_supported} metadata field. 1089 * 1090 * @param userInfoJWSAlgs The supported JWS algorithms, {@code null} if 1091 * not specified. 1092 */ 1093 public void setUserInfoJWSAlgs(final List<JWSAlgorithm> userInfoJWSAlgs) { 1094 1095 this.userInfoJWSAlgs = userInfoJWSAlgs; 1096 } 1097 1098 1099 /** 1100 * Gets the supported JWE algorithms for UserInfo JWTs. Corresponds to 1101 * the {@code userinfo_encryption_alg_values_supported} metadata field. 1102 * 1103 * @return The supported JWE algorithms, {@code null} if not specified. 1104 */ 1105 public List<JWEAlgorithm> getUserInfoJWEAlgs() { 1106 1107 return userInfoJWEAlgs; 1108 } 1109 1110 1111 /** 1112 * Sets the supported JWE algorithms for UserInfo JWTs. Corresponds to 1113 * the {@code userinfo_encryption_alg_values_supported} metadata field. 1114 * 1115 * @param userInfoJWEAlgs The supported JWE algorithms, {@code null} if 1116 * not specified. 1117 */ 1118 public void setUserInfoJWEAlgs(final List<JWEAlgorithm> userInfoJWEAlgs) { 1119 1120 this.userInfoJWEAlgs = userInfoJWEAlgs; 1121 } 1122 1123 1124 /** 1125 * Gets the supported encryption methods for UserInfo JWTs. Corresponds 1126 * to the {@code userinfo_encryption_enc_values_supported} metadata 1127 * field. 1128 * 1129 * @return The supported encryption methods, {@code null} if not 1130 * specified. 1131 */ 1132 public List<EncryptionMethod> getUserInfoJWEEncs() { 1133 1134 return userInfoJWEEncs; 1135 } 1136 1137 1138 /** 1139 * Sets the supported encryption methods for UserInfo JWTs. Corresponds 1140 * to the {@code userinfo_encryption_enc_values_supported} metadata 1141 * field. 1142 * 1143 * @param userInfoJWEEncs The supported encryption methods, 1144 * {@code null} if not specified. 1145 */ 1146 public void setUserInfoJWEEncs(final List<EncryptionMethod> userInfoJWEEncs) { 1147 1148 this.userInfoJWEEncs = userInfoJWEEncs; 1149 } 1150 1151 1152 /** 1153 * Gets the supported displays. Corresponds to the 1154 * {@code display_values_supported} metadata field. 1155 * 1156 * @return The supported displays, {@code null} if not specified. 1157 */ 1158 public List<Display> getDisplays() { 1159 1160 return displays; 1161 } 1162 1163 1164 /** 1165 * Sets the supported displays. Corresponds to the 1166 * {@code display_values_supported} metadata field. 1167 * 1168 * @param displays The supported displays, {@code null} if not 1169 * specified. 1170 */ 1171 public void setDisplays(final List<Display> displays) { 1172 1173 this.displays = displays; 1174 } 1175 1176 1177 /** 1178 * Gets the supported claim types. Corresponds to the 1179 * {@code claim_types_supported} metadata field. 1180 * 1181 * @return The supported claim types, {@code null} if not specified. 1182 */ 1183 public List<ClaimType> getClaimTypes() { 1184 1185 return claimTypes; 1186 } 1187 1188 1189 /** 1190 * Sets the supported claim types. Corresponds to the 1191 * {@code claim_types_supported} metadata field. 1192 * 1193 * @param claimTypes The supported claim types, {@code null} if not 1194 * specified. 1195 */ 1196 public void setClaimTypes(final List<ClaimType> claimTypes) { 1197 1198 this.claimTypes = claimTypes; 1199 } 1200 1201 1202 /** 1203 * Gets the supported claims names. Corresponds to the 1204 * {@code claims_supported} metadata field. 1205 * 1206 * @return The supported claims names, {@code null} if not specified. 1207 */ 1208 public List<String> getClaims() { 1209 1210 return claims; 1211 } 1212 1213 1214 /** 1215 * Sets the supported claims names. Corresponds to the 1216 * {@code claims_supported} metadata field. 1217 * 1218 * @param claims The supported claims names, {@code null} if not 1219 * specified. 1220 */ 1221 public void setClaims(final List<String> claims) { 1222 1223 this.claims = claims; 1224 } 1225 1226 1227 /** 1228 * Gets the supported claims locales. Corresponds to the 1229 * {@code claims_locales_supported} metadata field. 1230 * 1231 * @return The supported claims locales, {@code null} if not specified. 1232 */ 1233 public List<LangTag> getClaimsLocales() { 1234 1235 return claimsLocales; 1236 } 1237 1238 1239 /** 1240 * Sets the supported claims locales. Corresponds to the 1241 * {@code claims_locales_supported} metadata field. 1242 * 1243 * @param claimsLocales The supported claims locales, {@code null} if 1244 * not specified. 1245 */ 1246 public void setClaimLocales(final List<LangTag> claimsLocales) { 1247 1248 this.claimsLocales = claimsLocales; 1249 } 1250 1251 1252 /** 1253 * Gets the supported UI locales. Corresponds to the 1254 * {@code ui_locales_supported} metadata field. 1255 * 1256 * @return The supported UI locales, {@code null} if not specified. 1257 */ 1258 public List<LangTag> getUILocales() { 1259 1260 return uiLocales; 1261 } 1262 1263 1264 /** 1265 * Sets the supported UI locales. Corresponds to the 1266 * {@code ui_locales_supported} metadata field. 1267 * 1268 * @param uiLocales The supported UI locales, {@code null} if not 1269 * specified. 1270 */ 1271 public void setUILocales(final List<LangTag> uiLocales) { 1272 1273 this.uiLocales = uiLocales; 1274 } 1275 1276 1277 /** 1278 * Gets the service documentation URI. Corresponds to the 1279 * {@code service_documentation} metadata field. 1280 * 1281 * @return The service documentation URI, {@code null} if not 1282 * specified. 1283 */ 1284 public URI getServiceDocsURI() { 1285 1286 return serviceDocsURI; 1287 } 1288 1289 1290 /** 1291 * Sets the service documentation URI. Corresponds to the 1292 * {@code service_documentation} metadata field. 1293 * 1294 * @param serviceDocsURI The service documentation URI, {@code null} if 1295 * not specified. 1296 */ 1297 public void setServiceDocsURI(final URI serviceDocsURI) { 1298 1299 this.serviceDocsURI = serviceDocsURI; 1300 } 1301 1302 1303 /** 1304 * Gets the provider's policy regarding relying party use of data. 1305 * Corresponds to the {@code op_policy_uri} metadata field. 1306 * 1307 * @return The policy URI, {@code null} if not specified. 1308 */ 1309 public URI getPolicyURI() { 1310 1311 return policyURI; 1312 } 1313 1314 1315 /** 1316 * Sets the provider's policy regarding relying party use of data. 1317 * Corresponds to the {@code op_policy_uri} metadata field. 1318 * 1319 * @param policyURI The policy URI, {@code null} if not specified. 1320 */ 1321 public void setPolicyURI(final URI policyURI) { 1322 1323 this.policyURI = policyURI; 1324 } 1325 1326 1327 /** 1328 * Gets the provider's terms of service. Corresponds to the 1329 * {@code op_tos_uri} metadata field. 1330 * 1331 * @return The terms of service URI, {@code null} if not specified. 1332 */ 1333 public URI getTermsOfServiceURI() { 1334 1335 return tosURI; 1336 } 1337 1338 1339 /** 1340 * Sets the provider's terms of service. Corresponds to the 1341 * {@code op_tos_uri} metadata field. 1342 * 1343 * @param tosURI The terms of service URI, {@code null} if not 1344 * specified. 1345 */ 1346 public void setTermsOfServiceURI(final URI tosURI) { 1347 1348 this.tosURI = tosURI; 1349 } 1350 1351 1352 /** 1353 * Gets the support for the {@code claims} authorisation request 1354 * parameter. Corresponds to the {@code claims_parameter_supported} 1355 * metadata field. 1356 * 1357 * @return {@code true} if the {@code claim} parameter is supported, 1358 * else {@code false}. 1359 */ 1360 public boolean supportsClaimsParam() { 1361 1362 return claimsParamSupported; 1363 } 1364 1365 1366 /** 1367 * Sets the support for the {@code claims} authorisation request 1368 * parameter. Corresponds to the {@code claims_parameter_supported} 1369 * metadata field. 1370 * 1371 * @param claimsParamSupported {@code true} if the {@code claim} 1372 * parameter is supported, else 1373 * {@code false}. 1374 */ 1375 public void setSupportsClaimsParams(final boolean claimsParamSupported) { 1376 1377 this.claimsParamSupported = claimsParamSupported; 1378 } 1379 1380 1381 /** 1382 * Gets the support for the {@code request} authorisation request 1383 * parameter. Corresponds to the {@code request_parameter_supported} 1384 * metadata field. 1385 * 1386 * @return {@code true} if the {@code reqeust} parameter is supported, 1387 * else {@code false}. 1388 */ 1389 public boolean supportsRequestParam() { 1390 1391 return requestParamSupported; 1392 } 1393 1394 1395 /** 1396 * Sets the support for the {@code request} authorisation request 1397 * parameter. Corresponds to the {@code request_parameter_supported} 1398 * metadata field. 1399 * 1400 * @param requestParamSupported {@code true} if the {@code reqeust} 1401 * parameter is supported, else 1402 * {@code false}. 1403 */ 1404 public void setSupportsRequestParam(final boolean requestParamSupported) { 1405 1406 this.requestParamSupported = requestParamSupported; 1407 } 1408 1409 1410 /** 1411 * Gets the support for the {@code request_uri} authorisation request 1412 * parameter. Corresponds the {@code request_uri_parameter_supported} 1413 * metadata field. 1414 * 1415 * @return {@code true} if the {@code request_uri} parameter is 1416 * supported, else {@code false}. 1417 */ 1418 public boolean supportsRequestURIParam() { 1419 1420 return requestURIParamSupported; 1421 } 1422 1423 1424 /** 1425 * Sets the support for the {@code request_uri} authorisation request 1426 * parameter. Corresponds the {@code request_uri_parameter_supported} 1427 * metadata field. 1428 * 1429 * @param requestURIParamSupported {@code true} if the 1430 * {@code request_uri} parameter is 1431 * supported, else {@code false}. 1432 */ 1433 public void setSupportsRequestURIParam(final boolean requestURIParamSupported) { 1434 1435 this.requestURIParamSupported = requestURIParamSupported; 1436 } 1437 1438 1439 /** 1440 * Gets the requirement for the {@code request_uri} parameter 1441 * pre-registration. Corresponds to the 1442 * {@code require_request_uri_registration} metadata field. 1443 * 1444 * @return {@code true} if the {@code request_uri} parameter values 1445 * must be pre-registered, else {@code false}. 1446 */ 1447 public boolean requiresRequestURIRegistration() { 1448 1449 return requireRequestURIReg; 1450 } 1451 1452 1453 /** 1454 * Sets the requirement for the {@code request_uri} parameter 1455 * pre-registration. Corresponds to the 1456 * {@code require_request_uri_registration} metadata field. 1457 * 1458 * @param requireRequestURIReg {@code true} if the {@code request_uri} 1459 * parameter values must be pre-registered, 1460 * else {@code false}. 1461 */ 1462 public void setRequiresRequestURIRegistration(final boolean requireRequestURIReg) { 1463 1464 this.requireRequestURIReg = requireRequestURIReg; 1465 } 1466 1467 1468 /** 1469 * Gets the support for front-channel logout. Corresponds to the 1470 * {@code frontchannel_logout_supported} metadata field. 1471 * 1472 * @return {@code true} if front-channel logout is supported, else 1473 * {@code false}. 1474 */ 1475 public boolean supportsFrontChannelLogout() { 1476 1477 return frontChannelLogoutSupported; 1478 } 1479 1480 1481 /** 1482 * Sets the support for front-channel logout. Corresponds to the 1483 * {@code frontchannel_logout_supported} metadata field. 1484 * 1485 * @param frontChannelLogoutSupported {@code true} if front-channel 1486 * logout is supported, else 1487 * {@code false}. 1488 */ 1489 public void setSupportsFrontChannelLogout(final boolean frontChannelLogoutSupported) { 1490 1491 this.frontChannelLogoutSupported = frontChannelLogoutSupported; 1492 } 1493 1494 1495 /** 1496 * Gets the support for front-channel logout with a session ID. 1497 * Corresponds to the {@code frontchannel_logout_session_supported} 1498 * metadata field. 1499 * 1500 * @return {@code true} if front-channel logout with a session ID is 1501 * supported, else {@code false}. 1502 */ 1503 public boolean supportsFrontChannelLogoutSession() { 1504 1505 return frontChannelLogoutSessionSupported; 1506 } 1507 1508 1509 /** 1510 * Sets the support for front-channel logout with a session ID. 1511 * Corresponds to the {@code frontchannel_logout_session_supported} 1512 * metadata field. 1513 * 1514 * @param frontChannelLogoutSessionSupported {@code true} if 1515 * front-channel logout with 1516 * a session ID is supported, 1517 * else {@code false}. 1518 */ 1519 public void setSupportsFrontChannelLogoutSession(final boolean frontChannelLogoutSessionSupported) { 1520 1521 this.frontChannelLogoutSessionSupported = frontChannelLogoutSessionSupported; 1522 } 1523 1524 1525 /** 1526 * Gets the support for back-channel logout. Corresponds to the 1527 * {@code backchannel_logout_supported} metadata field. 1528 * 1529 * @return {@code true} if back-channel logout is supported, else 1530 * {@code false}. 1531 */ 1532 public boolean supportsBackChannelLogout() { 1533 1534 return backChannelLogoutSupported; 1535 } 1536 1537 1538 /** 1539 * Sets the support for back-channel logout. Corresponds to the 1540 * {@code backchannel_logout_supported} metadata field. 1541 * 1542 * @param backChannelLogoutSupported {@code true} if back-channel 1543 * logout is supported, else 1544 * {@code false}. 1545 */ 1546 public void setSupportsBackChannelLogout(final boolean backChannelLogoutSupported) { 1547 1548 this.backChannelLogoutSupported = backChannelLogoutSupported; 1549 } 1550 1551 1552 /** 1553 * Gets the support for back-channel logout with a session ID. 1554 * Corresponds to the {@code backchannel_logout_session_supported} 1555 * metadata field. 1556 * 1557 * @return {@code true} if back-channel logout with a session ID is 1558 * supported, else {@code false}. 1559 */ 1560 public boolean supportsBackChannelLogoutSession() { 1561 1562 return backChannelLogoutSessionSupported; 1563 } 1564 1565 1566 /** 1567 * Sets the support for back-channel logout with a session ID. 1568 * Corresponds to the {@code backchannel_logout_session_supported} 1569 * metadata field. 1570 * 1571 * @param backChannelLogoutSessionSupported {@code true} if 1572 * back-channel logout with a 1573 * session ID is supported, 1574 * else {@code false}. 1575 */ 1576 public void setSupportsBackChannelLogoutSession(final boolean backChannelLogoutSessionSupported) { 1577 1578 this.backChannelLogoutSessionSupported = backChannelLogoutSessionSupported; 1579 } 1580 1581 1582 /** 1583 * Gets the specified custom (not registered) parameter. 1584 * 1585 * @param name The parameter name. Must not be {@code null}. 1586 * 1587 * @return The parameter value, {@code null} if not specified. 1588 */ 1589 public Object getCustomParameter(final String name) { 1590 1591 return customParameters.get(name); 1592 } 1593 1594 1595 /** 1596 * Gets the specified custom (not registered) URI parameter. 1597 * 1598 * @param name The parameter name. Must not be {@code null}. 1599 * 1600 * @return The parameter URI value, {@code null} if not specified. 1601 */ 1602 public URI getCustomURIParameter(final String name) { 1603 1604 try { 1605 return JSONObjectUtils.getURI(customParameters, name); 1606 } catch (ParseException e) { 1607 return null; 1608 } 1609 } 1610 1611 1612 /** 1613 * Sets the specified custom (not registered) parameter. 1614 * 1615 * @param name The parameter name. Must not be {@code null}. 1616 * @param value The parameter value, {@code null} if not specified. 1617 */ 1618 public void setCustomParameter(final String name, final Object value) { 1619 1620 if (REGISTERED_PARAMETER_NAMES.contains(name)) { 1621 throw new IllegalArgumentException("The " + name + " parameter is registered"); 1622 } 1623 1624 customParameters.put(name, value); 1625 } 1626 1627 1628 /** 1629 * Gets the custom (not registered) parameters. 1630 * 1631 * @return The custom parameters, empty JSON object if none. 1632 */ 1633 public JSONObject getCustomParameters() { 1634 1635 return customParameters; 1636 } 1637 1638 1639 /** 1640 * Applies the OpenID Connect provider metadata defaults where no 1641 * values have been specified. 1642 * 1643 * <ul> 1644 * <li>The response modes default to {@code ["query", "fragment"]}. 1645 * <li>The grant types default to {@code ["authorization_code", 1646 * "implicit"]}. 1647 * <li>The token endpoint authentication methods default to 1648 * {@code ["client_secret_basic"]}. 1649 * <li>The claim types default to {@code ["normal]}. 1650 * </ul> 1651 */ 1652 public void applyDefaults() { 1653 1654 if (rms == null) { 1655 rms = new ArrayList<>(2); 1656 rms.add(ResponseMode.QUERY); 1657 rms.add(ResponseMode.FRAGMENT); 1658 } 1659 1660 if (gts == null) { 1661 gts = new ArrayList<>(2); 1662 gts.add(GrantType.AUTHORIZATION_CODE); 1663 gts.add(GrantType.IMPLICIT); 1664 } 1665 1666 if (claimTypes == null) { 1667 claimTypes = new ArrayList<>(1); 1668 claimTypes.add(ClaimType.NORMAL); 1669 } 1670 } 1671 1672 1673 /** 1674 * Returns the JSON object representation of this OpenID Connect 1675 * provider metadata. 1676 * 1677 * @return The JSON object representation. 1678 */ 1679 public JSONObject toJSONObject() { 1680 1681 JSONObject o = new OrderedJSONObject(); 1682 1683 // Mandatory fields 1684 1685 o.put("issuer", issuer.getValue()); 1686 1687 List<String> stringList = new ArrayList<>(subjectTypes.size()); 1688 1689 for (SubjectType st: subjectTypes) 1690 stringList.add(st.toString()); 1691 1692 o.put("subject_types_supported", stringList); 1693 1694 o.put("jwks_uri", jwkSetURI.toString()); 1695 1696 // Optional fields 1697 1698 if (authzEndpoint != null) 1699 o.put("authorization_endpoint", authzEndpoint.toString()); 1700 1701 if (tokenEndpoint != null) 1702 o.put("token_endpoint", tokenEndpoint.toString()); 1703 1704 if (userInfoEndpoint != null) 1705 o.put("userinfo_endpoint", userInfoEndpoint.toString()); 1706 1707 if (regEndpoint != null) 1708 o.put("registration_endpoint", regEndpoint.toString()); 1709 1710 if (introspectionEndpoint != null) 1711 o.put("introspection_endpoint", introspectionEndpoint.toString()); 1712 1713 if (revocationEndpoint != null) 1714 o.put("revocation_endpoint", revocationEndpoint.toString()); 1715 1716 if (checkSessionIframe != null) 1717 o.put("check_session_iframe", checkSessionIframe.toString()); 1718 1719 if (endSessionEndpoint != null) 1720 o.put("end_session_endpoint", endSessionEndpoint.toString()); 1721 1722 if (scope != null) 1723 o.put("scopes_supported", scope.toStringList()); 1724 1725 if (rts != null) { 1726 1727 stringList = new ArrayList<>(rts.size()); 1728 1729 for (ResponseType rt: rts) 1730 stringList.add(rt.toString()); 1731 1732 o.put("response_types_supported", stringList); 1733 } 1734 1735 if (rms != null) { 1736 1737 stringList = new ArrayList<>(rms.size()); 1738 1739 for (ResponseMode rm: rms) 1740 stringList.add(rm.getValue()); 1741 1742 o.put("response_modes_supported", stringList); 1743 } 1744 1745 if (gts != null) { 1746 1747 stringList = new ArrayList<>(gts.size()); 1748 1749 for (GrantType gt: gts) 1750 stringList.add(gt.toString()); 1751 1752 o.put("grant_types_supported", stringList); 1753 } 1754 1755 if (codeChallengeMethods != null) { 1756 1757 stringList = new ArrayList<>(codeChallengeMethods.size()); 1758 1759 for (CodeChallengeMethod m: codeChallengeMethods) 1760 stringList.add(m.getValue()); 1761 1762 o.put("code_challenge_methods_supported", stringList); 1763 } 1764 1765 if (acrValues != null) { 1766 1767 stringList = new ArrayList<>(acrValues.size()); 1768 1769 for (ACR acr: acrValues) 1770 stringList.add(acr.getValue()); 1771 1772 o.put("acr_values_supported", stringList); 1773 } 1774 1775 1776 if (tokenEndpointAuthMethods != null) { 1777 1778 stringList = new ArrayList<>(tokenEndpointAuthMethods.size()); 1779 1780 for (ClientAuthenticationMethod m: tokenEndpointAuthMethods) 1781 stringList.add(m.getValue()); 1782 1783 o.put("token_endpoint_auth_methods_supported", stringList); 1784 } 1785 1786 if (tokenEndpointJWSAlgs != null) { 1787 1788 stringList = new ArrayList<>(tokenEndpointJWSAlgs.size()); 1789 1790 for (JWSAlgorithm alg: tokenEndpointJWSAlgs) 1791 stringList.add(alg.getName()); 1792 1793 o.put("token_endpoint_auth_signing_alg_values_supported", stringList); 1794 } 1795 1796 if (requestObjectJWSAlgs != null) { 1797 1798 stringList = new ArrayList<>(requestObjectJWSAlgs.size()); 1799 1800 for (JWSAlgorithm alg: requestObjectJWSAlgs) 1801 stringList.add(alg.getName()); 1802 1803 o.put("request_object_signing_alg_values_supported", stringList); 1804 } 1805 1806 if (requestObjectJWEAlgs != null) { 1807 1808 stringList = new ArrayList<>(requestObjectJWEAlgs.size()); 1809 1810 for (JWEAlgorithm alg: requestObjectJWEAlgs) 1811 stringList.add(alg.getName()); 1812 1813 o.put("request_object_encryption_alg_values_supported", stringList); 1814 } 1815 1816 if (requestObjectJWEEncs != null) { 1817 1818 stringList = new ArrayList<>(requestObjectJWEEncs.size()); 1819 1820 for (EncryptionMethod m: requestObjectJWEEncs) 1821 stringList.add(m.getName()); 1822 1823 o.put("request_object_encryption_enc_values_supported", stringList); 1824 } 1825 1826 if (idTokenJWSAlgs != null) { 1827 1828 stringList = new ArrayList<>(idTokenJWSAlgs.size()); 1829 1830 for (JWSAlgorithm alg: idTokenJWSAlgs) 1831 stringList.add(alg.getName()); 1832 1833 o.put("id_token_signing_alg_values_supported", stringList); 1834 } 1835 1836 if (idTokenJWEAlgs != null) { 1837 1838 stringList = new ArrayList<>(idTokenJWEAlgs.size()); 1839 1840 for (JWEAlgorithm alg: idTokenJWEAlgs) 1841 stringList.add(alg.getName()); 1842 1843 o.put("id_token_encryption_alg_values_supported", stringList); 1844 } 1845 1846 if (idTokenJWEEncs != null) { 1847 1848 stringList = new ArrayList<>(idTokenJWEEncs.size()); 1849 1850 for (EncryptionMethod m: idTokenJWEEncs) 1851 stringList.add(m.getName()); 1852 1853 o.put("id_token_encryption_enc_values_supported", stringList); 1854 } 1855 1856 if (userInfoJWSAlgs != null) { 1857 1858 stringList = new ArrayList<>(userInfoJWSAlgs.size()); 1859 1860 for (JWSAlgorithm alg: userInfoJWSAlgs) 1861 stringList.add(alg.getName()); 1862 1863 o.put("userinfo_signing_alg_values_supported", stringList); 1864 } 1865 1866 if (userInfoJWEAlgs != null) { 1867 1868 stringList = new ArrayList<>(userInfoJWEAlgs.size()); 1869 1870 for (JWEAlgorithm alg: userInfoJWEAlgs) 1871 stringList.add(alg.getName()); 1872 1873 o.put("userinfo_encryption_alg_values_supported", stringList); 1874 } 1875 1876 if (userInfoJWEEncs != null) { 1877 1878 stringList = new ArrayList<>(userInfoJWEEncs.size()); 1879 1880 for (EncryptionMethod m: userInfoJWEEncs) 1881 stringList.add(m.getName()); 1882 1883 o.put("userinfo_encryption_enc_values_supported", stringList); 1884 } 1885 1886 if (displays != null) { 1887 1888 stringList = new ArrayList<>(displays.size()); 1889 1890 for (Display d: displays) 1891 stringList.add(d.toString()); 1892 1893 o.put("display_values_supported", stringList); 1894 } 1895 1896 if (claimTypes != null) { 1897 1898 stringList = new ArrayList<>(claimTypes.size()); 1899 1900 for (ClaimType ct: claimTypes) 1901 stringList.add(ct.toString()); 1902 1903 o.put("claim_types_supported", stringList); 1904 } 1905 1906 if (claims != null) 1907 o.put("claims_supported", claims); 1908 1909 if (claimsLocales != null) { 1910 1911 stringList = new ArrayList<>(claimsLocales.size()); 1912 1913 for (LangTag l: claimsLocales) 1914 stringList.add(l.toString()); 1915 1916 o.put("claims_locales_supported", stringList); 1917 } 1918 1919 if (uiLocales != null) { 1920 1921 stringList = new ArrayList<>(uiLocales.size()); 1922 1923 for (LangTag l: uiLocales) 1924 stringList.add(l.toString()); 1925 1926 o.put("ui_locales_supported", stringList); 1927 } 1928 1929 if (serviceDocsURI != null) 1930 o.put("service_documentation", serviceDocsURI.toString()); 1931 1932 if (policyURI != null) 1933 o.put("op_policy_uri", policyURI.toString()); 1934 1935 if (tosURI != null) 1936 o.put("op_tos_uri", tosURI.toString()); 1937 1938 o.put("claims_parameter_supported", claimsParamSupported); 1939 1940 o.put("request_parameter_supported", requestParamSupported); 1941 1942 o.put("request_uri_parameter_supported", requestURIParamSupported); 1943 1944 o.put("require_request_uri_registration", requireRequestURIReg); 1945 1946 // optional front and back-channel logout 1947 o.put("frontchannel_logout_supported", frontChannelLogoutSupported); 1948 1949 if (frontChannelLogoutSupported) { 1950 o.put("frontchannel_logout_session_supported", frontChannelLogoutSessionSupported); 1951 } 1952 1953 o.put("backchannel_logout_supported", backChannelLogoutSupported); 1954 1955 if (backChannelLogoutSupported) { 1956 o.put("backchannel_logout_session_supported", backChannelLogoutSessionSupported); 1957 } 1958 1959 // Append any custom (not registered) parameters 1960 o.putAll(customParameters); 1961 1962 return o; 1963 } 1964 1965 1966 1967 /** 1968 * Parses an OpenID Connect provider metadata from the specified JSON 1969 * object. 1970 * 1971 * @param jsonObject The JSON object to parse. Must not be 1972 * {@code null}. 1973 * 1974 * @return The OpenID Connect provider metadata. 1975 * 1976 * @throws ParseException If the JSON object couldn't be parsed to an 1977 * OpenID Connect provider metadata. 1978 */ 1979 public static OIDCProviderMetadata parse(final JSONObject jsonObject) 1980 throws ParseException { 1981 1982 // Parse issuer and subject_types_supported first 1983 1984 List<SubjectType> subjectTypes = new ArrayList<>(); 1985 1986 for (String v: JSONObjectUtils.getStringArray(jsonObject, "subject_types_supported")) { 1987 subjectTypes.add(SubjectType.parse(v)); 1988 } 1989 1990 Issuer issuer = new Issuer(JSONObjectUtils.getURI(jsonObject, "issuer").toString()); 1991 1992 URI jwkSetURI = JSONObjectUtils.getURI(jsonObject, "jwks_uri"); 1993 1994 1995 OIDCProviderMetadata op = new OIDCProviderMetadata(issuer, Collections.unmodifiableList(subjectTypes), jwkSetURI); 1996 1997 // Endpoints 1998 if (jsonObject.get("authorization_endpoint") != null) 1999 op.authzEndpoint = JSONObjectUtils.getURI(jsonObject, "authorization_endpoint"); 2000 2001 if (jsonObject.get("token_endpoint") != null) 2002 op.tokenEndpoint = JSONObjectUtils.getURI(jsonObject, "token_endpoint"); 2003 2004 if (jsonObject.get("userinfo_endpoint") != null) 2005 op.userInfoEndpoint = JSONObjectUtils.getURI(jsonObject, "userinfo_endpoint"); 2006 2007 if (jsonObject.get("registration_endpoint") != null) 2008 op.regEndpoint = JSONObjectUtils.getURI(jsonObject, "registration_endpoint"); 2009 2010 if (jsonObject.get("introspection_endpoint") != null) 2011 op.introspectionEndpoint = JSONObjectUtils.getURI(jsonObject, "introspection_endpoint"); 2012 2013 if (jsonObject.get("revocation_endpoint") != null) 2014 op.revocationEndpoint = JSONObjectUtils.getURI(jsonObject, "revocation_endpoint"); 2015 2016 if (jsonObject.get("check_session_iframe") != null) 2017 op.checkSessionIframe = JSONObjectUtils.getURI(jsonObject, "check_session_iframe"); 2018 2019 if (jsonObject.get("end_session_endpoint") != null) 2020 op.endSessionEndpoint = JSONObjectUtils.getURI(jsonObject, "end_session_endpoint"); 2021 2022 // OIDC capabilities 2023 if (jsonObject.get("scopes_supported") != null) { 2024 2025 op.scope = new Scope(); 2026 2027 for (String v: JSONObjectUtils.getStringArray(jsonObject, "scopes_supported")) { 2028 2029 if (v != null) 2030 op.scope.add(new Scope.Value(v)); 2031 } 2032 } 2033 2034 if (jsonObject.get("response_types_supported") != null) { 2035 2036 op.rts = new ArrayList<>(); 2037 2038 for (String v: JSONObjectUtils.getStringArray(jsonObject, "response_types_supported")) { 2039 2040 if (v != null) 2041 op.rts.add(ResponseType.parse(v)); 2042 } 2043 } 2044 2045 if (jsonObject.get("response_modes_supported") != null) { 2046 2047 op.rms = new ArrayList<>(); 2048 2049 for (String v: JSONObjectUtils.getStringArray(jsonObject, "response_modes_supported")) { 2050 2051 if (v != null) 2052 op.rms.add(new ResponseMode(v)); 2053 } 2054 } 2055 2056 if (jsonObject.get("grant_types_supported") != null) { 2057 2058 op.gts = new ArrayList<>(); 2059 2060 for (String v: JSONObjectUtils.getStringArray(jsonObject, "grant_types_supported")) { 2061 2062 if (v != null) 2063 op.gts.add(GrantType.parse(v)); 2064 } 2065 } 2066 2067 if (jsonObject.get("code_challenge_methods_supported") != null) { 2068 2069 op.codeChallengeMethods = new ArrayList<>(); 2070 2071 for (String v: JSONObjectUtils.getStringArray(jsonObject, "code_challenge_methods_supported")) { 2072 2073 if (v != null) 2074 op.codeChallengeMethods.add(CodeChallengeMethod.parse(v)); 2075 } 2076 } 2077 2078 if (jsonObject.get("acr_values_supported") != null) { 2079 2080 op.acrValues = new ArrayList<>(); 2081 2082 for (String v: JSONObjectUtils.getStringArray(jsonObject, "acr_values_supported")) { 2083 2084 if (v != null) 2085 op.acrValues.add(new ACR(v)); 2086 } 2087 } 2088 2089 if (jsonObject.get("token_endpoint_auth_methods_supported") != null) { 2090 2091 op.tokenEndpointAuthMethods = new ArrayList<>(); 2092 2093 for (String v: JSONObjectUtils.getStringArray(jsonObject, "token_endpoint_auth_methods_supported")) { 2094 2095 if (v != null) 2096 op.tokenEndpointAuthMethods.add(ClientAuthenticationMethod.parse(v)); 2097 } 2098 } 2099 2100 if (jsonObject.get("token_endpoint_auth_signing_alg_values_supported") != null) { 2101 2102 op.tokenEndpointJWSAlgs = new ArrayList<>(); 2103 2104 for (String v: JSONObjectUtils.getStringArray(jsonObject, "token_endpoint_auth_signing_alg_values_supported")) { 2105 2106 if (v != null && v.equals(Algorithm.NONE.getName())) 2107 throw new ParseException("The none algorithm is not accepted"); 2108 2109 if (v != null) 2110 op.tokenEndpointJWSAlgs.add(JWSAlgorithm.parse(v)); 2111 } 2112 } 2113 2114 2115 // OpenID Connect request object 2116 2117 if (jsonObject.get("request_object_signing_alg_values_supported") != null) { 2118 2119 op.requestObjectJWSAlgs = new ArrayList<>(); 2120 2121 for (String v: JSONObjectUtils.getStringArray(jsonObject, "request_object_signing_alg_values_supported")) { 2122 2123 if (v != null) 2124 op.requestObjectJWSAlgs.add(JWSAlgorithm.parse(v)); 2125 } 2126 } 2127 2128 2129 if (jsonObject.get("request_object_encryption_alg_values_supported") != null) { 2130 2131 op.requestObjectJWEAlgs = new ArrayList<>(); 2132 2133 for (String v: JSONObjectUtils.getStringArray(jsonObject, "request_object_encryption_alg_values_supported")) { 2134 2135 if (v != null) 2136 op.requestObjectJWEAlgs.add(JWEAlgorithm.parse(v)); 2137 } 2138 } 2139 2140 2141 if (jsonObject.get("request_object_encryption_enc_values_supported") != null) { 2142 2143 op.requestObjectJWEEncs = new ArrayList<>(); 2144 2145 for (String v: JSONObjectUtils.getStringArray(jsonObject, "request_object_encryption_enc_values_supported")) { 2146 2147 if (v != null) 2148 op.requestObjectJWEEncs.add(EncryptionMethod.parse(v)); 2149 } 2150 } 2151 2152 2153 // ID token 2154 2155 if (jsonObject.get("id_token_signing_alg_values_supported") != null) { 2156 2157 op.idTokenJWSAlgs = new ArrayList<>(); 2158 2159 for (String v: JSONObjectUtils.getStringArray(jsonObject, "id_token_signing_alg_values_supported")) { 2160 2161 if (v != null) 2162 op.idTokenJWSAlgs.add(JWSAlgorithm.parse(v)); 2163 } 2164 } 2165 2166 2167 if (jsonObject.get("id_token_encryption_alg_values_supported") != null) { 2168 2169 op.idTokenJWEAlgs = new ArrayList<>(); 2170 2171 for (String v: JSONObjectUtils.getStringArray(jsonObject, "id_token_encryption_alg_values_supported")) { 2172 2173 if (v != null) 2174 op.idTokenJWEAlgs.add(JWEAlgorithm.parse(v)); 2175 } 2176 } 2177 2178 2179 if (jsonObject.get("id_token_encryption_enc_values_supported") != null) { 2180 2181 op.idTokenJWEEncs = new ArrayList<>(); 2182 2183 for (String v: JSONObjectUtils.getStringArray(jsonObject, "id_token_encryption_enc_values_supported")) { 2184 2185 if (v != null) 2186 op.idTokenJWEEncs.add(EncryptionMethod.parse(v)); 2187 } 2188 } 2189 2190 // UserInfo 2191 2192 if (jsonObject.get("userinfo_signing_alg_values_supported") != null) { 2193 2194 op.userInfoJWSAlgs = new ArrayList<>(); 2195 2196 for (String v: JSONObjectUtils.getStringArray(jsonObject, "userinfo_signing_alg_values_supported")) { 2197 2198 if (v != null) 2199 op.userInfoJWSAlgs.add(JWSAlgorithm.parse(v)); 2200 } 2201 } 2202 2203 2204 if (jsonObject.get("userinfo_encryption_alg_values_supported") != null) { 2205 2206 op.userInfoJWEAlgs = new ArrayList<>(); 2207 2208 for (String v: JSONObjectUtils.getStringArray(jsonObject, "userinfo_encryption_alg_values_supported")) { 2209 2210 if (v != null) 2211 op.userInfoJWEAlgs.add(JWEAlgorithm.parse(v)); 2212 } 2213 } 2214 2215 2216 if (jsonObject.get("userinfo_encryption_enc_values_supported") != null) { 2217 2218 op.userInfoJWEEncs = new ArrayList<>(); 2219 2220 for (String v: JSONObjectUtils.getStringArray(jsonObject, "userinfo_encryption_enc_values_supported")) { 2221 2222 if (v != null) 2223 op.userInfoJWEEncs.add(EncryptionMethod.parse(v)); 2224 } 2225 } 2226 2227 2228 // Misc 2229 2230 if (jsonObject.get("display_values_supported") != null) { 2231 2232 op.displays = new ArrayList<>(); 2233 2234 for (String v: JSONObjectUtils.getStringArray(jsonObject, "display_values_supported")) { 2235 2236 if (v != null) 2237 op.displays.add(Display.parse(v)); 2238 } 2239 } 2240 2241 if (jsonObject.get("claim_types_supported") != null) { 2242 2243 op.claimTypes = new ArrayList<>(); 2244 2245 for (String v: JSONObjectUtils.getStringArray(jsonObject, "claim_types_supported")) { 2246 2247 if (v != null) 2248 op.claimTypes.add(ClaimType.parse(v)); 2249 } 2250 } 2251 2252 2253 if (jsonObject.get("claims_supported") != null) { 2254 2255 op.claims = new ArrayList<>(); 2256 2257 for (String v: JSONObjectUtils.getStringArray(jsonObject, "claims_supported")) { 2258 2259 if (v != null) 2260 op.claims.add(v); 2261 } 2262 } 2263 2264 if (jsonObject.get("claims_locales_supported") != null) { 2265 2266 op.claimsLocales = new ArrayList<>(); 2267 2268 for (String v : JSONObjectUtils.getStringArray(jsonObject, "claims_locales_supported")) { 2269 2270 if (v != null) { 2271 2272 try { 2273 op.claimsLocales.add(LangTag.parse(v)); 2274 2275 } catch (LangTagException e) { 2276 2277 throw new ParseException("Invalid claims_locales_supported field: " + e.getMessage(), e); 2278 } 2279 } 2280 } 2281 } 2282 2283 if (jsonObject.get("ui_locales_supported") != null) { 2284 2285 op.uiLocales = new ArrayList<>(); 2286 2287 for (String v : JSONObjectUtils.getStringArray(jsonObject, "ui_locales_supported")) { 2288 2289 if (v != null) { 2290 2291 try { 2292 op.uiLocales.add(LangTag.parse(v)); 2293 2294 } catch (LangTagException e) { 2295 2296 throw new ParseException("Invalid ui_locales_supported field: " + e.getMessage(), e); 2297 } 2298 } 2299 } 2300 } 2301 2302 2303 if (jsonObject.get("service_documentation") != null) 2304 op.serviceDocsURI = JSONObjectUtils.getURI(jsonObject, "service_documentation"); 2305 2306 if (jsonObject.get("op_policy_uri") != null) 2307 op.policyURI = JSONObjectUtils.getURI(jsonObject, "op_policy_uri"); 2308 2309 if (jsonObject.get("op_tos_uri") != null) 2310 op.tosURI = JSONObjectUtils.getURI(jsonObject, "op_tos_uri"); 2311 2312 if (jsonObject.get("claims_parameter_supported") != null) 2313 op.claimsParamSupported = JSONObjectUtils.getBoolean(jsonObject, "claims_parameter_supported"); 2314 2315 if (jsonObject.get("request_parameter_supported") != null) 2316 op.requestParamSupported = JSONObjectUtils.getBoolean(jsonObject, "request_parameter_supported"); 2317 2318 if (jsonObject.get("request_uri_parameter_supported") != null) 2319 op.requestURIParamSupported = JSONObjectUtils.getBoolean(jsonObject, "request_uri_parameter_supported"); 2320 2321 if (jsonObject.get("require_request_uri_registration") != null) 2322 op.requireRequestURIReg = JSONObjectUtils.getBoolean(jsonObject, "require_request_uri_registration"); 2323 2324 // optional front and back-channel logout 2325 if (jsonObject.get("frontchannel_logout_supported") != null) 2326 op.frontChannelLogoutSupported = JSONObjectUtils.getBoolean(jsonObject, "frontchannel_logout_supported"); 2327 2328 if (op.frontChannelLogoutSupported && jsonObject.get("frontchannel_logout_session_supported") != null) 2329 op.frontChannelLogoutSessionSupported = JSONObjectUtils.getBoolean(jsonObject, "frontchannel_logout_session_supported"); 2330 2331 if (jsonObject.get("backchannel_logout_supported") != null) 2332 op.backChannelLogoutSupported = JSONObjectUtils.getBoolean(jsonObject, "backchannel_logout_supported"); 2333 2334 if (op.frontChannelLogoutSupported && jsonObject.get("backchannel_logout_session_supported") != null) 2335 op.backChannelLogoutSessionSupported = JSONObjectUtils.getBoolean(jsonObject, "backchannel_logout_session_supported"); 2336 2337 // Parse custom (not registered) parameters 2338 JSONObject customParams = new JSONObject(jsonObject); 2339 customParams.keySet().removeAll(REGISTERED_PARAMETER_NAMES); 2340 for (Map.Entry<String,Object> customEntry: customParams.entrySet()) { 2341 op.setCustomParameter(customEntry.getKey(), customEntry.getValue()); 2342 } 2343 2344 return op; 2345 } 2346 2347 2348 /** 2349 * Parses an OpenID Connect provider metadata from the specified JSON 2350 * object string. 2351 * 2352 * @param s The JSON object sting to parse. Must not be {@code null}. 2353 * 2354 * @return The OpenID Connect provider metadata. 2355 * 2356 * @throws ParseException If the JSON object string couldn't be parsed 2357 * to an OpenID Connect provider metadata. 2358 */ 2359 public static OIDCProviderMetadata parse(final String s) 2360 throws ParseException { 2361 2362 return parse(JSONObjectUtils.parse(s)); 2363 } 2364 2365 2366 /** 2367 * Resolves OpenID Provider metadata from the specified issuer 2368 * identifier. The metadata is downloaded by HTTP GET from 2369 * {@code [issuer-url]/.well-known/openid-configuration}. 2370 * 2371 * @param issuer The OpenID Provider issuer identifier. Must represent 2372 * a valid HTTPS or HTTP URL. Must not be {@code null}. 2373 * 2374 * @return The OpenID Provider metadata. 2375 * 2376 * @throws GeneralException If the issuer identifier or the downloaded 2377 * metadata are invalid. 2378 * @throws IOException On a HTTP exception. 2379 */ 2380 public static OIDCProviderMetadata resolve(final Issuer issuer) 2381 throws GeneralException, IOException { 2382 2383 return resolve(issuer, 0, 0); 2384 } 2385 2386 2387 /** 2388 * Resolves OpenID Provider metadata from the specified issuer 2389 * identifier. The metadata is downloaded by HTTP GET from 2390 * {@code [issuer-url]/.well-known/openid-configuration}, using the 2391 * specified HTTP timeouts. 2392 * 2393 * @param issuer The OpenID Provider issuer identifier. Must 2394 * represent a valid HTTPS or HTTP URL. Must not 2395 * be {@code null}. 2396 * @param connectTimeout The HTTP connect timeout, in milliseconds. 2397 * Zero implies no timeout. Must not be negative. 2398 * @param readTimeout The HTTP response read timeout, in 2399 * milliseconds. Zero implies no timeout. Must 2400 * not be negative. 2401 * 2402 * @return The OpenID Provider metadata. 2403 * 2404 * @throws GeneralException If the issuer identifier or the downloaded 2405 * metadata are invalid. 2406 * @throws IOException On a HTTP exception. 2407 */ 2408 public static OIDCProviderMetadata resolve(final Issuer issuer, 2409 final int connectTimeout, 2410 final int readTimeout) 2411 throws GeneralException, IOException { 2412 2413 URL configURL; 2414 2415 try { 2416 URL issuerURL = new URL(issuer.getValue()); 2417 2418 // Validate but don't insist on HTTPS, see 2419 // http://openid.net/specs/openid-connect-core-1_0.html#Terminology 2420 if (issuerURL.getQuery() != null && ! issuerURL.getQuery().trim().isEmpty()) { 2421 throw new GeneralException("The issuer identifier must not contain a query component"); 2422 } 2423 2424 if (issuerURL.getPath() != null && issuerURL.getPath().endsWith("/")) { 2425 configURL = new URL(issuerURL + ".well-known/openid-configuration"); 2426 } else { 2427 configURL = new URL(issuerURL + "/.well-known/openid-configuration"); 2428 } 2429 2430 } catch (MalformedURLException e) { 2431 throw new GeneralException("The issuer identifier doesn't represent a valid URL: " + e.getMessage(), e); 2432 } 2433 2434 HTTPRequest httpRequest = new HTTPRequest(HTTPRequest.Method.GET, configURL); 2435 httpRequest.setConnectTimeout(connectTimeout); 2436 httpRequest.setReadTimeout(readTimeout); 2437 2438 HTTPResponse httpResponse = httpRequest.send(); 2439 2440 if (httpResponse.getStatusCode() != 200) { 2441 throw new IOException("Couldn't download OpenID Provider metadata from " + configURL + 2442 ": Status code " + httpResponse.getStatusCode()); 2443 } 2444 2445 JSONObject jsonObject = httpResponse.getContentAsJSONObject(); 2446 2447 return OIDCProviderMetadata.parse(jsonObject); 2448 } 2449}