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