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.URL; 025import java.util.*; 026 027import net.minidev.json.JSONObject; 028 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.GeneralException; 035import com.nimbusds.oauth2.sdk.ParseException; 036import com.nimbusds.oauth2.sdk.as.AuthorizationServerEndpointMetadata; 037import com.nimbusds.oauth2.sdk.as.AuthorizationServerMetadata; 038import com.nimbusds.oauth2.sdk.http.HTTPRequest; 039import com.nimbusds.oauth2.sdk.http.HTTPResponse; 040import com.nimbusds.oauth2.sdk.id.Identifier; 041import com.nimbusds.oauth2.sdk.id.Issuer; 042import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 043import com.nimbusds.openid.connect.sdk.Display; 044import com.nimbusds.openid.connect.sdk.SubjectType; 045import com.nimbusds.openid.connect.sdk.assurance.evidences.IDDocumentType; 046import com.nimbusds.openid.connect.sdk.assurance.evidences.IdentityEvidenceType; 047import com.nimbusds.openid.connect.sdk.assurance.IdentityTrustFramework; 048import com.nimbusds.openid.connect.sdk.assurance.evidences.IdentityVerificationMethod; 049import com.nimbusds.openid.connect.sdk.claims.ACR; 050import com.nimbusds.openid.connect.sdk.claims.ClaimType; 051 052 053/** 054 * OpenID Provider (OP) metadata. 055 * 056 * <p>Related specifications: 057 * 058 * <ul> 059 * <li>OpenID Connect Discovery 1.0, section 3. 060 * <li>OpenID Connect Session Management 1.0, section 2.1 (draft 28). 061 * <li>OpenID Connect Front-Channel Logout 1.0, section 3 (draft 02). 062 * <li>OpenID Connect Back-Channel Logout 1.0, section 2.1 (draft 04). 063 * <li>OpenID Connect for Identity Assurance 1.0 (draft 08). 064 * <li>OAuth 2.0 Authorization Server Metadata (RFC 8414) 065 * <li>OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound 066 * Access Tokens (draft-ietf-oauth-mtls-15) 067 * <li>Financial-grade API: JWT Secured Authorization Response Mode for 068 * OAuth 2.0 (JARM) 069 * </ul> 070 */ 071public class OIDCProviderMetadata extends AuthorizationServerMetadata { 072 073 074 /** 075 * The registered parameter names. 076 */ 077 private static final Set<String> REGISTERED_PARAMETER_NAMES; 078 079 080 static { 081 Set<String> p = new HashSet<>(AuthorizationServerMetadata.getRegisteredParameterNames()); 082 p.addAll(OIDCProviderEndpointMetadata.getRegisteredParameterNames()); 083 p.add("check_session_iframe"); 084 p.add("end_session_endpoint"); 085 p.add("acr_values_supported"); 086 p.add("subject_types_supported"); 087 p.add("id_token_signing_alg_values_supported"); 088 p.add("id_token_encryption_alg_values_supported"); 089 p.add("id_token_encryption_enc_values_supported"); 090 p.add("userinfo_signing_alg_values_supported"); 091 p.add("userinfo_encryption_alg_values_supported"); 092 p.add("userinfo_encryption_enc_values_supported"); 093 p.add("display_values_supported"); 094 p.add("claim_types_supported"); 095 p.add("claims_supported"); 096 p.add("claims_locales_supported"); 097 p.add("claims_parameter_supported"); 098 p.add("backchannel_logout_supported"); 099 p.add("backchannel_logout_session_supported"); 100 p.add("frontchannel_logout_supported"); 101 p.add("frontchannel_logout_session_supported"); 102 p.add("verified_claims_supported"); 103 p.add("trust_frameworks_supported"); 104 p.add("evidence_supported"); 105 p.add("id_documents_supported"); 106 p.add("id_documents_verification_methods_supported"); 107 p.add("claims_in_verified_claims_supported"); 108 REGISTERED_PARAMETER_NAMES = Collections.unmodifiableSet(p); 109 } 110 111 112 /** 113 * The UserInfo endpoint. 114 */ 115 private URI userInfoEndpoint; 116 117 118 /** 119 * The cross-origin check session iframe. 120 */ 121 private URI checkSessionIframe; 122 123 124 /** 125 * The logout endpoint. 126 */ 127 private URI endSessionEndpoint; 128 129 130 /** 131 * The supported ACRs. 132 */ 133 private List<ACR> acrValues; 134 135 136 /** 137 * The supported subject types. 138 */ 139 private final List<SubjectType> subjectTypes; 140 141 142 /** 143 * The supported ID token JWS algorithms. 144 */ 145 private List<JWSAlgorithm> idTokenJWSAlgs; 146 147 148 /** 149 * The supported ID token JWE algorithms. 150 */ 151 private List<JWEAlgorithm> idTokenJWEAlgs; 152 153 154 /** 155 * The supported ID token encryption methods. 156 */ 157 private List<EncryptionMethod> idTokenJWEEncs; 158 159 160 /** 161 * The supported UserInfo JWS algorithms. 162 */ 163 private List<JWSAlgorithm> userInfoJWSAlgs; 164 165 166 /** 167 * The supported UserInfo JWE algorithms. 168 */ 169 private List<JWEAlgorithm> userInfoJWEAlgs; 170 171 172 /** 173 * The supported UserInfo encryption methods. 174 */ 175 private List<EncryptionMethod> userInfoJWEEncs; 176 177 178 /** 179 * The supported displays. 180 */ 181 private List<Display> displays; 182 183 184 /** 185 * The supported claim types. 186 */ 187 private List<ClaimType> claimTypes; 188 189 190 /** 191 * The supported claims names. 192 */ 193 private List<String> claims; 194 195 196 /** 197 * The supported claims locales. 198 */ 199 private List<LangTag> claimsLocales; 200 201 202 /** 203 * If {@code true} the {@code claims} parameter is supported, else not. 204 */ 205 private boolean claimsParamSupported = false; 206 207 208 /** 209 * If {@code true} the {@code frontchannel_logout_supported} parameter 210 * is set, else not. 211 */ 212 private boolean frontChannelLogoutSupported = false; 213 214 215 /** 216 * If {@code true} the {@code frontchannel_logout_session_supported} 217 * parameter is set, else not. 218 */ 219 private boolean frontChannelLogoutSessionSupported = false; 220 221 222 /** 223 * If {@code true} the {@code backchannel_logout_supported} parameter 224 * is set, else not. 225 */ 226 private boolean backChannelLogoutSupported = false; 227 228 229 /** 230 * If {@code true} the {@code backchannel_logout_session_supported} 231 * parameter is set, else not. 232 */ 233 private boolean backChannelLogoutSessionSupported = false; 234 235 236 /** 237 * If {@code true} verified claims are supported. 238 */ 239 private boolean verifiedClaimsSupported = false; 240 241 242 /** 243 * The supported trust frameworks. 244 */ 245 private List<IdentityTrustFramework> trustFrameworks; 246 247 248 /** 249 * The supported identity evidence types. 250 */ 251 private List<IdentityEvidenceType> evidenceTypes; 252 253 254 /** 255 * The supported identity documents. 256 */ 257 private List<IDDocumentType> idDocuments; 258 259 260 /** 261 * The supported identity verification methods. 262 */ 263 private List<IdentityVerificationMethod> idVerificationMethods; 264 265 266 /** 267 * The supported verified claims. 268 */ 269 private List<String> verifiedClaims; 270 271 272 /** 273 * Creates a new OpenID Connect provider metadata instance. 274 * 275 * @param issuer The issuer identifier. Must be an URI using the 276 * https scheme with no query or fragment 277 * component. Must not be {@code null}. 278 * @param subjectTypes The supported subject types. At least one must 279 * be specified. Must not be {@code null}. 280 * @param jwkSetURI The JWK set URI. Must not be {@code null}. 281 */ 282 public OIDCProviderMetadata(final Issuer issuer, 283 final List<SubjectType> subjectTypes, 284 final URI jwkSetURI) { 285 286 super(issuer); 287 288 if (subjectTypes.size() < 1) 289 throw new IllegalArgumentException("At least one supported subject type must be specified"); 290 291 this.subjectTypes = subjectTypes; 292 293 if (jwkSetURI == null) 294 throw new IllegalArgumentException("The public JWK set URI must not be null"); 295 296 setJWKSetURI(jwkSetURI); 297 298 // Default OpenID Connect setting is supported 299 setSupportsRequestParam(true); 300 } 301 302 303 @Override 304 public void setMtlsEndpointAliases(AuthorizationServerEndpointMetadata mtlsEndpointAliases) { 305 306 if (mtlsEndpointAliases != null && !(mtlsEndpointAliases instanceof OIDCProviderEndpointMetadata)) { 307 // convert the provided endpoints to OIDC 308 super.setMtlsEndpointAliases(new OIDCProviderEndpointMetadata(mtlsEndpointAliases)); 309 } else { 310 super.setMtlsEndpointAliases(mtlsEndpointAliases); 311 } 312 } 313 314 @Override 315 public OIDCProviderEndpointMetadata getMtlsEndpointAliases() { 316 317 return (OIDCProviderEndpointMetadata) super.getMtlsEndpointAliases(); 318 } 319 320 321 /** 322 * Gets the registered OpenID Connect provider metadata parameter 323 * names. 324 * 325 * @return The registered OpenID Connect provider metadata parameter 326 * names, as an unmodifiable set. 327 */ 328 public static Set<String> getRegisteredParameterNames() { 329 330 return REGISTERED_PARAMETER_NAMES; 331 } 332 333 334 /** 335 * Gets the UserInfo endpoint URI. Corresponds the 336 * {@code userinfo_endpoint} metadata field. 337 * 338 * @return The UserInfo endpoint URI, {@code null} if not specified. 339 */ 340 public URI getUserInfoEndpointURI() { 341 342 return userInfoEndpoint; 343 } 344 345 346 /** 347 * Sets the UserInfo endpoint URI. Corresponds the 348 * {@code userinfo_endpoint} metadata field. 349 * 350 * @param userInfoEndpoint The UserInfo endpoint URI, {@code null} if 351 * not specified. 352 */ 353 public void setUserInfoEndpointURI(final URI userInfoEndpoint) { 354 355 this.userInfoEndpoint = userInfoEndpoint; 356 } 357 358 359 /** 360 * Gets the cross-origin check session iframe URI. Corresponds to the 361 * {@code check_session_iframe} metadata field. 362 * 363 * @return The check session iframe URI, {@code null} if not specified. 364 */ 365 public URI getCheckSessionIframeURI() { 366 367 return checkSessionIframe; 368 } 369 370 371 /** 372 * Sets the cross-origin check session iframe URI. Corresponds to the 373 * {@code check_session_iframe} metadata field. 374 * 375 * @param checkSessionIframe The check session iframe URI, {@code null} 376 * if not specified. 377 */ 378 public void setCheckSessionIframeURI(final URI checkSessionIframe) { 379 380 this.checkSessionIframe = checkSessionIframe; 381 } 382 383 384 /** 385 * Gets the logout endpoint URI. Corresponds to the 386 * {@code end_session_endpoint} metadata field. 387 * 388 * @return The logoout endpoint URI, {@code null} if not specified. 389 */ 390 public URI getEndSessionEndpointURI() { 391 392 return endSessionEndpoint; 393 } 394 395 396 /** 397 * Sets the logout endpoint URI. Corresponds to the 398 * {@code end_session_endpoint} metadata field. 399 * 400 * @param endSessionEndpoint The logoout endpoint URI, {@code null} if 401 * not specified. 402 */ 403 public void setEndSessionEndpointURI(final URI endSessionEndpoint) { 404 405 this.endSessionEndpoint = endSessionEndpoint; 406 } 407 408 /** 409 * Gets the supported Authentication Context Class References (ACRs). 410 * Corresponds to the {@code acr_values_supported} metadata field. 411 * 412 * @return The supported ACRs, {@code null} if not specified. 413 */ 414 public List<ACR> getACRs() { 415 416 return acrValues; 417 } 418 419 420 /** 421 * Sets the supported Authentication Context Class References (ACRs). 422 * Corresponds to the {@code acr_values_supported} metadata field. 423 * 424 * @param acrValues The supported ACRs, {@code null} if not specified. 425 */ 426 public void setACRs(final List<ACR> acrValues) { 427 428 this.acrValues = acrValues; 429 } 430 431 432 /** 433 * Gets the supported subject types. Corresponds to the 434 * {@code subject_types_supported} metadata field. 435 * 436 * @return The supported subject types. 437 */ 438 public List<SubjectType> getSubjectTypes() { 439 440 return subjectTypes; 441 } 442 443 444 /** 445 * Gets the supported JWS algorithms for ID tokens. Corresponds to the 446 * {@code id_token_signing_alg_values_supported} metadata field. 447 * 448 * @return The supported JWS algorithms, {@code null} if not specified. 449 */ 450 public List<JWSAlgorithm> getIDTokenJWSAlgs() { 451 452 return idTokenJWSAlgs; 453 } 454 455 456 /** 457 * Sets the supported JWS algorithms for ID tokens. Corresponds to the 458 * {@code id_token_signing_alg_values_supported} metadata field. 459 * 460 * @param idTokenJWSAlgs The supported JWS algorithms, {@code null} if 461 * not specified. 462 */ 463 public void setIDTokenJWSAlgs(final List<JWSAlgorithm> idTokenJWSAlgs) { 464 465 this.idTokenJWSAlgs = idTokenJWSAlgs; 466 } 467 468 469 /** 470 * Gets the supported JWE algorithms for ID tokens. Corresponds to the 471 * {@code id_token_encryption_alg_values_supported} metadata field. 472 * 473 * @return The supported JWE algorithms, {@code null} if not specified. 474 */ 475 public List<JWEAlgorithm> getIDTokenJWEAlgs() { 476 477 return idTokenJWEAlgs; 478 } 479 480 481 /** 482 * Sets the supported JWE algorithms for ID tokens. Corresponds to the 483 * {@code id_token_encryption_alg_values_supported} metadata field. 484 * 485 * @param idTokenJWEAlgs The supported JWE algorithms, {@code null} if 486 * not specified. 487 */ 488 public void setIDTokenJWEAlgs(final List<JWEAlgorithm> idTokenJWEAlgs) { 489 490 this.idTokenJWEAlgs = idTokenJWEAlgs; 491 } 492 493 494 /** 495 * Gets the supported encryption methods for ID tokens. Corresponds to 496 * the {@code id_token_encryption_enc_values_supported} metadata field. 497 * 498 * @return The supported encryption methods, {@code null} if not 499 * specified. 500 */ 501 public List<EncryptionMethod> getIDTokenJWEEncs() { 502 503 return idTokenJWEEncs; 504 } 505 506 507 /** 508 * Sets the supported encryption methods for ID tokens. Corresponds to 509 * the {@code id_token_encryption_enc_values_supported} metadata field. 510 * 511 * @param idTokenJWEEncs The supported encryption methods, {@code null} 512 * if not specified. 513 */ 514 public void setIDTokenJWEEncs(final List<EncryptionMethod> idTokenJWEEncs) { 515 516 this.idTokenJWEEncs = idTokenJWEEncs; 517 } 518 519 520 /** 521 * Gets the supported JWS algorithms for UserInfo JWTs. Corresponds to 522 * the {@code userinfo_signing_alg_values_supported} metadata field. 523 * 524 * @return The supported JWS algorithms, {@code null} if not specified. 525 */ 526 public List<JWSAlgorithm> getUserInfoJWSAlgs() { 527 528 return userInfoJWSAlgs; 529 } 530 531 532 /** 533 * Sets the supported JWS algorithms for UserInfo JWTs. Corresponds to 534 * the {@code userinfo_signing_alg_values_supported} metadata field. 535 * 536 * @param userInfoJWSAlgs The supported JWS algorithms, {@code null} if 537 * not specified. 538 */ 539 public void setUserInfoJWSAlgs(final List<JWSAlgorithm> userInfoJWSAlgs) { 540 541 this.userInfoJWSAlgs = userInfoJWSAlgs; 542 } 543 544 545 /** 546 * Gets the supported JWE algorithms for UserInfo JWTs. Corresponds to 547 * the {@code userinfo_encryption_alg_values_supported} metadata field. 548 * 549 * @return The supported JWE algorithms, {@code null} if not specified. 550 */ 551 public List<JWEAlgorithm> getUserInfoJWEAlgs() { 552 553 return userInfoJWEAlgs; 554 } 555 556 557 /** 558 * Sets the supported JWE algorithms for UserInfo JWTs. Corresponds to 559 * the {@code userinfo_encryption_alg_values_supported} metadata field. 560 * 561 * @param userInfoJWEAlgs The supported JWE algorithms, {@code null} if 562 * not specified. 563 */ 564 public void setUserInfoJWEAlgs(final List<JWEAlgorithm> userInfoJWEAlgs) { 565 566 this.userInfoJWEAlgs = userInfoJWEAlgs; 567 } 568 569 570 /** 571 * Gets the supported encryption methods for UserInfo JWTs. Corresponds 572 * to the {@code userinfo_encryption_enc_values_supported} metadata 573 * field. 574 * 575 * @return The supported encryption methods, {@code null} if not 576 * specified. 577 */ 578 public List<EncryptionMethod> getUserInfoJWEEncs() { 579 580 return userInfoJWEEncs; 581 } 582 583 584 /** 585 * Sets the supported encryption methods for UserInfo JWTs. Corresponds 586 * to the {@code userinfo_encryption_enc_values_supported} metadata 587 * field. 588 * 589 * @param userInfoJWEEncs The supported encryption methods, 590 * {@code null} if not specified. 591 */ 592 public void setUserInfoJWEEncs(final List<EncryptionMethod> userInfoJWEEncs) { 593 594 this.userInfoJWEEncs = userInfoJWEEncs; 595 } 596 597 598 /** 599 * Gets the supported displays. Corresponds to the 600 * {@code display_values_supported} metadata field. 601 * 602 * @return The supported displays, {@code null} if not specified. 603 */ 604 public List<Display> getDisplays() { 605 606 return displays; 607 } 608 609 610 /** 611 * Sets the supported displays. Corresponds to the 612 * {@code display_values_supported} metadata field. 613 * 614 * @param displays The supported displays, {@code null} if not 615 * specified. 616 */ 617 public void setDisplays(final List<Display> displays) { 618 619 this.displays = displays; 620 } 621 622 623 /** 624 * Gets the supported claim types. Corresponds to the 625 * {@code claim_types_supported} metadata field. 626 * 627 * @return The supported claim types, {@code null} if not specified. 628 */ 629 public List<ClaimType> getClaimTypes() { 630 631 return claimTypes; 632 } 633 634 635 /** 636 * Sets the supported claim types. Corresponds to the 637 * {@code claim_types_supported} metadata field. 638 * 639 * @param claimTypes The supported claim types, {@code null} if not 640 * specified. 641 */ 642 public void setClaimTypes(final List<ClaimType> claimTypes) { 643 644 this.claimTypes = claimTypes; 645 } 646 647 648 /** 649 * Gets the supported claims names. Corresponds to the 650 * {@code claims_supported} metadata field. 651 * 652 * @return The supported claims names, {@code null} if not specified. 653 */ 654 public List<String> getClaims() { 655 656 return claims; 657 } 658 659 660 /** 661 * Sets the supported claims names. Corresponds to the 662 * {@code claims_supported} metadata field. 663 * 664 * @param claims The supported claims names, {@code null} if not 665 * specified. 666 */ 667 public void setClaims(final List<String> claims) { 668 669 this.claims = claims; 670 } 671 672 673 /** 674 * Gets the supported claims locales. Corresponds to the 675 * {@code claims_locales_supported} metadata field. 676 * 677 * @return The supported claims locales, {@code null} if not specified. 678 */ 679 public List<LangTag> getClaimsLocales() { 680 681 return claimsLocales; 682 } 683 684 685 /** 686 * Sets the supported claims locales. Corresponds to the 687 * {@code claims_locales_supported} metadata field. 688 * 689 * @param claimsLocales The supported claims locales, {@code null} if 690 * not specified. 691 */ 692 public void setClaimLocales(final List<LangTag> claimsLocales) { 693 694 this.claimsLocales = claimsLocales; 695 } 696 697 698 /** 699 * Gets the support for the {@code claims} authorisation request 700 * parameter. Corresponds to the {@code claims_parameter_supported} 701 * metadata field. 702 * 703 * @return {@code true} if the {@code claim} parameter is supported, 704 * else {@code false}. 705 */ 706 public boolean supportsClaimsParam() { 707 708 return claimsParamSupported; 709 } 710 711 712 /** 713 * Sets the support for the {@code claims} authorisation request 714 * parameter. Corresponds to the {@code claims_parameter_supported} 715 * metadata field. 716 * 717 * @param claimsParamSupported {@code true} if the {@code claim} 718 * parameter is supported, else 719 * {@code false}. 720 */ 721 public void setSupportsClaimsParams(final boolean claimsParamSupported) { 722 723 this.claimsParamSupported = claimsParamSupported; 724 } 725 726 727 /** 728 * Gets the support for front-channel logout. Corresponds to the 729 * {@code frontchannel_logout_supported} metadata field. 730 * 731 * @return {@code true} if front-channel logout is supported, else 732 * {@code false}. 733 */ 734 public boolean supportsFrontChannelLogout() { 735 736 return frontChannelLogoutSupported; 737 } 738 739 740 /** 741 * Sets the support for front-channel logout. Corresponds to the 742 * {@code frontchannel_logout_supported} metadata field. 743 * 744 * @param frontChannelLogoutSupported {@code true} if front-channel 745 * logout is supported, else 746 * {@code false}. 747 */ 748 public void setSupportsFrontChannelLogout(final boolean frontChannelLogoutSupported) { 749 750 this.frontChannelLogoutSupported = frontChannelLogoutSupported; 751 } 752 753 754 /** 755 * Gets the support for front-channel logout with a session ID. 756 * Corresponds to the {@code frontchannel_logout_session_supported} 757 * metadata field. 758 * 759 * @return {@code true} if front-channel logout with a session ID is 760 * supported, else {@code false}. 761 */ 762 public boolean supportsFrontChannelLogoutSession() { 763 764 return frontChannelLogoutSessionSupported; 765 } 766 767 768 /** 769 * Sets the support for front-channel logout with a session ID. 770 * Corresponds to the {@code frontchannel_logout_session_supported} 771 * metadata field. 772 * 773 * @param frontChannelLogoutSessionSupported {@code true} if 774 * front-channel logout with 775 * a session ID is supported, 776 * else {@code false}. 777 */ 778 public void setSupportsFrontChannelLogoutSession(final boolean frontChannelLogoutSessionSupported) { 779 780 this.frontChannelLogoutSessionSupported = frontChannelLogoutSessionSupported; 781 } 782 783 784 /** 785 * Gets the support for back-channel logout. Corresponds to the 786 * {@code backchannel_logout_supported} metadata field. 787 * 788 * @return {@code true} if back-channel logout is supported, else 789 * {@code false}. 790 */ 791 public boolean supportsBackChannelLogout() { 792 793 return backChannelLogoutSupported; 794 } 795 796 797 /** 798 * Sets the support for back-channel logout. Corresponds to the 799 * {@code backchannel_logout_supported} metadata field. 800 * 801 * @param backChannelLogoutSupported {@code true} if back-channel 802 * logout is supported, else 803 * {@code false}. 804 */ 805 public void setSupportsBackChannelLogout(final boolean backChannelLogoutSupported) { 806 807 this.backChannelLogoutSupported = backChannelLogoutSupported; 808 } 809 810 811 /** 812 * Gets the support for back-channel logout with a session ID. 813 * Corresponds to the {@code backchannel_logout_session_supported} 814 * metadata field. 815 * 816 * @return {@code true} if back-channel logout with a session ID is 817 * supported, else {@code false}. 818 */ 819 public boolean supportsBackChannelLogoutSession() { 820 821 return backChannelLogoutSessionSupported; 822 } 823 824 825 /** 826 * Sets the support for back-channel logout with a session ID. 827 * Corresponds to the {@code backchannel_logout_session_supported} 828 * metadata field. 829 * 830 * @param backChannelLogoutSessionSupported {@code true} if 831 * back-channel logout with a 832 * session ID is supported, 833 * else {@code false}. 834 */ 835 public void setSupportsBackChannelLogoutSession(final boolean backChannelLogoutSessionSupported) { 836 837 this.backChannelLogoutSessionSupported = backChannelLogoutSessionSupported; 838 } 839 840 841 /** 842 * Gets support for verified claims. Corresponds to the 843 * {@code verified_claims_supported} metadata field. 844 * 845 * @return {@code true} if verified claims are supported, else 846 * {@code false}. 847 */ 848 public boolean supportsVerifiedClaims() { 849 850 return verifiedClaimsSupported; 851 } 852 853 854 /** 855 * Sets support for verified claims. Corresponds to the 856 * {@code verified_claims_supported} metadata field. 857 * 858 * @param verifiedClaimsSupported {@code true} if verified claims are 859 * supported, else {@code false}. 860 */ 861 public void setSupportsVerifiedClaims(final boolean verifiedClaimsSupported) { 862 863 this.verifiedClaimsSupported = verifiedClaimsSupported; 864 } 865 866 867 /** 868 * Gets the supported identity trust frameworks. Corresponds to the 869 * {@code trust_frameworks_supported} metadata field. 870 * 871 * @return The supported identity trust frameworks, {@code null} if not 872 * specified. 873 */ 874 public List<IdentityTrustFramework> getIdentityTrustFrameworks() { 875 return trustFrameworks; 876 } 877 878 879 /** 880 * Sets the supported identity trust frameworks. Corresponds to the 881 * {@code trust_frameworks_supported} metadata field. 882 * 883 * @param trustFrameworks The supported identity trust frameworks, 884 * {@code null} if not specified. 885 */ 886 public void setIdentityTrustFrameworks(final List<IdentityTrustFramework> trustFrameworks) { 887 this.trustFrameworks = trustFrameworks; 888 } 889 890 891 /** 892 * Gets the supported identity evidence types. Corresponds to the 893 * {@code evidence_supported} metadata field. 894 * 895 * @return The supported identity evidence types, {@code null} if not 896 * specified. 897 */ 898 public List<IdentityEvidenceType> getIdentityEvidenceTypes() { 899 return evidenceTypes; 900 } 901 902 903 /** 904 * Sets the supported identity evidence types. Corresponds to the 905 * {@code evidence_supported} metadata field. 906 * 907 * @param evidenceTypes The supported identity evidence types, 908 * {@code null} if not specified. 909 */ 910 public void setIdentityEvidenceTypes(final List<IdentityEvidenceType> evidenceTypes) { 911 this.evidenceTypes = evidenceTypes; 912 } 913 914 915 /** 916 * Gets the supported identity document types. Corresponds to the 917 * {@code id_documents_supported} metadata field. 918 * 919 * @return The supported identity documents types, {@code null} 920 * if not specified. 921 */ 922 public List<IDDocumentType> getIdentityDocumentTypes() { 923 return idDocuments; 924 } 925 926 927 /** 928 * Sets the supported identity document types. Corresponds to the 929 * {@code id_documents_supported} metadata field. 930 * 931 * @param idDocuments The supported identity document types, 932 * {@code null} if not specified. 933 */ 934 public void setIdentityDocumentTypes(List<IDDocumentType> idDocuments) { 935 this.idDocuments = idDocuments; 936 } 937 938 939 /** 940 * Gets the supported identity verification methods. Corresponds to the 941 * {@code id_documents_verification_methods_supported} metadata field. 942 * 943 * @return The supported identity verification methods, {@code null} 944 * if not specified. 945 */ 946 public List<IdentityVerificationMethod> getIdentityVerificationMethods() { 947 return idVerificationMethods; 948 } 949 950 951 /** 952 * Sets the supported identity verification methods. Corresponds to the 953 * {@code id_documents_verification_methods_supported} metadata field. 954 * 955 * @param idVerificationMethods The supported identity verification 956 * methods, {@code null} if not specified. 957 */ 958 public void setIdentityVerificationMethods(final List<IdentityVerificationMethod> idVerificationMethods) { 959 this.idVerificationMethods = idVerificationMethods; 960 } 961 962 963 /** 964 * Gets the supported verified claims names. Corresponds to the 965 * {@code claims_in_verified_claims_supported} metadata field. 966 * 967 * @return The supported verified claims names, {@code null} if not 968 * specified. 969 */ 970 public List<String> getVerifiedClaims() { 971 return verifiedClaims; 972 } 973 974 975 /** 976 * Gets the supported verified claims names. Corresponds to the 977 * {@code claims_in_verified_claims_supported} metadata field. 978 * 979 * @param verifiedClaims The supported verified claims names, 980 * {@code null} if not specified. 981 */ 982 public void setVerifiedClaims(final List<String> verifiedClaims) { 983 this.verifiedClaims = verifiedClaims; 984 } 985 986 987 /** 988 * Applies the OpenID Provider metadata defaults where no values have 989 * been specified. 990 * 991 * <ul> 992 * <li>The response modes default to {@code ["query", "fragment"]}. 993 * <li>The grant types default to {@code ["authorization_code", 994 * "implicit"]}. 995 * <li>The token endpoint authentication methods default to 996 * {@code ["client_secret_basic"]}. 997 * <li>The claim types default to {@code ["normal]}. 998 * </ul> 999 */ 1000 public void applyDefaults() { 1001 1002 super.applyDefaults(); 1003 1004 if (claimTypes == null) { 1005 claimTypes = new ArrayList<>(1); 1006 claimTypes.add(ClaimType.NORMAL); 1007 } 1008 } 1009 1010 1011 /** 1012 * Returns the JSON object representation of this OpenID Connect 1013 * provider metadata. 1014 * 1015 * @return The JSON object representation. 1016 */ 1017 public JSONObject toJSONObject() { 1018 1019 JSONObject o = super.toJSONObject(); 1020 1021 // Mandatory fields 1022 1023 List<String> stringList = new ArrayList<>(subjectTypes.size()); 1024 1025 for (SubjectType st: subjectTypes) 1026 stringList.add(st.toString()); 1027 1028 o.put("subject_types_supported", stringList); 1029 1030 // Optional fields 1031 1032 if (userInfoEndpoint != null) 1033 o.put("userinfo_endpoint", userInfoEndpoint.toString()); 1034 1035 if (checkSessionIframe != null) 1036 o.put("check_session_iframe", checkSessionIframe.toString()); 1037 1038 if (endSessionEndpoint != null) 1039 o.put("end_session_endpoint", endSessionEndpoint.toString()); 1040 1041 if (acrValues != null) { 1042 o.put("acr_values_supported", Identifier.toStringList(acrValues)); 1043 } 1044 1045 if (idTokenJWSAlgs != null) { 1046 1047 stringList = new ArrayList<>(idTokenJWSAlgs.size()); 1048 1049 for (JWSAlgorithm alg: idTokenJWSAlgs) 1050 stringList.add(alg.getName()); 1051 1052 o.put("id_token_signing_alg_values_supported", stringList); 1053 } 1054 1055 if (idTokenJWEAlgs != null) { 1056 1057 stringList = new ArrayList<>(idTokenJWEAlgs.size()); 1058 1059 for (JWEAlgorithm alg: idTokenJWEAlgs) 1060 stringList.add(alg.getName()); 1061 1062 o.put("id_token_encryption_alg_values_supported", stringList); 1063 } 1064 1065 if (idTokenJWEEncs != null) { 1066 1067 stringList = new ArrayList<>(idTokenJWEEncs.size()); 1068 1069 for (EncryptionMethod m: idTokenJWEEncs) 1070 stringList.add(m.getName()); 1071 1072 o.put("id_token_encryption_enc_values_supported", stringList); 1073 } 1074 1075 if (userInfoJWSAlgs != null) { 1076 1077 stringList = new ArrayList<>(userInfoJWSAlgs.size()); 1078 1079 for (JWSAlgorithm alg: userInfoJWSAlgs) 1080 stringList.add(alg.getName()); 1081 1082 o.put("userinfo_signing_alg_values_supported", stringList); 1083 } 1084 1085 if (userInfoJWEAlgs != null) { 1086 1087 stringList = new ArrayList<>(userInfoJWEAlgs.size()); 1088 1089 for (JWEAlgorithm alg: userInfoJWEAlgs) 1090 stringList.add(alg.getName()); 1091 1092 o.put("userinfo_encryption_alg_values_supported", stringList); 1093 } 1094 1095 if (userInfoJWEEncs != null) { 1096 1097 stringList = new ArrayList<>(userInfoJWEEncs.size()); 1098 1099 for (EncryptionMethod m: userInfoJWEEncs) 1100 stringList.add(m.getName()); 1101 1102 o.put("userinfo_encryption_enc_values_supported", stringList); 1103 } 1104 1105 if (displays != null) { 1106 1107 stringList = new ArrayList<>(displays.size()); 1108 1109 for (Display d: displays) 1110 stringList.add(d.toString()); 1111 1112 o.put("display_values_supported", stringList); 1113 } 1114 1115 if (claimTypes != null) { 1116 1117 stringList = new ArrayList<>(claimTypes.size()); 1118 1119 for (ClaimType ct: claimTypes) 1120 stringList.add(ct.toString()); 1121 1122 o.put("claim_types_supported", stringList); 1123 } 1124 1125 if (claims != null) 1126 o.put("claims_supported", claims); 1127 1128 if (claimsLocales != null) { 1129 1130 stringList = new ArrayList<>(claimsLocales.size()); 1131 1132 for (LangTag l: claimsLocales) 1133 stringList.add(l.toString()); 1134 1135 o.put("claims_locales_supported", stringList); 1136 } 1137 1138 o.put("claims_parameter_supported", claimsParamSupported); 1139 1140 // optional front and back-channel logout 1141 o.put("frontchannel_logout_supported", frontChannelLogoutSupported); 1142 1143 if (frontChannelLogoutSupported) { 1144 o.put("frontchannel_logout_session_supported", frontChannelLogoutSessionSupported); 1145 } 1146 1147 o.put("backchannel_logout_supported", backChannelLogoutSupported); 1148 1149 if (backChannelLogoutSupported) { 1150 o.put("backchannel_logout_session_supported", backChannelLogoutSessionSupported); 1151 } 1152 1153 if (verifiedClaimsSupported) { 1154 o.put("verified_claims_supported", true); 1155 if (trustFrameworks != null) { 1156 o.put("trust_frameworks_supported", Identifier.toStringList(trustFrameworks)); 1157 } 1158 if (evidenceTypes != null) { 1159 o.put("evidence_supported", Identifier.toStringList(evidenceTypes)); 1160 } 1161 if (idDocuments != null) { 1162 o.put("id_documents_supported", Identifier.toStringList(idDocuments)); 1163 } 1164 if (idVerificationMethods != null) { 1165 o.put("id_documents_verification_methods_supported", Identifier.toStringList(idVerificationMethods)); 1166 } 1167 if (verifiedClaims != null) { 1168 o.put("claims_in_verified_claims_supported", verifiedClaims); 1169 } 1170 } 1171 1172 return o; 1173 } 1174 1175 1176 /** 1177 * Parses an OpenID Provider metadata from the specified JSON object. 1178 * 1179 * @param jsonObject The JSON object to parse. Must not be 1180 * {@code null}. 1181 * 1182 * @return The OpenID Provider metadata. 1183 * 1184 * @throws ParseException If the JSON object couldn't be parsed to an 1185 * OpenID Provider metadata. 1186 */ 1187 public static OIDCProviderMetadata parse(final JSONObject jsonObject) 1188 throws ParseException { 1189 1190 AuthorizationServerMetadata as = AuthorizationServerMetadata.parse(jsonObject); 1191 1192 List<SubjectType> subjectTypes = new ArrayList<>(); 1193 for (String v: JSONObjectUtils.getStringArray(jsonObject, "subject_types_supported")) { 1194 subjectTypes.add(SubjectType.parse(v)); 1195 } 1196 1197 OIDCProviderMetadata op = new OIDCProviderMetadata( 1198 as.getIssuer(), 1199 Collections.unmodifiableList(subjectTypes), 1200 as.getJWKSetURI()); 1201 1202 // Endpoints 1203 op.setAuthorizationEndpointURI(as.getAuthorizationEndpointURI()); 1204 op.setTokenEndpointURI(as.getTokenEndpointURI()); 1205 op.setRegistrationEndpointURI(as.getRegistrationEndpointURI()); 1206 op.setIntrospectionEndpointURI(as.getIntrospectionEndpointURI()); 1207 op.setRevocationEndpointURI(as.getRevocationEndpointURI()); 1208 op.setRequestObjectEndpoint(as.getRequestObjectEndpoint()); 1209 op.userInfoEndpoint = JSONObjectUtils.getURI(jsonObject, "userinfo_endpoint", null); 1210 op.checkSessionIframe = JSONObjectUtils.getURI(jsonObject, "check_session_iframe", null); 1211 op.endSessionEndpoint = JSONObjectUtils.getURI(jsonObject, "end_session_endpoint", null); 1212 1213 // Capabilities 1214 op.setScopes(as.getScopes()); 1215 op.setResponseTypes(as.getResponseTypes()); 1216 op.setResponseModes(as.getResponseModes()); 1217 op.setGrantTypes(as.getGrantTypes()); 1218 1219 op.setTokenEndpointAuthMethods(as.getTokenEndpointAuthMethods()); 1220 op.setTokenEndpointJWSAlgs(as.getTokenEndpointJWSAlgs()); 1221 1222 op.setIntrospectionEndpointAuthMethods(as.getIntrospectionEndpointAuthMethods()); 1223 op.setIntrospectionEndpointJWSAlgs(as.getIntrospectionEndpointJWSAlgs()); 1224 1225 op.setRevocationEndpointAuthMethods(as.getRevocationEndpointAuthMethods()); 1226 op.setRevocationEndpointJWSAlgs(as.getRevocationEndpointJWSAlgs()); 1227 1228 op.setRequestObjectJWSAlgs(as.getRequestObjectJWSAlgs()); 1229 op.setRequestObjectJWEAlgs(as.getRequestObjectJWEAlgs()); 1230 op.setRequestObjectJWEEncs(as.getRequestObjectJWEEncs()); 1231 1232 op.setSupportsRequestParam(as.supportsRequestParam()); 1233 op.setSupportsRequestURIParam(as.supportsRequestURIParam()); 1234 op.setRequiresRequestURIRegistration(as.requiresRequestURIRegistration()); 1235 1236 op.setCodeChallengeMethods(as.getCodeChallengeMethods()); 1237 1238 if (jsonObject.get("acr_values_supported") != null) { 1239 1240 op.acrValues = new ArrayList<>(); 1241 1242 for (String v: JSONObjectUtils.getStringArray(jsonObject, "acr_values_supported")) { 1243 1244 if (v != null) 1245 op.acrValues.add(new ACR(v)); 1246 } 1247 } 1248 1249 // ID token 1250 1251 if (jsonObject.get("id_token_signing_alg_values_supported") != null) { 1252 1253 op.idTokenJWSAlgs = new ArrayList<>(); 1254 1255 for (String v: JSONObjectUtils.getStringArray(jsonObject, "id_token_signing_alg_values_supported")) { 1256 1257 if (v != null) 1258 op.idTokenJWSAlgs.add(JWSAlgorithm.parse(v)); 1259 } 1260 } 1261 1262 1263 if (jsonObject.get("id_token_encryption_alg_values_supported") != null) { 1264 1265 op.idTokenJWEAlgs = new ArrayList<>(); 1266 1267 for (String v: JSONObjectUtils.getStringArray(jsonObject, "id_token_encryption_alg_values_supported")) { 1268 1269 if (v != null) 1270 op.idTokenJWEAlgs.add(JWEAlgorithm.parse(v)); 1271 } 1272 } 1273 1274 1275 if (jsonObject.get("id_token_encryption_enc_values_supported") != null) { 1276 1277 op.idTokenJWEEncs = new ArrayList<>(); 1278 1279 for (String v: JSONObjectUtils.getStringArray(jsonObject, "id_token_encryption_enc_values_supported")) { 1280 1281 if (v != null) 1282 op.idTokenJWEEncs.add(EncryptionMethod.parse(v)); 1283 } 1284 } 1285 1286 // UserInfo 1287 1288 if (jsonObject.get("userinfo_signing_alg_values_supported") != null) { 1289 1290 op.userInfoJWSAlgs = new ArrayList<>(); 1291 1292 for (String v: JSONObjectUtils.getStringArray(jsonObject, "userinfo_signing_alg_values_supported")) { 1293 1294 if (v != null) 1295 op.userInfoJWSAlgs.add(JWSAlgorithm.parse(v)); 1296 } 1297 } 1298 1299 1300 if (jsonObject.get("userinfo_encryption_alg_values_supported") != null) { 1301 1302 op.userInfoJWEAlgs = new ArrayList<>(); 1303 1304 for (String v: JSONObjectUtils.getStringArray(jsonObject, "userinfo_encryption_alg_values_supported")) { 1305 1306 if (v != null) 1307 op.userInfoJWEAlgs.add(JWEAlgorithm.parse(v)); 1308 } 1309 } 1310 1311 1312 if (jsonObject.get("userinfo_encryption_enc_values_supported") != null) { 1313 1314 op.userInfoJWEEncs = new ArrayList<>(); 1315 1316 for (String v: JSONObjectUtils.getStringArray(jsonObject, "userinfo_encryption_enc_values_supported")) { 1317 1318 if (v != null) 1319 op.userInfoJWEEncs.add(EncryptionMethod.parse(v)); 1320 } 1321 } 1322 1323 1324 // Misc 1325 1326 if (jsonObject.get("display_values_supported") != null) { 1327 1328 op.displays = new ArrayList<>(); 1329 1330 for (String v: JSONObjectUtils.getStringArray(jsonObject, "display_values_supported")) { 1331 1332 if (v != null) 1333 op.displays.add(Display.parse(v)); 1334 } 1335 } 1336 1337 if (jsonObject.get("claim_types_supported") != null) { 1338 1339 op.claimTypes = new ArrayList<>(); 1340 1341 for (String v: JSONObjectUtils.getStringArray(jsonObject, "claim_types_supported")) { 1342 1343 if (v != null) 1344 op.claimTypes.add(ClaimType.parse(v)); 1345 } 1346 } 1347 1348 1349 if (jsonObject.get("claims_supported") != null) { 1350 1351 op.claims = new ArrayList<>(); 1352 1353 for (String v: JSONObjectUtils.getStringArray(jsonObject, "claims_supported")) { 1354 1355 if (v != null) 1356 op.claims.add(v); 1357 } 1358 } 1359 1360 if (jsonObject.get("claims_locales_supported") != null) { 1361 1362 op.claimsLocales = new ArrayList<>(); 1363 1364 for (String v : JSONObjectUtils.getStringArray(jsonObject, "claims_locales_supported")) { 1365 1366 if (v != null) { 1367 1368 try { 1369 op.claimsLocales.add(LangTag.parse(v)); 1370 1371 } catch (LangTagException e) { 1372 1373 throw new ParseException("Invalid claims_locales_supported field: " + e.getMessage(), e); 1374 } 1375 } 1376 } 1377 } 1378 1379 op.setUILocales(as.getUILocales()); 1380 op.setServiceDocsURI(as.getServiceDocsURI()); 1381 op.setPolicyURI(as.getPolicyURI()); 1382 op.setTermsOfServiceURI(as.getTermsOfServiceURI()); 1383 1384 if (jsonObject.get("claims_parameter_supported") != null) 1385 op.claimsParamSupported = JSONObjectUtils.getBoolean(jsonObject, "claims_parameter_supported"); 1386 1387 // Optional front and back-channel logout 1388 if (jsonObject.get("frontchannel_logout_supported") != null) 1389 op.frontChannelLogoutSupported = JSONObjectUtils.getBoolean(jsonObject, "frontchannel_logout_supported"); 1390 1391 if (op.frontChannelLogoutSupported && jsonObject.get("frontchannel_logout_session_supported") != null) 1392 op.frontChannelLogoutSessionSupported = JSONObjectUtils.getBoolean(jsonObject, "frontchannel_logout_session_supported"); 1393 1394 if (jsonObject.get("backchannel_logout_supported") != null) 1395 op.backChannelLogoutSupported = JSONObjectUtils.getBoolean(jsonObject, "backchannel_logout_supported"); 1396 1397 if (op.frontChannelLogoutSupported && jsonObject.get("backchannel_logout_session_supported") != null) 1398 op.backChannelLogoutSessionSupported = JSONObjectUtils.getBoolean(jsonObject, "backchannel_logout_session_supported"); 1399 1400 if (jsonObject.get("mtls_endpoint_aliases") != null) 1401 op.setMtlsEndpointAliases(OIDCProviderEndpointMetadata.parse(JSONObjectUtils.getJSONObject(jsonObject, "mtls_endpoint_aliases"))); 1402 1403 op.setSupportsTLSClientCertificateBoundAccessTokens(as.supportsTLSClientCertificateBoundAccessTokens()); 1404 1405 // JARM 1406 op.setAuthorizationJWSAlgs(as.getAuthorizationJWSAlgs()); 1407 op.setAuthorizationJWEAlgs(as.getAuthorizationJWEAlgs()); 1408 op.setAuthorizationJWEEncs(as.getAuthorizationJWEEncs()); 1409 1410 // OpenID Connect for Identity Assurance 1.0 1411 if (jsonObject.get("verified_claims_supported") != null) { 1412 op.verifiedClaimsSupported = JSONObjectUtils.getBoolean(jsonObject, "verified_claims_supported"); 1413 if (op.verifiedClaimsSupported) { 1414 if (jsonObject.get("trust_frameworks_supported") != null) { 1415 op.trustFrameworks = new LinkedList<>(); 1416 for (String v : JSONObjectUtils.getStringList(jsonObject, "trust_frameworks_supported")) { 1417 op.trustFrameworks.add(new IdentityTrustFramework(v)); 1418 } 1419 } 1420 if (jsonObject.get("evidence_supported") != null) { 1421 op.evidenceTypes = new LinkedList<>(); 1422 for (String v: JSONObjectUtils.getStringList(jsonObject, "evidence_supported")) { 1423 op.evidenceTypes.add(new IdentityEvidenceType(v)); 1424 } 1425 } 1426 if (jsonObject.get("id_documents_supported") != null) { 1427 op.idDocuments = new LinkedList<>(); 1428 for (String v: JSONObjectUtils.getStringList(jsonObject, "id_documents_supported")) { 1429 op.idDocuments.add(new IDDocumentType(v)); 1430 } 1431 } 1432 if (jsonObject.get("id_documents_verification_methods_supported") != null) { 1433 op.idVerificationMethods = new LinkedList<>(); 1434 for (String v: JSONObjectUtils.getStringList(jsonObject, "id_documents_verification_methods_supported")) { 1435 op.idVerificationMethods.add(new IdentityVerificationMethod(v)); 1436 } 1437 } 1438 if (jsonObject.get("claims_in_verified_claims_supported") != null) { 1439 op.verifiedClaims = JSONObjectUtils.getStringList(jsonObject, "claims_in_verified_claims_supported"); 1440 } 1441 } 1442 } 1443 1444 // Parse custom (not registered) parameters 1445 for (Map.Entry<String,?> entry: as.getCustomParameters().entrySet()) { 1446 if (REGISTERED_PARAMETER_NAMES.contains(entry.getKey())) 1447 continue; // skip 1448 op.setCustomParameter(entry.getKey(), entry.getValue()); 1449 } 1450 1451 return op; 1452 } 1453 1454 1455 /** 1456 * Parses an OpenID Provider metadata from the specified JSON object 1457 * string. 1458 * 1459 * @param s The JSON object sting to parse. Must not be {@code null}. 1460 * 1461 * @return The OpenID Provider metadata. 1462 * 1463 * @throws ParseException If the JSON object string couldn't be parsed 1464 * to an OpenID Provider metadata. 1465 */ 1466 public static OIDCProviderMetadata parse(final String s) 1467 throws ParseException { 1468 1469 return parse(JSONObjectUtils.parse(s)); 1470 } 1471 1472 1473 /** 1474 * Resolves OpenID Provider metadata URL from the specified issuer 1475 * identifier. 1476 * 1477 * @param issuer The OpenID Provider issuer identifier. Must represent 1478 * a valid HTTPS or HTTP URL. Must not be {@code null}. 1479 * 1480 * @return The OpenID Provider metadata URL. 1481 * 1482 * @throws GeneralException If the issuer identifier is invalid. 1483 */ 1484 public static URL resolveURL(final Issuer issuer) 1485 throws GeneralException { 1486 1487 try { 1488 URL issuerURL = new URL(issuer.getValue()); 1489 1490 // Validate but don't insist on HTTPS, see 1491 // http://openid.net/specs/openid-connect-core-1_0.html#Terminology 1492 if (issuerURL.getQuery() != null && ! issuerURL.getQuery().trim().isEmpty()) { 1493 throw new GeneralException("The issuer identifier must not contain a query component"); 1494 } 1495 1496 if (issuerURL.getPath() != null && issuerURL.getPath().endsWith("/")) { 1497 return new URL(issuerURL + ".well-known/openid-configuration"); 1498 } else { 1499 return new URL(issuerURL + "/.well-known/openid-configuration"); 1500 } 1501 1502 } catch (MalformedURLException e) { 1503 throw new GeneralException("The issuer identifier doesn't represent a valid URL: " + e.getMessage(), e); 1504 } 1505 } 1506 1507 1508 /** 1509 * Resolves OpenID Provider metadata from the specified issuer 1510 * identifier. The metadata is downloaded by HTTP GET from 1511 * {@code [issuer-url]/.well-known/openid-configuration}. 1512 * 1513 * @param issuer The OpenID Provider issuer identifier. Must represent 1514 * a valid HTTPS or HTTP URL. Must not be {@code null}. 1515 * 1516 * @return The OpenID Provider metadata. 1517 * 1518 * @throws GeneralException If the issuer identifier or the downloaded 1519 * metadata are invalid. 1520 * @throws IOException On a HTTP exception. 1521 */ 1522 public static OIDCProviderMetadata resolve(final Issuer issuer) 1523 throws GeneralException, IOException { 1524 1525 return resolve(issuer, 0, 0); 1526 } 1527 1528 1529 /** 1530 * Resolves OpenID Provider metadata from the specified issuer 1531 * identifier. The metadata is downloaded by HTTP GET from 1532 * {@code [issuer-url]/.well-known/openid-configuration}, using the 1533 * specified HTTP timeouts. 1534 * 1535 * @param issuer The issuer identifier. Must represent a valid 1536 * HTTPS or HTTP URL. Must not be {@code null}. 1537 * @param connectTimeout The HTTP connect timeout, in milliseconds. 1538 * Zero implies no timeout. Must not be negative. 1539 * @param readTimeout The HTTP response read timeout, in 1540 * milliseconds. Zero implies no timeout. Must 1541 * not be negative. 1542 * 1543 * @return The OpenID Provider metadata. 1544 * 1545 * @throws GeneralException If the issuer identifier or the downloaded 1546 * metadata are invalid. 1547 * @throws IOException On a HTTP exception. 1548 */ 1549 public static OIDCProviderMetadata resolve(final Issuer issuer, 1550 final int connectTimeout, 1551 final int readTimeout) 1552 throws GeneralException, IOException { 1553 1554 URL configURL = resolveURL(issuer); 1555 1556 HTTPRequest httpRequest = new HTTPRequest(HTTPRequest.Method.GET, configURL); 1557 httpRequest.setConnectTimeout(connectTimeout); 1558 httpRequest.setReadTimeout(readTimeout); 1559 1560 HTTPResponse httpResponse = httpRequest.send(); 1561 1562 if (httpResponse.getStatusCode() != 200) { 1563 throw new IOException("Couldn't download OpenID Provider metadata from " + configURL + 1564 ": Status code " + httpResponse.getStatusCode()); 1565 } 1566 1567 JSONObject jsonObject = httpResponse.getContentAsJSONObject(); 1568 1569 OIDCProviderMetadata op = OIDCProviderMetadata.parse(jsonObject); 1570 1571 if (! issuer.equals(op.getIssuer())) { 1572 throw new GeneralException("The returned issuer doesn't match the expected: " + op.getIssuer()); 1573 } 1574 1575 return op; 1576 } 1577}