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