001/* 002 * oauth2-oidc-sdk 003 * 004 * Copyright 2012-2022 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 com.nimbusds.jose.EncryptionMethod; 022import com.nimbusds.jose.JWEAlgorithm; 023import com.nimbusds.jose.JWSAlgorithm; 024import com.nimbusds.jose.jwk.JWKSet; 025import com.nimbusds.langtag.LangTag; 026import com.nimbusds.langtag.LangTagException; 027import com.nimbusds.oauth2.sdk.GeneralException; 028import com.nimbusds.oauth2.sdk.ParseException; 029import com.nimbusds.oauth2.sdk.as.AuthorizationServerEndpointMetadata; 030import com.nimbusds.oauth2.sdk.as.AuthorizationServerMetadata; 031import com.nimbusds.oauth2.sdk.http.HTTPRequest; 032import com.nimbusds.oauth2.sdk.http.HTTPRequestConfigurator; 033import com.nimbusds.oauth2.sdk.http.HTTPRequestModifier; 034import com.nimbusds.oauth2.sdk.http.HTTPResponse; 035import com.nimbusds.oauth2.sdk.id.Identifier; 036import com.nimbusds.oauth2.sdk.id.Issuer; 037import com.nimbusds.oauth2.sdk.util.CollectionUtils; 038import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 039import com.nimbusds.openid.connect.sdk.Display; 040import com.nimbusds.openid.connect.sdk.SubjectType; 041import com.nimbusds.openid.connect.sdk.assurance.IdentityTrustFramework; 042import com.nimbusds.openid.connect.sdk.assurance.evidences.*; 043import com.nimbusds.openid.connect.sdk.assurance.evidences.attachment.AttachmentType; 044import com.nimbusds.openid.connect.sdk.assurance.evidences.attachment.HashAlgorithm; 045import com.nimbusds.openid.connect.sdk.claims.ACR; 046import com.nimbusds.openid.connect.sdk.claims.ClaimType; 047import com.nimbusds.openid.connect.sdk.federation.registration.ClientRegistrationType; 048import net.minidev.json.JSONObject; 049 050import java.io.IOException; 051import java.net.MalformedURLException; 052import java.net.URI; 053import java.net.URL; 054import java.util.*; 055 056 057/** 058 * OpenID Provider (OP) metadata. 059 * 060 * <p>Related specifications: 061 * 062 * <ul> 063 * <li>OpenID Connect Discovery 1.0 064 * <li>OpenID Connect Session Management 1.0 065 * <li>OpenID Connect Front-Channel Logout 1.0 066 * <li>OpenID Connect Back-Channel Logout 1.0 067 * <li>OpenID Connect Native SSO for Mobile Apps 1.0 068 * <li>OpenID Connect for Identity Assurance 1.0 069 * <li>OpenID Connect Federation 1.0 070 * <li>Initiating User Registration via OpenID Connect 1.0 071 * <li>OAuth 2.0 Authorization Server Metadata (RFC 8414) 072 * <li>OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound 073 * Access Tokens (RFC 8705) 074 * <li>Financial-grade API: JWT Secured Authorization Response Mode for 075 * OAuth 2.0 (JARM) 076 * <li>OAuth 2.0 Authorization Server Issuer Identification (RFC 9207) 077 * <li>Financial-grade API - Part 2: Read and Write API Security Profile 078 * <li>OAuth 2.0 Pushed Authorization Requests (RFC 9126) 079 * <li>OAuth 2.0 Rich Authorization Requests (RFC 9396) 080 * <li>OAuth 2.0 Device Authorization Grant (RFC 8628) 081 * <li>OAuth 2.0 Incremental Authorization (draft-ietf-oauth-incremental-authz) 082 * </ul> 083 */ 084public class OIDCProviderMetadata extends AuthorizationServerMetadata implements ReadOnlyOIDCProviderMetadata { 085 086 087 /** 088 * The registered parameter names. 089 */ 090 private static final Set<String> REGISTERED_PARAMETER_NAMES; 091 092 093 static { 094 Set<String> p = new HashSet<>(AuthorizationServerMetadata.getRegisteredParameterNames()); 095 p.addAll(OIDCProviderEndpointMetadata.getRegisteredParameterNames()); 096 p.add("acr_values_supported"); 097 p.add("subject_types_supported"); 098 p.add("id_token_signing_alg_values_supported"); 099 p.add("id_token_encryption_alg_values_supported"); 100 p.add("id_token_encryption_enc_values_supported"); 101 p.add("userinfo_signing_alg_values_supported"); 102 p.add("userinfo_encryption_alg_values_supported"); 103 p.add("userinfo_encryption_enc_values_supported"); 104 p.add("display_values_supported"); 105 p.add("claim_types_supported"); 106 p.add("claims_supported"); 107 p.add("claims_locales_supported"); 108 p.add("claims_parameter_supported"); 109 p.add("backchannel_logout_supported"); 110 p.add("backchannel_logout_session_supported"); 111 p.add("frontchannel_logout_supported"); 112 p.add("frontchannel_logout_session_supported"); 113 p.add("native_sso_supported"); 114 p.add("verified_claims_supported"); 115 p.add("trust_frameworks_supported"); 116 p.add("evidence_supported"); 117 p.add("documents_supported"); 118 p.add("documents_methods_supported"); 119 p.add("documents_validation_methods_supported"); 120 p.add("documents_verification_methods_supported"); 121 p.add("id_documents_supported"); // deprecated 122 p.add("id_documents_verification_methods_supported"); // deprecated 123 p.add("electronic_records_supported"); 124 p.add("claims_in_verified_claims_supported"); 125 p.add("attachments_supported"); 126 p.add("digest_algorithms_supported"); 127 REGISTERED_PARAMETER_NAMES = Collections.unmodifiableSet(p); 128 } 129 130 131 /** 132 * The UserInfo endpoint. 133 */ 134 private URI userInfoEndpoint; 135 136 137 /** 138 * The cross-origin check session iframe. 139 */ 140 private URI checkSessionIframe; 141 142 143 /** 144 * The logout endpoint. 145 */ 146 private URI endSessionEndpoint; 147 148 149 /** 150 * The supported ACRs. 151 */ 152 private List<ACR> acrValues; 153 154 155 /** 156 * The supported subject types. 157 */ 158 private final List<SubjectType> subjectTypes; 159 160 161 /** 162 * The supported ID token JWS algorithms. 163 */ 164 private List<JWSAlgorithm> idTokenJWSAlgs; 165 166 167 /** 168 * The supported ID token JWE algorithms. 169 */ 170 private List<JWEAlgorithm> idTokenJWEAlgs; 171 172 173 /** 174 * The supported ID token encryption methods. 175 */ 176 private List<EncryptionMethod> idTokenJWEEncs; 177 178 179 /** 180 * The supported UserInfo JWS algorithms. 181 */ 182 private List<JWSAlgorithm> userInfoJWSAlgs; 183 184 185 /** 186 * The supported UserInfo JWE algorithms. 187 */ 188 private List<JWEAlgorithm> userInfoJWEAlgs; 189 190 191 /** 192 * The supported UserInfo encryption methods. 193 */ 194 private List<EncryptionMethod> userInfoJWEEncs; 195 196 197 /** 198 * The supported displays. 199 */ 200 private List<Display> displays; 201 202 203 /** 204 * The supported claim types. 205 */ 206 private List<ClaimType> claimTypes; 207 208 209 /** 210 * The supported claims names. 211 */ 212 private List<String> claims; 213 214 215 /** 216 * The supported claims locales. 217 */ 218 private List<LangTag> claimsLocales; 219 220 221 /** 222 * If {@code true} the {@code claims} parameter is supported, else not. 223 */ 224 private boolean claimsParamSupported = false; 225 226 227 /** 228 * If {@code true} the {@code frontchannel_logout_supported} parameter 229 * is set, else not. 230 */ 231 private boolean frontChannelLogoutSupported = false; 232 233 234 /** 235 * If {@code true} the {@code frontchannel_logout_session_supported} 236 * parameter is set, else not. 237 */ 238 private boolean frontChannelLogoutSessionSupported = false; 239 240 241 /** 242 * If {@code true} the {@code backchannel_logout_supported} parameter 243 * is set, else not. 244 */ 245 private boolean backChannelLogoutSupported = false; 246 247 248 /** 249 * If {@code true} the {@code backchannel_logout_session_supported} 250 * parameter is set, else not. 251 */ 252 private boolean backChannelLogoutSessionSupported = false; 253 254 255 /** 256 * If {@code true} the {@code native_sso_supported} parameter is set, 257 * else not. 258 */ 259 private boolean nativeSSOSupported = false; 260 261 262 /** 263 * If {@code true} verified claims are supported. 264 */ 265 private boolean verifiedClaimsSupported = false; 266 267 268 /** 269 * The supported trust frameworks. 270 */ 271 private List<IdentityTrustFramework> trustFrameworks; 272 273 274 /** 275 * The supported identity evidence types. 276 */ 277 private List<IdentityEvidenceType> evidenceTypes; 278 279 280 /** 281 * The supported identity document types. 282 */ 283 private List<DocumentType> documentTypes; 284 285 286 /** 287 * The supported coarse identity verification methods for evidences of 288 * type document. 289 */ 290 private List<IdentityVerificationMethod> documentMethods; 291 292 293 /** 294 * The supported validation methods for evidences of type document. 295 */ 296 private List<ValidationMethodType> documentValidationMethods; 297 298 299 /** 300 * The supported verification methods for evidences of type document. 301 */ 302 private List<VerificationMethodType> documentVerificationMethods; 303 304 305 /** 306 * The supported identity document types. 307 */ 308 @Deprecated 309 private List<IDDocumentType> idDocumentTypes; 310 311 312 /** 313 * The supported verification methods for identity documents. 314 */ 315 @Deprecated 316 private List<IdentityVerificationMethod> idVerificationMethods; 317 318 319 /** 320 * The supported electronic record types. 321 */ 322 private List<ElectronicRecordType> electronicRecordTypes; 323 324 325 /** 326 * The supported verified claims. 327 */ 328 private List<String> verifiedClaims; 329 330 331 /** 332 * The supported attachment types. 333 */ 334 private List<AttachmentType> attachmentTypes; 335 336 337 /** 338 * The supported digest algorithms for external attachments. 339 */ 340 private List<HashAlgorithm> attachmentDigestAlgs; 341 342 343 /** 344 * Creates a new OpenID Connect provider metadata instance. 345 * 346 * @param issuer The issuer identifier. Must be a URI using the 347 * https scheme with no query or fragment 348 * component. Must not be {@code null}. 349 * @param subjectTypes The supported subject types. At least one must 350 * be specified. Must not be {@code null}. 351 * @param jwkSetURI The JWK set URI. Must not be {@code null}. 352 */ 353 public OIDCProviderMetadata(final Issuer issuer, 354 final List<SubjectType> subjectTypes, 355 final URI jwkSetURI) { 356 357 super(issuer); 358 359 ensureAtLeastOneSubjectType(subjectTypes); 360 this.subjectTypes = subjectTypes; 361 setJWKSetURI(Objects.requireNonNull(jwkSetURI)); 362 363 // Default OpenID Connect setting is supported 364 setSupportsRequestURIParam(true); 365 } 366 367 368 /** 369 * Creates a new OpenID Connect Federation 1.0 provider metadata 370 * instance. The provider JWK set should be specified by 371 * {@code jwks_uri}, {@code signed_jwks_uri} or {@code jwks}. 372 * 373 * @param issuer The issuer identifier. Must be a URI 374 * using the https scheme with no query 375 * or fragment component. Must not be 376 * {@code null}. 377 * @param subjectTypes The supported subject types. At least 378 * one must be specified. Must not be 379 * {@code null}. 380 * @param clientRegistrationTypes The supported client registration 381 * types. At least one must be 382 * specified. Must not be {@code null}. 383 * @param jwkSetURI The JWK set URI, {@code null} if 384 * specified by another field. 385 * @param signedJWKSetURI The signed JWK set URI, {@code null} 386 * if specified by another field. 387 * @param jwkSet the JWK set, {@code null} if 388 * specified by another field. 389 */ 390 public OIDCProviderMetadata(final Issuer issuer, 391 final List<SubjectType> subjectTypes, 392 final List<ClientRegistrationType> clientRegistrationTypes, 393 final URI jwkSetURI, 394 final URI signedJWKSetURI, 395 final JWKSet jwkSet) { 396 397 super(issuer); 398 399 ensureAtLeastOneSubjectType(subjectTypes); 400 this.subjectTypes = subjectTypes; 401 402 if (clientRegistrationTypes.size() < 1) { 403 throw new IllegalArgumentException("At least one federation client registration type must be specified"); 404 } 405 setClientRegistrationTypes(clientRegistrationTypes); 406 407 if (jwkSetURI == null && signedJWKSetURI == null && jwkSet == null) { 408 throw new IllegalArgumentException("At least one public JWK must be specified"); 409 } 410 411 setJWKSetURI(jwkSetURI); 412 setSignedJWKSetURI(signedJWKSetURI); 413 setJWKSet(jwkSet); 414 415 // Default OpenID Connect setting is supported 416 setSupportsRequestURIParam(true); 417 } 418 419 420 private void ensureAtLeastOneSubjectType(final List<SubjectType> subjectTypes) { 421 if (subjectTypes.size() < 1) 422 throw new IllegalArgumentException("At least one supported subject type must be specified"); 423 } 424 425 426 @Override 427 public void setMtlsEndpointAliases(AuthorizationServerEndpointMetadata mtlsEndpointAliases) { 428 if (mtlsEndpointAliases != null && !(mtlsEndpointAliases instanceof OIDCProviderEndpointMetadata)) { 429 // convert the provided endpoints to OIDC 430 super.setMtlsEndpointAliases(new OIDCProviderEndpointMetadata(mtlsEndpointAliases)); 431 } else { 432 super.setMtlsEndpointAliases(mtlsEndpointAliases); 433 } 434 } 435 436 437 @Override 438 public OIDCProviderEndpointMetadata getReadOnlyMtlsEndpointAliases() { 439 return getMtlsEndpointAliases(); 440 } 441 442 443 @Override 444 public OIDCProviderEndpointMetadata getMtlsEndpointAliases() { 445 return (OIDCProviderEndpointMetadata) super.getMtlsEndpointAliases(); 446 } 447 448 449 /** 450 * Gets the registered OpenID Connect provider metadata parameter 451 * names. 452 * 453 * @return The registered OpenID Connect provider metadata parameter 454 * names, as an unmodifiable set. 455 */ 456 public static Set<String> getRegisteredParameterNames() { 457 return REGISTERED_PARAMETER_NAMES; 458 } 459 460 461 @Override 462 public URI getUserInfoEndpointURI() { 463 return userInfoEndpoint; 464 } 465 466 467 /** 468 * Sets the UserInfo endpoint URI. Corresponds the 469 * {@code userinfo_endpoint} metadata field. 470 * 471 * @param userInfoEndpoint The UserInfo endpoint URI, {@code null} if 472 * not specified. 473 */ 474 public void setUserInfoEndpointURI(final URI userInfoEndpoint) { 475 this.userInfoEndpoint = userInfoEndpoint; 476 } 477 478 479 @Override 480 public URI getCheckSessionIframeURI() { 481 return checkSessionIframe; 482 } 483 484 485 /** 486 * Sets the cross-origin check session iframe URI. Corresponds to the 487 * {@code check_session_iframe} metadata field. 488 * 489 * @param checkSessionIframe The check session iframe URI, {@code null} 490 * if not specified. 491 */ 492 public void setCheckSessionIframeURI(final URI checkSessionIframe) { 493 this.checkSessionIframe = checkSessionIframe; 494 } 495 496 497 @Override 498 public URI getEndSessionEndpointURI() { 499 return endSessionEndpoint; 500 } 501 502 503 /** 504 * Sets the logout endpoint URI. Corresponds to the 505 * {@code end_session_endpoint} metadata field. 506 * 507 * @param endSessionEndpoint The logoout endpoint URI, {@code null} if 508 * not specified. 509 */ 510 public void setEndSessionEndpointURI(final URI endSessionEndpoint) { 511 this.endSessionEndpoint = endSessionEndpoint; 512 } 513 514 @Override 515 public List<ACR> getACRs() { 516 return acrValues; 517 } 518 519 520 /** 521 * Sets the supported Authentication Context Class References (ACRs). 522 * Corresponds to the {@code acr_values_supported} metadata field. 523 * 524 * @param acrValues The supported ACRs, {@code null} if not specified. 525 */ 526 public void setACRs(final List<ACR> acrValues) { 527 this.acrValues = acrValues; 528 } 529 530 531 @Override 532 public List<SubjectType> getSubjectTypes() { 533 return subjectTypes; 534 } 535 536 537 @Override 538 public List<JWSAlgorithm> getIDTokenJWSAlgs() { 539 return idTokenJWSAlgs; 540 } 541 542 543 /** 544 * Sets the supported JWS algorithms for ID tokens. Corresponds to the 545 * {@code id_token_signing_alg_values_supported} metadata field. 546 * 547 * @param idTokenJWSAlgs The supported JWS algorithms, {@code null} if 548 * not specified. 549 */ 550 public void setIDTokenJWSAlgs(final List<JWSAlgorithm> idTokenJWSAlgs) { 551 this.idTokenJWSAlgs = idTokenJWSAlgs; 552 } 553 554 555 @Override 556 public List<JWEAlgorithm> getIDTokenJWEAlgs() { 557 return idTokenJWEAlgs; 558 } 559 560 561 /** 562 * Sets the supported JWE algorithms for ID tokens. Corresponds to the 563 * {@code id_token_encryption_alg_values_supported} metadata field. 564 * 565 * @param idTokenJWEAlgs The supported JWE algorithms, {@code null} if 566 * not specified. 567 */ 568 public void setIDTokenJWEAlgs(final List<JWEAlgorithm> idTokenJWEAlgs) { 569 this.idTokenJWEAlgs = idTokenJWEAlgs; 570 } 571 572 573 @Override 574 public List<EncryptionMethod> getIDTokenJWEEncs() { 575 return idTokenJWEEncs; 576 } 577 578 579 /** 580 * Sets the supported encryption methods for ID tokens. Corresponds to 581 * the {@code id_token_encryption_enc_values_supported} metadata field. 582 * 583 * @param idTokenJWEEncs The supported encryption methods, {@code null} 584 * if not specified. 585 */ 586 public void setIDTokenJWEEncs(final List<EncryptionMethod> idTokenJWEEncs) { 587 this.idTokenJWEEncs = idTokenJWEEncs; 588 } 589 590 591 @Override 592 public List<JWSAlgorithm> getUserInfoJWSAlgs() { 593 return userInfoJWSAlgs; 594 } 595 596 597 /** 598 * Sets the supported JWS algorithms for UserInfo JWTs. Corresponds to 599 * the {@code userinfo_signing_alg_values_supported} metadata field. 600 * 601 * @param userInfoJWSAlgs The supported JWS algorithms, {@code null} if 602 * not specified. 603 */ 604 public void setUserInfoJWSAlgs(final List<JWSAlgorithm> userInfoJWSAlgs) { 605 this.userInfoJWSAlgs = userInfoJWSAlgs; 606 } 607 608 609 @Override 610 public List<JWEAlgorithm> getUserInfoJWEAlgs() { 611 return userInfoJWEAlgs; 612 } 613 614 615 /** 616 * Sets the supported JWE algorithms for UserInfo JWTs. Corresponds to 617 * the {@code userinfo_encryption_alg_values_supported} metadata field. 618 * 619 * @param userInfoJWEAlgs The supported JWE algorithms, {@code null} if 620 * not specified. 621 */ 622 public void setUserInfoJWEAlgs(final List<JWEAlgorithm> userInfoJWEAlgs) { 623 this.userInfoJWEAlgs = userInfoJWEAlgs; 624 } 625 626 627 @Override 628 public List<EncryptionMethod> getUserInfoJWEEncs() { 629 return userInfoJWEEncs; 630 } 631 632 633 /** 634 * Sets the supported encryption methods for UserInfo JWTs. Corresponds 635 * to the {@code userinfo_encryption_enc_values_supported} metadata 636 * field. 637 * 638 * @param userInfoJWEEncs The supported encryption methods, 639 * {@code null} if not specified. 640 */ 641 public void setUserInfoJWEEncs(final List<EncryptionMethod> userInfoJWEEncs) { 642 this.userInfoJWEEncs = userInfoJWEEncs; 643 } 644 645 646 @Override 647 public List<Display> getDisplays() { 648 return displays; 649 } 650 651 652 /** 653 * Sets the supported displays. Corresponds to the 654 * {@code display_values_supported} metadata field. 655 * 656 * @param displays The supported displays, {@code null} if not 657 * specified. 658 */ 659 public void setDisplays(final List<Display> displays) { 660 this.displays = displays; 661 } 662 663 664 @Override 665 public List<ClaimType> getClaimTypes() { 666 return claimTypes; 667 } 668 669 670 /** 671 * Sets the supported claim types. Corresponds to the 672 * {@code claim_types_supported} metadata field. 673 * 674 * @param claimTypes The supported claim types, {@code null} if not 675 * specified. 676 */ 677 public void setClaimTypes(final List<ClaimType> claimTypes) { 678 this.claimTypes = claimTypes; 679 } 680 681 682 @Override 683 public List<String> getClaims() { 684 return claims; 685 } 686 687 688 /** 689 * Sets the supported claims names. Corresponds to the 690 * {@code claims_supported} metadata field. 691 * 692 * @param claims The supported claims names, {@code null} if not 693 * specified. 694 */ 695 public void setClaims(final List<String> claims) { 696 this.claims = claims; 697 } 698 699 700 @Override 701 public List<LangTag> getClaimsLocales() { 702 return claimsLocales; 703 } 704 705 706 /** 707 * Sets the supported claims locales. Corresponds to the 708 * {@code claims_locales_supported} metadata field. 709 * 710 * @param claimsLocales The supported claims locales, {@code null} if 711 * not specified. 712 */ 713 public void setClaimLocales(final List<LangTag> claimsLocales) { 714 this.claimsLocales = claimsLocales; 715 } 716 717 718 @Override 719 public boolean supportsClaimsParam() { 720 return claimsParamSupported; 721 } 722 723 724 /** 725 * Sets the support for the {@code claims} authorisation request 726 * parameter. Corresponds to the {@code claims_parameter_supported} 727 * metadata field. 728 * 729 * @param claimsParamSupported {@code true} if the {@code claim} 730 * parameter is supported, else 731 * {@code false}. 732 */ 733 public void setSupportsClaimsParams(final boolean claimsParamSupported) { 734 this.claimsParamSupported = claimsParamSupported; 735 } 736 737 738 @Override 739 public boolean supportsFrontChannelLogout() { 740 return frontChannelLogoutSupported; 741 } 742 743 744 /** 745 * Sets the support for front-channel logout. Corresponds to the 746 * {@code frontchannel_logout_supported} metadata field. 747 * 748 * @param frontChannelLogoutSupported {@code true} if front-channel 749 * logout is supported, else 750 * {@code false}. 751 */ 752 public void setSupportsFrontChannelLogout(final boolean frontChannelLogoutSupported) { 753 this.frontChannelLogoutSupported = frontChannelLogoutSupported; 754 } 755 756 757 @Override 758 public boolean supportsFrontChannelLogoutSession() { 759 return frontChannelLogoutSessionSupported; 760 } 761 762 763 /** 764 * Sets the support for front-channel logout with a session ID. 765 * Corresponds to the {@code frontchannel_logout_session_supported} 766 * metadata field. 767 * 768 * @param frontChannelLogoutSessionSupported {@code true} if 769 * front-channel logout with 770 * a session ID is supported, 771 * else {@code false}. 772 */ 773 public void setSupportsFrontChannelLogoutSession(final boolean frontChannelLogoutSessionSupported) { 774 this.frontChannelLogoutSessionSupported = frontChannelLogoutSessionSupported; 775 } 776 777 778 @Override 779 public boolean supportsBackChannelLogout() { 780 return backChannelLogoutSupported; 781 } 782 783 784 /** 785 * Sets the support for back-channel logout. Corresponds to the 786 * {@code backchannel_logout_supported} metadata field. 787 * 788 * @param backChannelLogoutSupported {@code true} if back-channel 789 * logout is supported, else 790 * {@code false}. 791 */ 792 public void setSupportsBackChannelLogout(final boolean backChannelLogoutSupported) { 793 this.backChannelLogoutSupported = backChannelLogoutSupported; 794 } 795 796 797 @Override 798 public boolean supportsBackChannelLogoutSession() { 799 return backChannelLogoutSessionSupported; 800 } 801 802 803 /** 804 * Sets the support for back-channel logout with a session ID. 805 * Corresponds to the {@code backchannel_logout_session_supported} 806 * metadata field. 807 * 808 * @param backChannelLogoutSessionSupported {@code true} if 809 * back-channel logout with a 810 * session ID is supported, 811 * else {@code false}. 812 */ 813 public void setSupportsBackChannelLogoutSession(final boolean backChannelLogoutSessionSupported) { 814 this.backChannelLogoutSessionSupported = backChannelLogoutSessionSupported; 815 } 816 817 818 @Override 819 public boolean supportsNativeSSO() { 820 return nativeSSOSupported; 821 } 822 823 824 /** 825 * Sets the support for OpenID Connect native SSO. Corresponds to the 826 * {@code native_sso_supported} metadata field. 827 * 828 * @param nativeSSOSupported {@code true} if native SSO is supported, 829 * else {@code false}. 830 */ 831 public void setSupportsNativeSSO(final boolean nativeSSOSupported) { 832 this.nativeSSOSupported = nativeSSOSupported; 833 } 834 835 836 @Override 837 public boolean supportsVerifiedClaims() { 838 return verifiedClaimsSupported; 839 } 840 841 842 /** 843 * Sets support for verified claims. Corresponds to the 844 * {@code verified_claims_supported} metadata field. 845 * 846 * @param verifiedClaimsSupported {@code true} if verified claims are 847 * supported, else {@code false}. 848 */ 849 public void setSupportsVerifiedClaims(final boolean verifiedClaimsSupported) { 850 this.verifiedClaimsSupported = verifiedClaimsSupported; 851 } 852 853 854 @Override 855 public List<IdentityTrustFramework> getIdentityTrustFrameworks() { 856 return trustFrameworks; 857 } 858 859 860 /** 861 * Sets the supported identity trust frameworks. Corresponds to the 862 * {@code trust_frameworks_supported} metadata field. 863 * 864 * @param trustFrameworks The supported identity trust frameworks, 865 * {@code null} if not specified. 866 */ 867 public void setIdentityTrustFrameworks(final List<IdentityTrustFramework> trustFrameworks) { 868 this.trustFrameworks = trustFrameworks; 869 } 870 871 872 @Override 873 public List<IdentityEvidenceType> getIdentityEvidenceTypes() { 874 return evidenceTypes; 875 } 876 877 878 /** 879 * Sets the supported identity evidence types. Corresponds to the 880 * {@code evidence_supported} metadata field. 881 * 882 * @param evidenceTypes The supported identity evidence types, 883 * {@code null} if not specified. 884 */ 885 public void setIdentityEvidenceTypes(final List<IdentityEvidenceType> evidenceTypes) { 886 this.evidenceTypes = evidenceTypes; 887 } 888 889 890 @Override 891 public List<DocumentType> getDocumentTypes() { 892 return documentTypes; 893 } 894 895 896 /** 897 * Sets the supported identity document types. Corresponds to the 898 * {@code documents_supported} metadata field. 899 * 900 * @param documentTypes The supported identity document types, 901 * {@code null} if not specified. 902 */ 903 public void setDocumentTypes(final List<DocumentType> documentTypes) { 904 this.documentTypes = documentTypes; 905 } 906 907 908 @Override 909 @Deprecated 910 public List<IDDocumentType> getIdentityDocumentTypes() { 911 return idDocumentTypes; 912 } 913 914 915 /** 916 * Sets the supported identity document types. Corresponds to the 917 * {@code id_documents_supported} metadata field. 918 * 919 * @param idDocuments The supported identity document types, 920 * {@code null} if not specified. 921 * 922 * @deprecated Use {@link #setDocumentTypes} instead. 923 */ 924 @Deprecated 925 public void setIdentityDocumentTypes(final List<IDDocumentType> idDocuments) { 926 this.idDocumentTypes = idDocuments; 927 } 928 929 930 @Override 931 public List<IdentityVerificationMethod> getDocumentMethods() { 932 return documentMethods; 933 } 934 935 936 /** 937 * Sets the supported coarse identity verification methods for 938 * evidences of type document. Corresponds to the 939 * {@code documents_methods_supported} metadata field. 940 * 941 * @param methods The supported identity verification methods for 942 * document evidences, {@code null} if not specified. 943 */ 944 public void setDocumentMethods(final List<IdentityVerificationMethod> methods) { 945 this.documentMethods = methods; 946 } 947 948 949 @Override 950 public List<ValidationMethodType> getDocumentValidationMethods() { 951 return documentValidationMethods; 952 } 953 954 955 /** 956 * Sets the supported validation methods for evidences of type 957 * document. Corresponds to the 958 * {@code documents_validation_methods_supported} metadata field. 959 * 960 * @param methods The validation methods for document evidences, 961 * {@code null} if not specified. 962 */ 963 public void setDocumentValidationMethods(final List<ValidationMethodType> methods) { 964 this.documentValidationMethods = methods; 965 } 966 967 968 @Override 969 public List<VerificationMethodType> getDocumentVerificationMethods() { 970 return documentVerificationMethods; 971 } 972 973 974 /** 975 * Sets the supported verification methods for evidences of type 976 * document. Corresponds to the 977 * {@code documents_verification_methods_supported} metadata field. 978 * 979 * @param methods The verification methods for document evidences, 980 * {@code null} if not specified. 981 */ 982 public void setDocumentVerificationMethods(final List<VerificationMethodType> methods) { 983 this.documentVerificationMethods = methods; 984 } 985 986 987 @Override 988 public List<ElectronicRecordType> getElectronicRecordTypes() { 989 return electronicRecordTypes; 990 } 991 992 993 /** 994 * Sets the supported electronic record types. Corresponds to the 995 * {@code electronic_records_supported} metadata field. 996 * 997 * @param electronicRecordTypes The supported electronic record types, 998 * {@code null} if not specified. 999 */ 1000 public void setElectronicRecordTypes(final List<ElectronicRecordType> electronicRecordTypes) { 1001 this.electronicRecordTypes = electronicRecordTypes; 1002 } 1003 1004 1005 @Override 1006 @Deprecated 1007 public List<IdentityVerificationMethod> getIdentityVerificationMethods() { 1008 return idVerificationMethods; 1009 } 1010 1011 1012 /** 1013 * Sets the supported identity verification methods. Corresponds to the 1014 * {@code id_documents_verification_methods_supported} metadata field. 1015 * 1016 * @param idVerificationMethods The supported identity verification 1017 * methods, {@code null} if not specified. 1018 */ 1019 @Deprecated 1020 public void setIdentityVerificationMethods(final List<IdentityVerificationMethod> idVerificationMethods) { 1021 this.idVerificationMethods = idVerificationMethods; 1022 } 1023 1024 1025 @Override 1026 public List<String> getVerifiedClaims() { 1027 return verifiedClaims; 1028 } 1029 1030 1031 /** 1032 * Sets the names of the supported verified claims. Corresponds to the 1033 * {@code claims_in_verified_claims_supported} metadata field. 1034 * 1035 * @param verifiedClaims The supported verified claims names, 1036 * {@code null} if not specified. 1037 */ 1038 public void setVerifiedClaims(final List<String> verifiedClaims) { 1039 this.verifiedClaims = verifiedClaims; 1040 } 1041 1042 1043 @Override 1044 public List<AttachmentType> getAttachmentTypes() { 1045 return attachmentTypes; 1046 } 1047 1048 1049 /** 1050 * Sets the supported evidence attachment types. Corresponds to the 1051 * {@code attachments_supported} metadata field. 1052 * 1053 * @param attachmentTypes The supported evidence attachment types, 1054 * empty if attachments are not supported, 1055 * {@code null} if not specified. 1056 */ 1057 public void setAttachmentTypes(final List<AttachmentType> attachmentTypes) { 1058 this.attachmentTypes = attachmentTypes; 1059 } 1060 1061 1062 @Override 1063 public List<HashAlgorithm> getAttachmentDigestAlgs() { 1064 return attachmentDigestAlgs; 1065 } 1066 1067 1068 /** 1069 * Sets the supported digest algorithms for the external evidence 1070 * attachments. Corresponds to the {@code digest_algorithms_supported} 1071 * metadata field. 1072 * 1073 * @param digestAlgs The supported digest algorithms, {@code null} if 1074 * not specified. 1075 */ 1076 public void setAttachmentDigestAlgs(final List<HashAlgorithm> digestAlgs) { 1077 this.attachmentDigestAlgs = digestAlgs; 1078 } 1079 1080 1081 /** 1082 * Applies the OpenID Provider metadata defaults where no values have 1083 * been specified. 1084 * 1085 * <ul> 1086 * <li>The response modes default to {@code ["query", "fragment"]}. 1087 * <li>The grant types default to {@code ["authorization_code", 1088 * "implicit"]}. 1089 * <li>The token endpoint authentication methods default to 1090 * {@code ["client_secret_basic"]}. 1091 * <li>The claim types default to {@code ["normal]}. 1092 * </ul> 1093 */ 1094 public void applyDefaults() { 1095 1096 super.applyDefaults(); 1097 1098 if (claimTypes == null) { 1099 claimTypes = new ArrayList<>(1); 1100 claimTypes.add(ClaimType.NORMAL); 1101 } 1102 } 1103 1104 1105 @Override 1106 public JSONObject toJSONObject() { 1107 1108 JSONObject o = super.toJSONObject(); 1109 1110 // Mandatory fields 1111 1112 List<String> stringList = new ArrayList<>(subjectTypes.size()); 1113 1114 for (SubjectType st: subjectTypes) 1115 stringList.add(st.toString()); 1116 1117 o.put("subject_types_supported", stringList); 1118 1119 // Optional fields 1120 1121 if (userInfoEndpoint != null) 1122 o.put("userinfo_endpoint", userInfoEndpoint.toString()); 1123 1124 if (checkSessionIframe != null) 1125 o.put("check_session_iframe", checkSessionIframe.toString()); 1126 1127 if (endSessionEndpoint != null) 1128 o.put("end_session_endpoint", endSessionEndpoint.toString()); 1129 1130 if (acrValues != null) { 1131 o.put("acr_values_supported", Identifier.toStringList(acrValues)); 1132 } 1133 1134 if (idTokenJWSAlgs != null) { 1135 1136 stringList = new ArrayList<>(idTokenJWSAlgs.size()); 1137 1138 for (JWSAlgorithm alg: idTokenJWSAlgs) 1139 stringList.add(alg.getName()); 1140 1141 o.put("id_token_signing_alg_values_supported", stringList); 1142 } 1143 1144 if (idTokenJWEAlgs != null) { 1145 1146 stringList = new ArrayList<>(idTokenJWEAlgs.size()); 1147 1148 for (JWEAlgorithm alg: idTokenJWEAlgs) 1149 stringList.add(alg.getName()); 1150 1151 o.put("id_token_encryption_alg_values_supported", stringList); 1152 } 1153 1154 if (idTokenJWEEncs != null) { 1155 1156 stringList = new ArrayList<>(idTokenJWEEncs.size()); 1157 1158 for (EncryptionMethod m: idTokenJWEEncs) 1159 stringList.add(m.getName()); 1160 1161 o.put("id_token_encryption_enc_values_supported", stringList); 1162 } 1163 1164 if (userInfoJWSAlgs != null) { 1165 1166 stringList = new ArrayList<>(userInfoJWSAlgs.size()); 1167 1168 for (JWSAlgorithm alg: userInfoJWSAlgs) 1169 stringList.add(alg.getName()); 1170 1171 o.put("userinfo_signing_alg_values_supported", stringList); 1172 } 1173 1174 if (userInfoJWEAlgs != null) { 1175 1176 stringList = new ArrayList<>(userInfoJWEAlgs.size()); 1177 1178 for (JWEAlgorithm alg: userInfoJWEAlgs) 1179 stringList.add(alg.getName()); 1180 1181 o.put("userinfo_encryption_alg_values_supported", stringList); 1182 } 1183 1184 if (userInfoJWEEncs != null) { 1185 1186 stringList = new ArrayList<>(userInfoJWEEncs.size()); 1187 1188 for (EncryptionMethod m: userInfoJWEEncs) 1189 stringList.add(m.getName()); 1190 1191 o.put("userinfo_encryption_enc_values_supported", stringList); 1192 } 1193 1194 if (displays != null) { 1195 1196 stringList = new ArrayList<>(displays.size()); 1197 1198 for (Display d: displays) 1199 stringList.add(d.toString()); 1200 1201 o.put("display_values_supported", stringList); 1202 } 1203 1204 if (claimTypes != null) { 1205 1206 stringList = new ArrayList<>(claimTypes.size()); 1207 1208 for (ClaimType ct: claimTypes) 1209 stringList.add(ct.toString()); 1210 1211 o.put("claim_types_supported", stringList); 1212 } 1213 1214 if (claims != null) 1215 o.put("claims_supported", claims); 1216 1217 if (claimsLocales != null) { 1218 1219 stringList = new ArrayList<>(claimsLocales.size()); 1220 1221 for (LangTag l: claimsLocales) 1222 stringList.add(l.toString()); 1223 1224 o.put("claims_locales_supported", stringList); 1225 } 1226 1227 if (claimsParamSupported) { 1228 o.put("claims_parameter_supported", true); 1229 } 1230 1231 // Always output, for OP metadata default value is true, for 1232 // AS metadata implied default is false 1233 o.put("request_uri_parameter_supported", supportsRequestURIParam()); 1234 1235 // optional front and back-channel logout 1236 if (frontChannelLogoutSupported) { 1237 o.put("frontchannel_logout_supported", true); 1238 } 1239 1240 if (frontChannelLogoutSupported) { 1241 o.put("frontchannel_logout_session_supported", frontChannelLogoutSessionSupported); 1242 } 1243 1244 if (backChannelLogoutSupported) { 1245 o.put("backchannel_logout_supported", true); 1246 } 1247 1248 if (backChannelLogoutSupported) { 1249 o.put("backchannel_logout_session_supported", backChannelLogoutSessionSupported); 1250 } 1251 1252 if (nativeSSOSupported) { 1253 o.put("native_sso_supported", true); 1254 } 1255 1256 // OpenID Connect for Identity Assurance 1.0 1257 if (verifiedClaimsSupported) { 1258 o.put("verified_claims_supported", true); 1259 if (trustFrameworks != null) { 1260 o.put("trust_frameworks_supported", Identifier.toStringList(trustFrameworks)); 1261 } 1262 if (evidenceTypes != null) { 1263 o.put("evidence_supported", Identifier.toStringList(evidenceTypes)); 1264 } 1265 if ( 1266 (CollectionUtils.contains(evidenceTypes, IdentityEvidenceType.DOCUMENT) || CollectionUtils.contains(evidenceTypes, IdentityEvidenceType.ID_DOCUMENT)) 1267 && documentTypes != null) { 1268 1269 o.put("documents_supported", Identifier.toStringList(documentTypes)); 1270 1271 // TODO await resolution of 1272 // https://bitbucket.org/openid/ekyc-ida/issues/1275/clarification-regarding-op-metadata 1273 if (documentMethods != null) { 1274 o.put("documents_methods_supported", Identifier.toStringList(documentMethods)); 1275 } 1276 if (documentValidationMethods != null) { 1277 o.put("documents_validation_methods_supported", Identifier.toStringList(documentValidationMethods)); 1278 } 1279 if (documentVerificationMethods != null) { 1280 o.put("documents_verification_methods_supported", Identifier.toStringList(documentVerificationMethods)); 1281 } 1282 } 1283 if (idDocumentTypes != null) { 1284 // deprecated 1285 o.put("id_documents_supported", Identifier.toStringList(idDocumentTypes)); 1286 } 1287 if (idVerificationMethods != null) { 1288 // deprecated 1289 o.put("id_documents_verification_methods_supported", Identifier.toStringList(idVerificationMethods)); 1290 } 1291 if (electronicRecordTypes != null) { 1292 o.put("electronic_records_supported", Identifier.toStringList(electronicRecordTypes)); 1293 } 1294 if (verifiedClaims != null) { 1295 o.put("claims_in_verified_claims_supported", verifiedClaims); 1296 } 1297 if (attachmentTypes != null) { 1298 List<String> strings = new LinkedList<>(); 1299 for (AttachmentType type: attachmentTypes) { 1300 strings.add(type.toString()); 1301 } 1302 o.put("attachments_supported", strings); 1303 1304 if (attachmentTypes.contains(AttachmentType.EXTERNAL) && attachmentDigestAlgs != null) { 1305 o.put("digest_algorithms_supported", Identifier.toStringList(attachmentDigestAlgs)); 1306 } 1307 } 1308 } 1309 1310 return o; 1311 } 1312 1313 1314 /** 1315 * Parses an OpenID Provider metadata from the specified JSON object. 1316 * 1317 * @param jsonObject The JSON object to parse. Must not be 1318 * {@code null}. 1319 * 1320 * @return The OpenID Provider metadata. 1321 * 1322 * @throws ParseException If the JSON object couldn't be parsed to an 1323 * OpenID Provider metadata. 1324 */ 1325 public static OIDCProviderMetadata parse(final JSONObject jsonObject) 1326 throws ParseException { 1327 1328 AuthorizationServerMetadata as = AuthorizationServerMetadata.parse(jsonObject); 1329 1330 List<SubjectType> subjectTypes = new ArrayList<>(); 1331 for (String v: JSONObjectUtils.getStringArray(jsonObject, "subject_types_supported")) { 1332 subjectTypes.add(SubjectType.parse(v)); 1333 } 1334 1335 OIDCProviderMetadata op; 1336 if (jsonObject.get("client_registration_types_supported") != null) { 1337 // OIDC Federation 1.0 constructor 1338 List<ClientRegistrationType> clientRegistrationTypes = new LinkedList<>(); 1339 for (String v: JSONObjectUtils.getStringList(jsonObject, "client_registration_types_supported")) { 1340 clientRegistrationTypes.add(new ClientRegistrationType(v)); 1341 } 1342 try { 1343 JWKSet jwkSet = null; 1344 if (jsonObject.get("jwks") != null) { 1345 jwkSet = JWKSet.parse(JSONObjectUtils.getJSONObject(jsonObject, "jwks")); 1346 } 1347 1348 op = new OIDCProviderMetadata( 1349 as.getIssuer(), 1350 Collections.unmodifiableList(subjectTypes), 1351 clientRegistrationTypes, 1352 as.getJWKSetURI(), 1353 JSONObjectUtils.getURI(jsonObject, "signed_jwks_uri", null), 1354 jwkSet); 1355 } catch (java.text.ParseException | IllegalArgumentException e) { 1356 throw new ParseException(e.getMessage(), e); 1357 } 1358 } else { 1359 // Regular constructor 1360 op = new OIDCProviderMetadata( 1361 as.getIssuer(), 1362 Collections.unmodifiableList(subjectTypes), 1363 as.getJWKSetURI()); 1364 } 1365 1366 1367 // Endpoints 1368 op.setAuthorizationEndpointURI(as.getAuthorizationEndpointURI()); 1369 op.setTokenEndpointURI(as.getTokenEndpointURI()); 1370 op.setRegistrationEndpointURI(as.getRegistrationEndpointURI()); 1371 op.setIntrospectionEndpointURI(as.getIntrospectionEndpointURI()); 1372 op.setRevocationEndpointURI(as.getRevocationEndpointURI()); 1373 op.setRequestObjectEndpoint(as.getRequestObjectEndpoint()); 1374 op.setPushedAuthorizationRequestEndpointURI(as.getPushedAuthorizationRequestEndpointURI()); 1375 op.setDeviceAuthorizationEndpointURI(as.getDeviceAuthorizationEndpointURI()); 1376 op.userInfoEndpoint = JSONObjectUtils.getURI(jsonObject, "userinfo_endpoint", null); 1377 op.checkSessionIframe = JSONObjectUtils.getURI(jsonObject, "check_session_iframe", null); 1378 op.endSessionEndpoint = JSONObjectUtils.getURI(jsonObject, "end_session_endpoint", null); 1379 1380 // Capabilities 1381 op.setScopes(as.getScopes()); 1382 op.setResponseTypes(as.getResponseTypes()); 1383 op.setResponseModes(as.getResponseModes()); 1384 op.setGrantTypes(as.getGrantTypes()); 1385 1386 op.setTokenEndpointAuthMethods(as.getTokenEndpointAuthMethods()); 1387 op.setTokenEndpointJWSAlgs(as.getTokenEndpointJWSAlgs()); 1388 1389 op.setIntrospectionEndpointAuthMethods(as.getIntrospectionEndpointAuthMethods()); 1390 op.setIntrospectionEndpointJWSAlgs(as.getIntrospectionEndpointJWSAlgs()); 1391 1392 op.setRevocationEndpointAuthMethods(as.getRevocationEndpointAuthMethods()); 1393 op.setRevocationEndpointJWSAlgs(as.getRevocationEndpointJWSAlgs()); 1394 1395 op.setRequestObjectJWSAlgs(as.getRequestObjectJWSAlgs()); 1396 op.setRequestObjectJWEAlgs(as.getRequestObjectJWEAlgs()); 1397 op.setRequestObjectJWEEncs(as.getRequestObjectJWEEncs()); 1398 1399 op.setSupportsRequestParam(as.supportsRequestParam()); 1400 op.setSupportsRequestURIParam(as.supportsRequestURIParam()); 1401 op.setRequiresRequestURIRegistration(as.requiresRequestURIRegistration()); 1402 1403 op.requiresPushedAuthorizationRequests(as.requiresPushedAuthorizationRequests()); 1404 1405 op.setSupportsAuthorizationResponseIssuerParam(as.supportsAuthorizationResponseIssuerParam()); 1406 1407 op.setCodeChallengeMethods(as.getCodeChallengeMethods()); 1408 1409 1410 op.setBackChannelAuthenticationEndpointURI(as.getBackChannelAuthenticationEndpointURI()); 1411 op.setBackChannelAuthenticationRequestJWSAlgs(as.getBackChannelAuthenticationRequestJWSAlgs()); 1412 op.setSupportsBackChannelUserCodeParam(as.supportsBackChannelUserCodeParam()); 1413 op.setBackChannelTokenDeliveryModes(as.getBackChannelTokenDeliveryModes()); 1414 1415 op.setPromptTypes(as.getPromptTypes()); 1416 1417 op.setOrganizationName(as.getOrganizationName()); 1418 op.setJWKSet(as.getJWKSet()); 1419 op.setSignedJWKSetURI(as.getSignedJWKSetURI()); 1420 op.setClientRegistrationTypes(as.getClientRegistrationTypes()); 1421 op.setClientRegistrationAuthnMethods(as.getClientRegistrationAuthnMethods()); 1422 op.setClientRegistrationAuthnJWSAlgs(as.getClientRegistrationAuthnJWSAlgs()); 1423 op.setFederationRegistrationEndpointURI(as.getFederationRegistrationEndpointURI()); 1424 1425 if (jsonObject.get("acr_values_supported") != null) { 1426 1427 op.acrValues = new ArrayList<>(); 1428 1429 for (String v: JSONObjectUtils.getStringArray(jsonObject, "acr_values_supported")) { 1430 1431 if (v != null) 1432 op.acrValues.add(new ACR(v)); 1433 } 1434 } 1435 1436 // ID token 1437 1438 if (jsonObject.get("id_token_signing_alg_values_supported") != null) { 1439 1440 op.idTokenJWSAlgs = new ArrayList<>(); 1441 1442 for (String v: JSONObjectUtils.getStringArray(jsonObject, "id_token_signing_alg_values_supported")) { 1443 1444 if (v != null) 1445 op.idTokenJWSAlgs.add(JWSAlgorithm.parse(v)); 1446 } 1447 } 1448 1449 1450 if (jsonObject.get("id_token_encryption_alg_values_supported") != null) { 1451 1452 op.idTokenJWEAlgs = new ArrayList<>(); 1453 1454 for (String v: JSONObjectUtils.getStringArray(jsonObject, "id_token_encryption_alg_values_supported")) { 1455 1456 if (v != null) 1457 op.idTokenJWEAlgs.add(JWEAlgorithm.parse(v)); 1458 } 1459 } 1460 1461 1462 if (jsonObject.get("id_token_encryption_enc_values_supported") != null) { 1463 1464 op.idTokenJWEEncs = new ArrayList<>(); 1465 1466 for (String v: JSONObjectUtils.getStringArray(jsonObject, "id_token_encryption_enc_values_supported")) { 1467 1468 if (v != null) 1469 op.idTokenJWEEncs.add(EncryptionMethod.parse(v)); 1470 } 1471 } 1472 1473 // UserInfo 1474 1475 if (jsonObject.get("userinfo_signing_alg_values_supported") != null) { 1476 1477 op.userInfoJWSAlgs = new ArrayList<>(); 1478 1479 for (String v: JSONObjectUtils.getStringArray(jsonObject, "userinfo_signing_alg_values_supported")) { 1480 1481 if (v != null) 1482 op.userInfoJWSAlgs.add(JWSAlgorithm.parse(v)); 1483 } 1484 } 1485 1486 1487 if (jsonObject.get("userinfo_encryption_alg_values_supported") != null) { 1488 1489 op.userInfoJWEAlgs = new ArrayList<>(); 1490 1491 for (String v: JSONObjectUtils.getStringArray(jsonObject, "userinfo_encryption_alg_values_supported")) { 1492 1493 if (v != null) 1494 op.userInfoJWEAlgs.add(JWEAlgorithm.parse(v)); 1495 } 1496 } 1497 1498 1499 if (jsonObject.get("userinfo_encryption_enc_values_supported") != null) { 1500 1501 op.userInfoJWEEncs = new ArrayList<>(); 1502 1503 for (String v: JSONObjectUtils.getStringArray(jsonObject, "userinfo_encryption_enc_values_supported")) { 1504 1505 if (v != null) 1506 op.userInfoJWEEncs.add(EncryptionMethod.parse(v)); 1507 } 1508 } 1509 1510 1511 // Misc 1512 1513 if (jsonObject.get("display_values_supported") != null) { 1514 1515 op.displays = new ArrayList<>(); 1516 1517 for (String v: JSONObjectUtils.getStringArray(jsonObject, "display_values_supported")) { 1518 1519 if (v != null) 1520 op.displays.add(Display.parse(v)); 1521 } 1522 } 1523 1524 if (jsonObject.get("claim_types_supported") != null) { 1525 1526 op.claimTypes = new ArrayList<>(); 1527 1528 for (String v: JSONObjectUtils.getStringArray(jsonObject, "claim_types_supported")) { 1529 1530 if (v != null) 1531 op.claimTypes.add(ClaimType.parse(v)); 1532 } 1533 } 1534 1535 1536 if (jsonObject.get("claims_supported") != null) { 1537 1538 op.claims = new ArrayList<>(); 1539 1540 for (String v: JSONObjectUtils.getStringArray(jsonObject, "claims_supported")) { 1541 1542 if (v != null) 1543 op.claims.add(v); 1544 } 1545 } 1546 1547 if (jsonObject.get("claims_locales_supported") != null) { 1548 1549 op.claimsLocales = new ArrayList<>(); 1550 1551 for (String v : JSONObjectUtils.getStringArray(jsonObject, "claims_locales_supported")) { 1552 1553 if (v != null) { 1554 1555 try { 1556 op.claimsLocales.add(LangTag.parse(v)); 1557 1558 } catch (LangTagException e) { 1559 1560 throw new ParseException("Invalid claims_locales_supported field: " + e.getMessage(), e); 1561 } 1562 } 1563 } 1564 } 1565 1566 op.setUILocales(as.getUILocales()); 1567 op.setServiceDocsURI(as.getServiceDocsURI()); 1568 op.setPolicyURI(as.getPolicyURI()); 1569 op.setTermsOfServiceURI(as.getTermsOfServiceURI()); 1570 1571 if (jsonObject.get("claims_parameter_supported") != null) 1572 op.claimsParamSupported = JSONObjectUtils.getBoolean(jsonObject, "claims_parameter_supported"); 1573 1574 if (jsonObject.get("request_uri_parameter_supported") == null) { 1575 op.setSupportsRequestURIParam(true); 1576 } 1577 1578 // Optional front and back-channel logout 1579 if (jsonObject.get("frontchannel_logout_supported") != null) 1580 op.frontChannelLogoutSupported = JSONObjectUtils.getBoolean(jsonObject, "frontchannel_logout_supported"); 1581 1582 if (op.frontChannelLogoutSupported && jsonObject.get("frontchannel_logout_session_supported") != null) 1583 op.frontChannelLogoutSessionSupported = JSONObjectUtils.getBoolean(jsonObject, "frontchannel_logout_session_supported"); 1584 1585 if (jsonObject.get("backchannel_logout_supported") != null) 1586 op.backChannelLogoutSupported = JSONObjectUtils.getBoolean(jsonObject, "backchannel_logout_supported"); 1587 1588 if (op.backChannelLogoutSupported && jsonObject.get("backchannel_logout_session_supported") != null) 1589 op.backChannelLogoutSessionSupported = JSONObjectUtils.getBoolean(jsonObject, "backchannel_logout_session_supported"); 1590 1591 // Native SSO 1592 if (jsonObject.get("native_sso_supported") != null) 1593 op.setSupportsNativeSSO(JSONObjectUtils.getBoolean(jsonObject, "native_sso_supported")); 1594 1595 if (jsonObject.get("mtls_endpoint_aliases") != null) 1596 op.setMtlsEndpointAliases(OIDCProviderEndpointMetadata.parse(JSONObjectUtils.getJSONObject(jsonObject, "mtls_endpoint_aliases"))); 1597 1598 op.setSupportsTLSClientCertificateBoundAccessTokens(as.supportsTLSClientCertificateBoundAccessTokens()); 1599 1600 // DPoP 1601 op.setDPoPJWSAlgs(as.getDPoPJWSAlgs()); 1602 1603 // JARM 1604 op.setAuthorizationJWSAlgs(as.getAuthorizationJWSAlgs()); 1605 op.setAuthorizationJWEAlgs(as.getAuthorizationJWEAlgs()); 1606 op.setAuthorizationJWEEncs(as.getAuthorizationJWEEncs()); 1607 1608 // RAR 1609 op.setAuthorizationDetailsTypes(as.getAuthorizationDetailsTypes()); 1610 1611 // Incremental authz 1612 op.setIncrementalAuthorizationTypes(as.getIncrementalAuthorizationTypes()); 1613 1614 // OpenID Connect for Identity Assurance 1.0 1615 if (jsonObject.get("verified_claims_supported") != null) { 1616 op.verifiedClaimsSupported = JSONObjectUtils.getBoolean(jsonObject, "verified_claims_supported"); 1617 if (op.verifiedClaimsSupported) { 1618 if (jsonObject.get("trust_frameworks_supported") != null) { 1619 op.trustFrameworks = new LinkedList<>(); 1620 for (String v : JSONObjectUtils.getStringList(jsonObject, "trust_frameworks_supported")) { 1621 op.trustFrameworks.add(new IdentityTrustFramework(v)); 1622 } 1623 } 1624 if (jsonObject.get("evidence_supported") != null) { 1625 op.evidenceTypes = new LinkedList<>(); 1626 for (String v: JSONObjectUtils.getStringList(jsonObject, "evidence_supported")) { 1627 op.evidenceTypes.add(new IdentityEvidenceType(v)); 1628 } 1629 } 1630 1631 if ( 1632 (CollectionUtils.contains(op.evidenceTypes, IdentityEvidenceType.DOCUMENT) || CollectionUtils.contains(op.evidenceTypes, IdentityEvidenceType.ID_DOCUMENT)) 1633 && jsonObject.get("documents_supported") != null) { 1634 1635 op.documentTypes = new LinkedList<>(); 1636 for (String v: JSONObjectUtils.getStringList(jsonObject, "documents_supported")) { 1637 op.documentTypes.add(new DocumentType(v)); 1638 } 1639 1640 // TODO await resolution of 1641 // https://bitbucket.org/openid/ekyc-ida/issues/1275/clarification-regarding-op-metadata 1642 if (jsonObject.get("documents_methods_supported") != null) { 1643 op.documentMethods = new LinkedList<>(); 1644 for (String v: JSONObjectUtils.getStringList(jsonObject, "documents_methods_supported")) { 1645 op.documentMethods.add(new IdentityVerificationMethod(v)); 1646 } 1647 } 1648 1649 if (jsonObject.get("documents_validation_methods_supported") != null) { 1650 op.documentValidationMethods = new LinkedList<>(); 1651 for (String v: JSONObjectUtils.getStringList(jsonObject, "documents_validation_methods_supported")) { 1652 op.documentValidationMethods.add(new ValidationMethodType(v)); 1653 } 1654 } 1655 1656 if (jsonObject.get("documents_verification_methods_supported") != null) { 1657 op.documentVerificationMethods = new LinkedList<>(); 1658 for (String v: JSONObjectUtils.getStringList(jsonObject, "documents_verification_methods_supported")) { 1659 op.documentVerificationMethods.add(new VerificationMethodType(v)); 1660 } 1661 } 1662 } 1663 1664 if (jsonObject.get("id_documents_supported") != null) { 1665 // deprecated 1666 op.idDocumentTypes = new LinkedList<>(); 1667 for (String v: JSONObjectUtils.getStringList(jsonObject, "id_documents_supported")) { 1668 op.idDocumentTypes.add(new IDDocumentType(v)); 1669 } 1670 } 1671 if (jsonObject.get("id_documents_verification_methods_supported") != null) { 1672 // deprecated 1673 op.idVerificationMethods = new LinkedList<>(); 1674 for (String v: JSONObjectUtils.getStringList(jsonObject, "id_documents_verification_methods_supported")) { 1675 op.idVerificationMethods.add(new IdentityVerificationMethod(v)); 1676 } 1677 } 1678 if (jsonObject.get("electronic_records_supported") != null) { 1679 op.electronicRecordTypes = new LinkedList<>(); 1680 for (String v: JSONObjectUtils.getStringList(jsonObject, "electronic_records_supported")) { 1681 op.electronicRecordTypes.add(new ElectronicRecordType(v)); 1682 } 1683 } 1684 if (jsonObject.get("claims_in_verified_claims_supported") != null) { 1685 op.verifiedClaims = JSONObjectUtils.getStringList(jsonObject, "claims_in_verified_claims_supported"); 1686 } 1687 if (jsonObject.get("attachments_supported") != null) { 1688 op.attachmentTypes = new LinkedList<>(); 1689 for (String v: JSONObjectUtils.getStringList(jsonObject, "attachments_supported")) { 1690 op.attachmentTypes.add(AttachmentType.parse(v)); 1691 } 1692 1693 if (op.attachmentTypes.contains(AttachmentType.EXTERNAL) && jsonObject.get("digest_algorithms_supported") != null) { 1694 op.attachmentDigestAlgs = new LinkedList<>(); 1695 for (String v: JSONObjectUtils.getStringList(jsonObject, "digest_algorithms_supported")) { 1696 op.attachmentDigestAlgs.add(new HashAlgorithm(v)); 1697 } 1698 } 1699 } 1700 } 1701 } 1702 1703 // Parse custom (not registered) parameters 1704 for (Map.Entry<String,?> entry: as.getCustomParameters().entrySet()) { 1705 if (REGISTERED_PARAMETER_NAMES.contains(entry.getKey())) 1706 continue; // skip 1707 op.setCustomParameter(entry.getKey(), entry.getValue()); 1708 } 1709 1710 return op; 1711 } 1712 1713 1714 /** 1715 * Parses an OpenID Provider metadata from the specified JSON object 1716 * string. 1717 * 1718 * @param s The JSON object sting to parse. Must not be {@code null}. 1719 * 1720 * @return The OpenID Provider metadata. 1721 * 1722 * @throws ParseException If the JSON object string couldn't be parsed 1723 * to an OpenID Provider metadata. 1724 */ 1725 public static OIDCProviderMetadata parse(final String s) 1726 throws ParseException { 1727 1728 return parse(JSONObjectUtils.parse(s)); 1729 } 1730 1731 1732 /** 1733 * Resolves the OpenID Provider metadata URL for the specified issuer. 1734 * 1735 * @param issuer The issuer. Must represent a valid HTTPS or HTTP URL. 1736 * Must not be {@code null}. 1737 * 1738 * @return The OpenID Provider metadata URL. 1739 * 1740 * @throws GeneralException If the issuer is invalid. 1741 */ 1742 public static URL resolveURL(final Issuer issuer) 1743 throws GeneralException { 1744 1745 try { 1746 URL issuerURL = new URL(issuer.getValue()); 1747 1748 // Validate but don't insist on HTTPS, see 1749 // http://openid.net/specs/openid-connect-core-1_0.html#Terminology 1750 if (issuerURL.getQuery() != null && ! issuerURL.getQuery().trim().isEmpty()) { 1751 throw new GeneralException("The issuer must not contain a query component"); 1752 } 1753 1754 if (issuerURL.getPath() != null && issuerURL.getPath().endsWith("/")) { 1755 return new URL(issuerURL + ".well-known/openid-configuration"); 1756 } else { 1757 return new URL(issuerURL + "/.well-known/openid-configuration"); 1758 } 1759 1760 } catch (MalformedURLException e) { 1761 throw new GeneralException("The issuer is not a valid URL", e); 1762 } 1763 } 1764 1765 1766 /** 1767 * Resolves the OpenID Provider metadata for the specified issuer. 1768 * The metadata is downloaded by HTTP GET from 1769 * {@code [issuer-url]/.well-known/openid-configuration}. 1770 * 1771 * @param issuer The issuer. Must represent a valid HTTPS or HTTP URL. 1772 * Must not be {@code null}. 1773 * 1774 * @return The OpenID Provider metadata. 1775 * 1776 * @throws GeneralException On invalid issuer or metadata. 1777 * @throws IOException On an HTTP exception. 1778 */ 1779 public static OIDCProviderMetadata resolve(final Issuer issuer) 1780 throws GeneralException, IOException { 1781 1782 return resolve(issuer, null, 0, 0); 1783 } 1784 1785 1786 /** 1787 * Resolves the OpenID Provider metadata for the specified issuer. The 1788 * metadata is downloaded by HTTP GET from 1789 * {@code [issuer-url]/.well-known/openid-configuration}. 1790 * 1791 * @param issuer The issuer. Must represent a valid HTTPS or HTTP 1792 * URL. Must not be {@code null}. 1793 * @param altBaseURL Alternative base URL to use instead of the issuer 1794 * URL, when the issuer URL is not resolvable or 1795 * accessible. When {@code null} the issuer URL is 1796 * used as the base URL. 1797 * 1798 * @return The OpenID Provider metadata. 1799 * 1800 * @throws GeneralException On invalid issuer or metadata. 1801 * @throws IOException On an HTTP exception. 1802 */ 1803 public static OIDCProviderMetadata resolve(final Issuer issuer, final URL altBaseURL) 1804 throws GeneralException, IOException { 1805 1806 return resolve(issuer, altBaseURL, 0, 0); 1807 } 1808 1809 1810 /** 1811 * Resolves the OpenID Provider metadata for the specified issuer. The 1812 * metadata is downloaded by HTTP GET from 1813 * {@code [issuer-url]/.well-known/openid-configuration}, using the 1814 * specified HTTP timeouts. 1815 * 1816 * @param issuer The issuer. Must represent a valid HTTPS or 1817 * HTTP URL. Must not be {@code null}. 1818 * @param connectTimeout The HTTP connect timeout, in milliseconds. 1819 * Zero implies no timeout. Must not be negative. 1820 * @param readTimeout The HTTP response read timeout, in 1821 * milliseconds. Zero implies no timeout. Must 1822 * not be negative. 1823 * 1824 * @return The OpenID Provider metadata. 1825 * 1826 * @throws GeneralException On invalid issuer or metadata. 1827 * @throws IOException On an HTTP exception. 1828 */ 1829 public static OIDCProviderMetadata resolve(final Issuer issuer, 1830 final int connectTimeout, 1831 final int readTimeout) 1832 throws GeneralException, IOException { 1833 1834 return resolve(issuer, null, connectTimeout, readTimeout); 1835 } 1836 1837 1838 /** 1839 * Resolves the OpenID Provider metadata for the specified issuer. The 1840 * metadata is downloaded by HTTP GET from 1841 * {@code [issuer-url]/.well-known/openid-configuration}, using the 1842 * specified HTTP timeouts. 1843 * 1844 * @param issuer The issuer. Must represent a valid HTTPS or 1845 * HTTP URL. Must not be {@code null}. 1846 * @param altBaseURL Alternative base URL to use instead of the 1847 * issuer URL, when the issuer URL is not 1848 * resolvable or accessible. When {@code null} 1849 * the issuer URL is used as the base URL. 1850 * @param connectTimeout The HTTP connect timeout, in milliseconds. 1851 * Zero implies no timeout. Must not be negative. 1852 * @param readTimeout The HTTP response read timeout, in 1853 * milliseconds. Zero implies no timeout. Must 1854 * not be negative. 1855 * 1856 * @return The OpenID Provider metadata. 1857 * 1858 * @throws GeneralException On invalid issuer or metadata. 1859 * @throws IOException On an HTTP exception. 1860 */ 1861 public static OIDCProviderMetadata resolve(final Issuer issuer, 1862 final URL altBaseURL, 1863 final int connectTimeout, 1864 final int readTimeout) 1865 throws GeneralException, IOException { 1866 1867 HTTPRequestConfigurator requestConfigurator = new HTTPRequestConfigurator() { 1868 1869 @Override 1870 public void configure(HTTPRequest httpRequest) { 1871 httpRequest.setConnectTimeout(connectTimeout); 1872 httpRequest.setReadTimeout(readTimeout); 1873 } 1874 }; 1875 1876 return resolve(issuer, altBaseURL, requestConfigurator); 1877 } 1878 1879 1880 /** 1881 * Resolves the OpenID Provider metadata from the specified issuer. The 1882 * metadata is downloaded by HTTP GET from 1883 * {@code [issuer-url]/.well-known/openid-configuration}, using the 1884 * specified HTTP request configurator. 1885 * 1886 * @param issuer The issuer. Must represent a valid HTTPS 1887 * or HTTP URL. Must not be {@code null}. 1888 * @param requestConfigurator An {@link HTTPRequestConfigurator} 1889 * instance to perform additional 1890 * {@link HTTPRequest} configuration. Must 1891 * not be {@code null}. 1892 * 1893 * @return The OpenID Provider metadata. 1894 * 1895 * @throws GeneralException On invalid issuer or metadata. 1896 * @throws IOException On an HTTP exception. 1897 */ 1898 public static OIDCProviderMetadata resolve(final Issuer issuer, 1899 final HTTPRequestConfigurator requestConfigurator) 1900 throws GeneralException, IOException { 1901 1902 return resolve(issuer, null, requestConfigurator); 1903 } 1904 1905 1906 /** 1907 * Resolves the OpenID Provider metadata for the specified issuer. The 1908 * metadata is downloaded by HTTP GET from 1909 * {@code [issuer]/.well-known/openid-configuration}, using the 1910 * specified HTTP request configurator. 1911 * 1912 * @param issuer The issuer. Must represent a valid HTTPS 1913 * or HTTP URL. Must not be {@code null}. 1914 * @param altBaseURL Alternative base URL to use instead of 1915 * the issuer URL, when the issuer URL is 1916 * not resolvable or accessible. When 1917 * {@code null} the issuer URL is used as 1918 * the base URL. 1919 * @param requestConfigurator An {@link HTTPRequestConfigurator} 1920 * instance to perform additional 1921 * {@link HTTPRequest} configuration. Must 1922 * not be {@code null}. 1923 * 1924 * @return The OpenID Provider metadata. 1925 * 1926 * @throws GeneralException On invalid issuer or metadata. 1927 * @throws IOException On an HTTP exception. 1928 */ 1929 public static OIDCProviderMetadata resolve(final Issuer issuer, 1930 final URL altBaseURL, 1931 final HTTPRequestConfigurator requestConfigurator) 1932 throws GeneralException, IOException { 1933 1934 return resolve( 1935 issuer, 1936 altBaseURL, 1937 new HTTPRequestModifier() { 1938 @Override 1939 public HTTPRequest modify(HTTPRequest httpRequest) { 1940 requestConfigurator.configure(httpRequest); 1941 return httpRequest; 1942 } 1943 }, 1944 false); 1945 } 1946 1947 1948 /** 1949 * Resolves the OpenID Provider metadata for the specified issuer. The 1950 * metadata is downloaded by HTTP GET from 1951 * {@code [issuer]/.well-known/openid-configuration}, using the 1952 * specified HTTP request modifier. 1953 * 1954 * @param issuer The issuer. Must represent a valid HTTPS 1955 * or HTTP URL. Must not be {@code null}. 1956 * @param altBaseURL Alternative base URL to use instead of 1957 * the issuer URL, when the issuer URL is 1958 * not resolvable or accessible. When 1959 * {@code null} the issuer URL is used as 1960 * the base URL. 1961 * @param requestModifier An {@link HTTPRequestModifier} to perform 1962 * additional {@link HTTPRequest} 1963 * configuration. Must not be {@code null}. 1964 * @param ignoreTrailingSlash If {@code true} compares the issuer URL 1965 * to the issuer in the OpenID provider 1966 * metadata ignoring any trailing slashes. 1967 * 1968 * @return The OpenID Provider metadata. 1969 * 1970 * @throws GeneralException On invalid issuer or metadata. 1971 * @throws IOException On an HTTP exception. 1972 */ 1973 public static OIDCProviderMetadata resolve(final Issuer issuer, 1974 final URL altBaseURL, 1975 final HTTPRequestModifier requestModifier, 1976 final boolean ignoreTrailingSlash) 1977 throws GeneralException, IOException { 1978 1979 URL configURL = resolveURL(altBaseURL != null ? new Issuer(altBaseURL.toString()) : issuer); 1980 1981 HTTPRequest httpRequest = new HTTPRequest(HTTPRequest.Method.GET, configURL); 1982 httpRequest = requestModifier.modify(httpRequest); 1983 1984 HTTPResponse httpResponse = httpRequest.send(); 1985 1986 if (httpResponse.getStatusCode() != 200) { 1987 throw new IOException("Couldn't download OpenID Provider metadata from " + configURL + 1988 ": Status code " + httpResponse.getStatusCode()); 1989 } 1990 1991 JSONObject jsonObject = httpResponse.getBodyAsJSONObject(); 1992 1993 OIDCProviderMetadata op = OIDCProviderMetadata.parse(jsonObject); 1994 1995 if (ignoreTrailingSlash ? ! issuer.equalsIgnoreTrailingSlash(op.getIssuer()) : ! issuer.equals(op.getIssuer())) { 1996 throw new GeneralException("The returned issuer doesn't match the expected: " + op.getIssuer()); 1997 } 1998 1999 return op; 2000 } 2001}