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.HTTPResponse;
034import com.nimbusds.oauth2.sdk.id.Identifier;
035import com.nimbusds.oauth2.sdk.id.Issuer;
036import com.nimbusds.oauth2.sdk.util.CollectionUtils;
037import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
038import com.nimbusds.openid.connect.sdk.Display;
039import com.nimbusds.openid.connect.sdk.SubjectType;
040import com.nimbusds.openid.connect.sdk.assurance.IdentityTrustFramework;
041import com.nimbusds.openid.connect.sdk.assurance.evidences.*;
042import com.nimbusds.openid.connect.sdk.assurance.evidences.attachment.AttachmentType;
043import com.nimbusds.openid.connect.sdk.assurance.evidences.attachment.HashAlgorithm;
044import com.nimbusds.openid.connect.sdk.claims.ACR;
045import com.nimbusds.openid.connect.sdk.claims.ClaimType;
046import com.nimbusds.openid.connect.sdk.federation.registration.ClientRegistrationType;
047import net.minidev.json.JSONObject;
048
049import java.io.IOException;
050import java.net.MalformedURLException;
051import java.net.URI;
052import java.net.URL;
053import java.util.*;
054
055
056/**
057 * OpenID Provider (OP) metadata.
058 *
059 * <p>Related specifications:
060 *
061 * <ul>
062 *     <li>OpenID Connect Discovery 1.0
063 *     <li>OpenID Connect Session Management 1.0
064 *     <li>OpenID Connect Front-Channel Logout 1.0
065 *     <li>OpenID Connect Back-Channel Logout 1.0
066 *     <li>OpenID Connect Native SSO for Mobile Apps 1.0
067 *     <li>OpenID Connect for Identity Assurance 1.0
068 *     <li>OpenID Connect Federation 1.0
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 (draft-ietf-oauth-incremental-authz)
081 * </ul>
082 */
083public class OIDCProviderMetadata extends AuthorizationServerMetadata implements ReadOnlyOIDCProviderMetadata {
084
085
086        /**
087         * The registered parameter names.
088         */
089        private static final Set<String> REGISTERED_PARAMETER_NAMES;
090
091
092        static {
093                Set<String> p = new HashSet<>(AuthorizationServerMetadata.getRegisteredParameterNames());
094                p.addAll(OIDCProviderEndpointMetadata.getRegisteredParameterNames());
095                p.add("acr_values_supported");
096                p.add("subject_types_supported");
097                p.add("id_token_signing_alg_values_supported");
098                p.add("id_token_encryption_alg_values_supported");
099                p.add("id_token_encryption_enc_values_supported");
100                p.add("userinfo_signing_alg_values_supported");
101                p.add("userinfo_encryption_alg_values_supported");
102                p.add("userinfo_encryption_enc_values_supported");
103                p.add("display_values_supported");
104                p.add("claim_types_supported");
105                p.add("claims_supported");
106                p.add("claims_locales_supported");
107                p.add("claims_parameter_supported");
108                p.add("backchannel_logout_supported");
109                p.add("backchannel_logout_session_supported");
110                p.add("frontchannel_logout_supported");
111                p.add("frontchannel_logout_session_supported");
112                p.add("native_sso_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} the {@code native_sso_supported} parameter is set,
256         * else not.
257         */
258        private boolean nativeSSOSupported = false;
259        
260        
261        /**
262         * If {@code true} verified claims are supported.
263         */
264        private boolean verifiedClaimsSupported = false;
265        
266        
267        /**
268         * The supported trust frameworks.
269         */
270        private List<IdentityTrustFramework> trustFrameworks;
271        
272        
273        /**
274         * The supported identity evidence types.
275         */
276        private List<IdentityEvidenceType> evidenceTypes;
277        
278        
279        /**
280         * The supported identity document types.
281         */
282        private List<DocumentType> documentTypes;
283        
284        
285        /**
286         * The supported coarse identity verification methods for evidences of
287         * type document.
288         */
289        private List<IdentityVerificationMethod> documentMethods;
290        
291        
292        /**
293         * The supported validation methods for evidences of type document.
294         */
295        private List<ValidationMethodType> documentValidationMethods;
296        
297        
298        /**
299         * The supported verification methods for evidences of type document.
300         */
301        private List<VerificationMethodType> documentVerificationMethods;
302        
303        
304        /**
305         * The supported identity document types.
306         */
307        @Deprecated
308        private List<IDDocumentType> idDocumentTypes;
309        
310        
311        /**
312         * The supported verification methods for identity documents.
313         */
314        @Deprecated
315        private List<IdentityVerificationMethod> idVerificationMethods;
316        
317        
318        /**
319         * The supported electronic record types.
320         */
321        private List<ElectronicRecordType> electronicRecordTypes;
322        
323        
324        /**
325         * The supported verified claims.
326         */
327        private List<String> verifiedClaims;
328        
329        
330        /**
331         * The supported attachment types.
332         */
333        private List<AttachmentType> attachmentTypes;
334        
335        
336        /**
337         * The supported digest algorithms for external attachments.
338         */
339        private List<HashAlgorithm> attachmentDigestAlgs;
340
341
342        /**
343         * Creates a new OpenID Connect provider metadata instance.
344         * 
345         * @param issuer       The issuer identifier. Must be a URI using the
346         *                     https scheme with no query or fragment 
347         *                     component. Must not be {@code null}.
348         * @param subjectTypes The supported subject types. At least one must
349         *                     be specified. Must not be {@code null}.
350         * @param jwkSetURI    The JWK set URI. Must not be {@code null}.
351         */
352        public OIDCProviderMetadata(final Issuer issuer,
353                                    final List<SubjectType> subjectTypes,
354                                    final URI jwkSetURI) {
355        
356                super(issuer);
357                
358                ensureAtLeastOneSubjectType(subjectTypes);
359                this.subjectTypes = subjectTypes;
360                setJWKSetURI(Objects.requireNonNull(jwkSetURI));
361                
362                // Default OpenID Connect setting is supported
363                setSupportsRequestURIParam(true);
364        }
365
366
367        /**
368         * Creates a new OpenID Connect Federation 1.0 provider metadata
369         * instance. The provider JWK set should be specified by
370         * {@code jwks_uri}, {@code signed_jwks_uri} or {@code jwks}.
371         *
372         * @param issuer                  The issuer identifier. Must be a URI
373         *                                using the https scheme with no query
374         *                                or fragment component. Must not be
375         *                                {@code null}.
376         * @param subjectTypes            The supported subject types. At least
377         *                                one must be specified. Must not be
378         *                                {@code null}.
379         * @param clientRegistrationTypes The supported client registration
380         *                                types. At least one must be
381         *                                specified. Must not be {@code null}.
382         * @param jwkSetURI               The JWK set URI, {@code null} if
383         *                                specified by another field.
384         * @param signedJWKSetURI         The signed JWK set URI, {@code null}
385         *                                if specified by another field.
386         * @param jwkSet                  the JWK set, {@code null} if
387         *                                specified by another field.
388         */
389        public OIDCProviderMetadata(final Issuer issuer,
390                                    final List<SubjectType> subjectTypes,
391                                    final List<ClientRegistrationType> clientRegistrationTypes,
392                                    final URI jwkSetURI,
393                                    final URI signedJWKSetURI,
394                                    final JWKSet jwkSet) {
395        
396                super(issuer);
397                
398                ensureAtLeastOneSubjectType(subjectTypes);
399                this.subjectTypes = subjectTypes;
400                
401                if (clientRegistrationTypes.size() < 1) {
402                        throw new IllegalArgumentException("At least one federation client registration type must be specified");
403                }
404                setClientRegistrationTypes(clientRegistrationTypes);
405                
406                if (jwkSetURI == null && signedJWKSetURI == null && jwkSet == null) {
407                        throw new IllegalArgumentException("At least one public JWK 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                if (jsonObject.get("client_registration_types_supported") != null) {
1336                        // OIDC Federation 1.0 constructor
1337                        List<ClientRegistrationType> clientRegistrationTypes = new LinkedList<>();
1338                        for (String v: JSONObjectUtils.getStringList(jsonObject, "client_registration_types_supported")) {
1339                                clientRegistrationTypes.add(new ClientRegistrationType(v));
1340                        }
1341                        try {
1342                                JWKSet jwkSet = null;
1343                                if (jsonObject.get("jwks") != null) {
1344                                        jwkSet = JWKSet.parse(JSONObjectUtils.getJSONObject(jsonObject, "jwks"));
1345                                }
1346                                
1347                                op = new OIDCProviderMetadata(
1348                                        as.getIssuer(),
1349                                        Collections.unmodifiableList(subjectTypes),
1350                                        clientRegistrationTypes,
1351                                        as.getJWKSetURI(),
1352                                        JSONObjectUtils.getURI(jsonObject, "signed_jwks_uri", null),
1353                                        jwkSet);
1354                        } catch (java.text.ParseException | IllegalArgumentException e) {
1355                                throw new ParseException(e.getMessage(), e);
1356                        }
1357                } else {
1358                        // Regular constructor
1359                        op = new OIDCProviderMetadata(
1360                                as.getIssuer(),
1361                                Collections.unmodifiableList(subjectTypes),
1362                                as.getJWKSetURI());
1363                }
1364                
1365
1366                // Endpoints
1367                op.setAuthorizationEndpointURI(as.getAuthorizationEndpointURI());
1368                op.setTokenEndpointURI(as.getTokenEndpointURI());
1369                op.setRegistrationEndpointURI(as.getRegistrationEndpointURI());
1370                op.setIntrospectionEndpointURI(as.getIntrospectionEndpointURI());
1371                op.setRevocationEndpointURI(as.getRevocationEndpointURI());
1372                op.setRequestObjectEndpoint(as.getRequestObjectEndpoint());
1373                op.setPushedAuthorizationRequestEndpointURI(as.getPushedAuthorizationRequestEndpointURI());
1374                op.setDeviceAuthorizationEndpointURI(as.getDeviceAuthorizationEndpointURI());
1375                op.userInfoEndpoint = JSONObjectUtils.getURI(jsonObject, "userinfo_endpoint", null);
1376                op.checkSessionIframe = JSONObjectUtils.getURI(jsonObject, "check_session_iframe", null);
1377                op.endSessionEndpoint = JSONObjectUtils.getURI(jsonObject, "end_session_endpoint", null);
1378
1379                // Capabilities
1380                op.setScopes(as.getScopes());
1381                op.setResponseTypes(as.getResponseTypes());
1382                op.setResponseModes(as.getResponseModes());
1383                op.setGrantTypes(as.getGrantTypes());
1384                
1385                op.setTokenEndpointAuthMethods(as.getTokenEndpointAuthMethods());
1386                op.setTokenEndpointJWSAlgs(as.getTokenEndpointJWSAlgs());
1387                
1388                op.setIntrospectionEndpointAuthMethods(as.getIntrospectionEndpointAuthMethods());
1389                op.setIntrospectionEndpointJWSAlgs(as.getIntrospectionEndpointJWSAlgs());
1390                
1391                op.setRevocationEndpointAuthMethods(as.getRevocationEndpointAuthMethods());
1392                op.setRevocationEndpointJWSAlgs(as.getRevocationEndpointJWSAlgs());
1393                
1394                op.setRequestObjectJWSAlgs(as.getRequestObjectJWSAlgs());
1395                op.setRequestObjectJWEAlgs(as.getRequestObjectJWEAlgs());
1396                op.setRequestObjectJWEEncs(as.getRequestObjectJWEEncs());
1397                
1398                op.setSupportsRequestParam(as.supportsRequestParam());
1399                op.setSupportsRequestURIParam(as.supportsRequestURIParam());
1400                op.setRequiresRequestURIRegistration(as.requiresRequestURIRegistration());
1401                
1402                op.requiresPushedAuthorizationRequests(as.requiresPushedAuthorizationRequests());
1403                
1404                op.setSupportsAuthorizationResponseIssuerParam(as.supportsAuthorizationResponseIssuerParam());
1405                
1406                op.setCodeChallengeMethods(as.getCodeChallengeMethods());
1407                
1408
1409                op.setBackChannelAuthenticationEndpointURI(as.getBackChannelAuthenticationEndpointURI());
1410                op.setBackChannelAuthenticationRequestJWSAlgs(as.getBackChannelAuthenticationRequestJWSAlgs());
1411                op.setSupportsBackChannelUserCodeParam(as.supportsBackChannelUserCodeParam());
1412                op.setBackChannelTokenDeliveryModes(as.getBackChannelTokenDeliveryModes());
1413                
1414                op.setPromptTypes(as.getPromptTypes());
1415                
1416                op.setOrganizationName(as.getOrganizationName());
1417                op.setJWKSet(as.getJWKSet());
1418                op.setSignedJWKSetURI(as.getSignedJWKSetURI());
1419                op.setClientRegistrationTypes(as.getClientRegistrationTypes());
1420                op.setClientRegistrationAuthnMethods(as.getClientRegistrationAuthnMethods());
1421                op.setClientRegistrationAuthnJWSAlgs(as.getClientRegistrationAuthnJWSAlgs());
1422                op.setFederationRegistrationEndpointURI(as.getFederationRegistrationEndpointURI());
1423
1424                if (jsonObject.get("acr_values_supported") != null) {
1425
1426                        op.acrValues = new ArrayList<>();
1427
1428                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "acr_values_supported")) {
1429
1430                                if (v != null)
1431                                        op.acrValues.add(new ACR(v));
1432                        }
1433                }
1434                
1435                // ID token
1436
1437                if (jsonObject.get("id_token_signing_alg_values_supported") != null) {
1438
1439                        op.idTokenJWSAlgs = new ArrayList<>();
1440
1441                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "id_token_signing_alg_values_supported")) {
1442
1443                                if (v != null)
1444                                        op.idTokenJWSAlgs.add(JWSAlgorithm.parse(v));
1445                        }
1446                }
1447
1448
1449                if (jsonObject.get("id_token_encryption_alg_values_supported") != null) {
1450
1451                        op.idTokenJWEAlgs = new ArrayList<>();
1452
1453                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "id_token_encryption_alg_values_supported")) {
1454
1455                                if (v != null)
1456                                        op.idTokenJWEAlgs.add(JWEAlgorithm.parse(v));
1457                        }
1458                }
1459
1460
1461                if (jsonObject.get("id_token_encryption_enc_values_supported") != null) {
1462
1463                        op.idTokenJWEEncs = new ArrayList<>();
1464
1465                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "id_token_encryption_enc_values_supported")) {
1466
1467                                if (v != null)
1468                                        op.idTokenJWEEncs.add(EncryptionMethod.parse(v));
1469                        }
1470                }
1471
1472                // UserInfo
1473
1474                if (jsonObject.get("userinfo_signing_alg_values_supported") != null) {
1475
1476                        op.userInfoJWSAlgs = new ArrayList<>();
1477
1478                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "userinfo_signing_alg_values_supported")) {
1479
1480                                if (v != null)
1481                                        op.userInfoJWSAlgs.add(JWSAlgorithm.parse(v));
1482                        }
1483                }
1484
1485
1486                if (jsonObject.get("userinfo_encryption_alg_values_supported") != null) {
1487
1488                        op.userInfoJWEAlgs = new ArrayList<>();
1489
1490                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "userinfo_encryption_alg_values_supported")) {
1491
1492                                if (v != null)
1493                                        op.userInfoJWEAlgs.add(JWEAlgorithm.parse(v));
1494                        }
1495                }
1496
1497
1498                if (jsonObject.get("userinfo_encryption_enc_values_supported") != null) {
1499
1500                        op.userInfoJWEEncs = new ArrayList<>();
1501
1502                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "userinfo_encryption_enc_values_supported")) {
1503
1504                                        if (v != null)
1505                                                op.userInfoJWEEncs.add(EncryptionMethod.parse(v));
1506                        }
1507                }
1508
1509                
1510                // Misc
1511
1512                if (jsonObject.get("display_values_supported") != null) {
1513
1514                        op.displays = new ArrayList<>();
1515
1516                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "display_values_supported")) {
1517
1518                                if (v != null)
1519                                        op.displays.add(Display.parse(v));
1520                        }
1521                }
1522                
1523                if (jsonObject.get("claim_types_supported") != null) {
1524                        
1525                        op.claimTypes = new ArrayList<>();
1526                        
1527                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "claim_types_supported")) {
1528                                
1529                                if (v != null)
1530                                        op.claimTypes.add(ClaimType.parse(v));
1531                        }
1532                }
1533
1534
1535                if (jsonObject.get("claims_supported") != null) {
1536
1537                        op.claims = new ArrayList<>();
1538
1539                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "claims_supported")) {
1540
1541                                if (v != null)
1542                                        op.claims.add(v);
1543                        }
1544                }
1545                
1546                if (jsonObject.get("claims_locales_supported") != null) {
1547                        
1548                        op.claimsLocales = new ArrayList<>();
1549                        
1550                        for (String v : JSONObjectUtils.getStringArray(jsonObject, "claims_locales_supported")) {
1551                                
1552                                if (v != null) {
1553                                        
1554                                        try {
1555                                                op.claimsLocales.add(LangTag.parse(v));
1556                                        
1557                                        } catch (LangTagException e) {
1558                                                
1559                                                throw new ParseException("Invalid claims_locales_supported field: " + e.getMessage(), e);
1560                                        }
1561                                }
1562                        }
1563                }
1564                
1565                op.setUILocales(as.getUILocales());
1566                op.setServiceDocsURI(as.getServiceDocsURI());
1567                op.setPolicyURI(as.getPolicyURI());
1568                op.setTermsOfServiceURI(as.getTermsOfServiceURI());
1569                
1570                if (jsonObject.get("claims_parameter_supported") != null)
1571                        op.claimsParamSupported = JSONObjectUtils.getBoolean(jsonObject, "claims_parameter_supported");
1572                
1573                if (jsonObject.get("request_uri_parameter_supported") == null) {
1574                        op.setSupportsRequestURIParam(true);
1575                }
1576                
1577                // Optional front and back-channel logout
1578                if (jsonObject.get("frontchannel_logout_supported") != null)
1579                        op.frontChannelLogoutSupported = JSONObjectUtils.getBoolean(jsonObject, "frontchannel_logout_supported");
1580                
1581                if (op.frontChannelLogoutSupported && jsonObject.get("frontchannel_logout_session_supported") != null)
1582                        op.frontChannelLogoutSessionSupported = JSONObjectUtils.getBoolean(jsonObject, "frontchannel_logout_session_supported");
1583                
1584                if (jsonObject.get("backchannel_logout_supported") != null)
1585                        op.backChannelLogoutSupported = JSONObjectUtils.getBoolean(jsonObject, "backchannel_logout_supported");
1586                
1587                if (op.backChannelLogoutSupported && jsonObject.get("backchannel_logout_session_supported") != null)
1588                        op.backChannelLogoutSessionSupported = JSONObjectUtils.getBoolean(jsonObject, "backchannel_logout_session_supported");
1589
1590                // Native SSO
1591                if (jsonObject.get("native_sso_supported") != null)
1592                        op.setSupportsNativeSSO(JSONObjectUtils.getBoolean(jsonObject, "native_sso_supported"));
1593
1594                if (jsonObject.get("mtls_endpoint_aliases") != null)
1595                        op.setMtlsEndpointAliases(OIDCProviderEndpointMetadata.parse(JSONObjectUtils.getJSONObject(jsonObject, "mtls_endpoint_aliases")));
1596                
1597                op.setSupportsTLSClientCertificateBoundAccessTokens(as.supportsTLSClientCertificateBoundAccessTokens());
1598                
1599                // DPoP
1600                op.setDPoPJWSAlgs(as.getDPoPJWSAlgs());
1601                
1602                // JARM
1603                op.setAuthorizationJWSAlgs(as.getAuthorizationJWSAlgs());
1604                op.setAuthorizationJWEAlgs(as.getAuthorizationJWEAlgs());
1605                op.setAuthorizationJWEEncs(as.getAuthorizationJWEEncs());
1606
1607                // RAR
1608                op.setAuthorizationDetailsTypes(as.getAuthorizationDetailsTypes());
1609                
1610                // Incremental authz
1611                op.setIncrementalAuthorizationTypes(as.getIncrementalAuthorizationTypes());
1612                
1613                // OpenID Connect for Identity Assurance 1.0
1614                if (jsonObject.get("verified_claims_supported") != null) {
1615                        op.verifiedClaimsSupported = JSONObjectUtils.getBoolean(jsonObject, "verified_claims_supported");
1616                        if (op.verifiedClaimsSupported) {
1617                                if (jsonObject.get("trust_frameworks_supported") != null) {
1618                                        op.trustFrameworks = new LinkedList<>();
1619                                        for (String v : JSONObjectUtils.getStringList(jsonObject, "trust_frameworks_supported")) {
1620                                                op.trustFrameworks.add(new IdentityTrustFramework(v));
1621                                        }
1622                                }
1623                                if (jsonObject.get("evidence_supported") != null) {
1624                                        op.evidenceTypes = new LinkedList<>();
1625                                        for (String v: JSONObjectUtils.getStringList(jsonObject, "evidence_supported")) {
1626                                                op.evidenceTypes.add(new IdentityEvidenceType(v));
1627                                        }
1628                                }
1629                                
1630                                if (
1631                                        (CollectionUtils.contains(op.evidenceTypes, IdentityEvidenceType.DOCUMENT) || CollectionUtils.contains(op.evidenceTypes, IdentityEvidenceType.ID_DOCUMENT))
1632                                        && jsonObject.get("documents_supported") != null) {
1633                                        
1634                                        op.documentTypes = new LinkedList<>();
1635                                        for (String v: JSONObjectUtils.getStringList(jsonObject, "documents_supported")) {
1636                                                op.documentTypes.add(new DocumentType(v));
1637                                        }
1638                                        
1639                                        // TODO await resolution of
1640                                        //  https://bitbucket.org/openid/ekyc-ida/issues/1275/clarification-regarding-op-metadata
1641                                        if (jsonObject.get("documents_methods_supported") != null) {
1642                                                op.documentMethods = new LinkedList<>();
1643                                                for (String v: JSONObjectUtils.getStringList(jsonObject, "documents_methods_supported")) {
1644                                                        op.documentMethods.add(new IdentityVerificationMethod(v));
1645                                                }
1646                                        }
1647                                        
1648                                        if (jsonObject.get("documents_validation_methods_supported") != null) {
1649                                                op.documentValidationMethods = new LinkedList<>();
1650                                                for (String v: JSONObjectUtils.getStringList(jsonObject, "documents_validation_methods_supported")) {
1651                                                        op.documentValidationMethods.add(new ValidationMethodType(v));
1652                                                }
1653                                        }
1654                                        
1655                                        if (jsonObject.get("documents_verification_methods_supported") != null) {
1656                                                op.documentVerificationMethods = new LinkedList<>();
1657                                                for (String v: JSONObjectUtils.getStringList(jsonObject, "documents_verification_methods_supported")) {
1658                                                        op.documentVerificationMethods.add(new VerificationMethodType(v));
1659                                                }
1660                                        }
1661                                }
1662                                
1663                                if (jsonObject.get("id_documents_supported") != null) {
1664                                        // deprecated
1665                                        op.idDocumentTypes = new LinkedList<>();
1666                                        for (String v: JSONObjectUtils.getStringList(jsonObject, "id_documents_supported")) {
1667                                                op.idDocumentTypes.add(new IDDocumentType(v));
1668                                        }
1669                                }
1670                                if (jsonObject.get("id_documents_verification_methods_supported") != null) {
1671                                        // deprecated
1672                                        op.idVerificationMethods = new LinkedList<>();
1673                                        for (String v: JSONObjectUtils.getStringList(jsonObject, "id_documents_verification_methods_supported")) {
1674                                                op.idVerificationMethods.add(new IdentityVerificationMethod(v));
1675                                        }
1676                                }
1677                                if (jsonObject.get("electronic_records_supported") != null) {
1678                                        op.electronicRecordTypes = new LinkedList<>();
1679                                        for (String v: JSONObjectUtils.getStringList(jsonObject, "electronic_records_supported")) {
1680                                                op.electronicRecordTypes.add(new ElectronicRecordType(v));
1681                                        }
1682                                }
1683                                if (jsonObject.get("claims_in_verified_claims_supported") != null) {
1684                                        op.verifiedClaims = JSONObjectUtils.getStringList(jsonObject, "claims_in_verified_claims_supported");
1685                                }
1686                                if (jsonObject.get("attachments_supported") != null) {
1687                                        op.attachmentTypes = new LinkedList<>();
1688                                        for (String v: JSONObjectUtils.getStringList(jsonObject, "attachments_supported")) {
1689                                                op.attachmentTypes.add(AttachmentType.parse(v));
1690                                        }
1691                                        
1692                                        if (op.attachmentTypes.contains(AttachmentType.EXTERNAL) && jsonObject.get("digest_algorithms_supported") != null) {
1693                                                op.attachmentDigestAlgs = new LinkedList<>();
1694                                                for (String v: JSONObjectUtils.getStringList(jsonObject, "digest_algorithms_supported")) {
1695                                                        op.attachmentDigestAlgs.add(new HashAlgorithm(v));
1696                                                }
1697                                        }
1698                                }
1699                        }
1700                }
1701                
1702                // Parse custom (not registered) parameters
1703                for (Map.Entry<String,?> entry: as.getCustomParameters().entrySet()) {
1704                        if (REGISTERED_PARAMETER_NAMES.contains(entry.getKey()))
1705                                continue; // skip
1706                        op.setCustomParameter(entry.getKey(), entry.getValue());
1707                }
1708
1709                return op;
1710        }
1711
1712
1713        /**
1714         * Parses an OpenID Provider metadata from the specified JSON object
1715         * string.
1716         *
1717         * @param s The JSON object sting to parse. Must not be {@code null}.
1718         *
1719         * @return The OpenID Provider metadata.
1720         *
1721         * @throws ParseException If the JSON object string couldn't be parsed
1722         *                        to an OpenID Provider metadata.
1723         */
1724        public static OIDCProviderMetadata parse(final String s)
1725                throws ParseException {
1726
1727                return parse(JSONObjectUtils.parse(s));
1728        }
1729        
1730        
1731        /**
1732         * Resolves the OpenID Provider metadata URL for the specified issuer.
1733         *
1734         * @param issuer The issuer. Must represent a valid HTTPS or HTTP URL.
1735         *               Must not be {@code null}.
1736         *
1737         * @return The OpenID Provider metadata URL.
1738         *
1739         * @throws GeneralException If the issuer is invalid.
1740         */
1741        public static URL resolveURL(final Issuer issuer)
1742                throws GeneralException {
1743                
1744                try {
1745                        URL issuerURL = new URL(issuer.getValue());
1746                        
1747                        // Validate but don't insist on HTTPS, see
1748                        // http://openid.net/specs/openid-connect-core-1_0.html#Terminology
1749                        if (issuerURL.getQuery() != null && ! issuerURL.getQuery().trim().isEmpty()) {
1750                                throw new GeneralException("The issuer must not contain a query component");
1751                        }
1752                        
1753                        if (issuerURL.getPath() != null && issuerURL.getPath().endsWith("/")) {
1754                                return new URL(issuerURL + ".well-known/openid-configuration");
1755                        } else {
1756                                return new URL(issuerURL + "/.well-known/openid-configuration");
1757                        }
1758                        
1759                } catch (MalformedURLException e) {
1760                        throw new GeneralException("The issuer is not a valid URL", e);
1761                }
1762        }
1763        
1764        
1765        /**
1766         * Resolves the OpenID Provider metadata for the specified issuer.
1767         * The metadata is downloaded by HTTP GET from
1768         * {@code [issuer-url]/.well-known/openid-configuration}.
1769         *
1770         * @param issuer The issuer. Must represent a valid HTTPS or HTTP URL.
1771         *               Must not be {@code null}.
1772         *
1773         * @return The OpenID Provider metadata.
1774         *
1775         * @throws GeneralException On invalid issuer or metadata.
1776         * @throws IOException      On an HTTP exception.
1777         */
1778        public static OIDCProviderMetadata resolve(final Issuer issuer)
1779                throws GeneralException, IOException {
1780
1781                return resolve(issuer, null, 0, 0);
1782        }
1783
1784
1785        /**
1786         * Resolves the OpenID Provider metadata for the specified issuer. The
1787         * metadata is downloaded by HTTP GET from
1788         * {@code [issuer-url]/.well-known/openid-configuration}.
1789         *
1790         * @param issuer     The issuer. Must represent a valid HTTPS or HTTP
1791         *                   URL. Must not be {@code null}.
1792         * @param altBaseURL Alternative base URL to use instead of the issuer
1793         *                   URL, when the issuer URL is not resolvable or
1794         *                   accessible. When {@code null} the issuer URL is
1795         *                   used as the base URL.
1796         *
1797         * @return The OpenID Provider metadata.
1798         *
1799         * @throws GeneralException On invalid issuer or metadata.
1800         * @throws IOException      On an HTTP exception.
1801         */
1802        public static OIDCProviderMetadata resolve(final Issuer issuer, final URL altBaseURL)
1803                throws GeneralException, IOException {
1804
1805                return resolve(issuer, altBaseURL, 0, 0);
1806        }
1807
1808
1809        /**
1810         * Resolves the OpenID Provider metadata for the specified issuer. The
1811         * metadata is downloaded by HTTP GET from
1812         * {@code [issuer-url]/.well-known/openid-configuration}, using the
1813         * specified HTTP timeouts.
1814         *
1815         * @param issuer         The issuer. Must represent a valid HTTPS or
1816         *                       HTTP URL. Must not be {@code null}.
1817         * @param connectTimeout The HTTP connect timeout, in milliseconds.
1818         *                       Zero implies no timeout. Must not be negative.
1819         * @param readTimeout    The HTTP response read timeout, in
1820         *                       milliseconds. Zero implies no timeout. Must
1821         *                       not be negative.
1822         *
1823         * @return The OpenID Provider metadata.
1824         *
1825         * @throws GeneralException On invalid issuer or metadata.
1826         * @throws IOException      On an HTTP exception.
1827         */
1828        public static OIDCProviderMetadata resolve(final Issuer issuer,
1829                                                   final int connectTimeout,
1830                                                   final int readTimeout)
1831                throws GeneralException, IOException {
1832
1833                return resolve(issuer, null, connectTimeout, readTimeout);
1834        }
1835
1836
1837        /**
1838         * Resolves the OpenID Provider metadata for the specified issuer. The
1839         * metadata is downloaded by HTTP GET from
1840         * {@code [issuer-url]/.well-known/openid-configuration}, using the
1841         * specified HTTP timeouts.
1842         *
1843         * @param issuer         The issuer. Must represent a valid HTTPS or
1844         *                       HTTP URL. Must not be {@code null}.
1845         * @param altBaseURL     Alternative base URL to use instead of the
1846         *                       issuer URL, when the issuer URL is not
1847         *                       resolvable or accessible. When {@code null}
1848         *                       the issuer URL is used as the base URL.
1849         * @param connectTimeout The HTTP connect timeout, in milliseconds.
1850         *                       Zero implies no timeout. Must not be negative.
1851         * @param readTimeout    The HTTP response read timeout, in
1852         *                       milliseconds. Zero implies no timeout. Must
1853         *                       not be negative.
1854         *
1855         * @return The OpenID Provider metadata.
1856         *
1857         * @throws GeneralException On invalid issuer or metadata.
1858         * @throws IOException      On an HTTP exception.
1859         */
1860        public static OIDCProviderMetadata resolve(final Issuer issuer,
1861                                                   final URL altBaseURL,
1862                                                   final int connectTimeout,
1863                                                   final int readTimeout)
1864                throws GeneralException, IOException {
1865
1866                HTTPRequestConfigurator requestConfigurator = new HTTPRequestConfigurator() {
1867
1868                        @Override
1869                        public void configure(HTTPRequest httpRequest) {
1870                                httpRequest.setConnectTimeout(connectTimeout);
1871                                httpRequest.setReadTimeout(readTimeout);
1872                        }
1873                };
1874
1875                return resolve(issuer, altBaseURL, requestConfigurator);
1876        }
1877
1878
1879        /**
1880         * Resolves the OpenID Provider metadata from the specified issuer. The
1881         * metadata is downloaded by HTTP GET from
1882         * {@code [issuer-url]/.well-known/openid-configuration}, using the
1883         * specified HTTP request configurator.
1884         *
1885         * @param issuer              The issuer. Must represent a valid HTTPS
1886         *                            or HTTP URL. Must not be {@code null}.
1887         * @param requestConfigurator An {@link HTTPRequestConfigurator}
1888         *                            instance to perform additional
1889         *                            {@link HTTPRequest} configuration. Must
1890         *                            not be {@code null}.
1891         *
1892         * @return The OpenID Provider metadata.
1893         *
1894         * @throws GeneralException On invalid issuer or metadata.
1895         * @throws IOException      On an HTTP exception.
1896         */
1897        public static OIDCProviderMetadata resolve(final Issuer issuer,
1898                                                   final HTTPRequestConfigurator requestConfigurator)
1899                throws GeneralException, IOException {
1900
1901                return resolve(issuer, null, requestConfigurator);
1902        }
1903
1904
1905        /**
1906         * Resolves the OpenID Provider metadata for the specified issuer. The
1907         * metadata is downloaded by HTTP GET from
1908         * {@code [issuer]/.well-known/openid-configuration}, using the
1909         * specified HTTP request configurator.
1910         *
1911         * @param issuer              The issuer. Must represent a valid HTTPS
1912         *                            or HTTP URL. Must not be {@code null}.
1913         * @param altBaseURL          Alternative base URL to use instead of
1914         *                            the issuer URL, when the issuer URL is
1915         *                            not resolvable or accessible. When
1916         *                            {@code null} the issuer URL is used as
1917         *                            the base URL.
1918         * @param requestConfigurator An {@link HTTPRequestConfigurator}
1919         *                            instance to perform additional
1920         *                            {@link HTTPRequest} configuration. Must
1921         *                            not be {@code null}.
1922         *
1923         * @return The OpenID Provider metadata.
1924         *
1925         * @throws GeneralException On invalid issuer or metadata.
1926         * @throws IOException      On an HTTP exception.
1927         */
1928        public static OIDCProviderMetadata resolve(final Issuer issuer,
1929                                                   final URL altBaseURL,
1930                                                   final HTTPRequestConfigurator requestConfigurator)
1931                throws GeneralException, IOException {
1932
1933                URL configURL = resolveURL(altBaseURL != null ? new Issuer(altBaseURL.toString()) : issuer);
1934
1935                HTTPRequest httpRequest = new HTTPRequest(HTTPRequest.Method.GET, configURL);
1936                requestConfigurator.configure(httpRequest);
1937
1938                HTTPResponse httpResponse = httpRequest.send();
1939
1940                if (httpResponse.getStatusCode() != 200) {
1941                        throw new IOException("Couldn't download OpenID Provider metadata from " + configURL + ": Status code "
1942                                + httpResponse.getStatusCode());
1943                }
1944
1945                JSONObject jsonObject = httpResponse.getBodyAsJSONObject();
1946
1947                OIDCProviderMetadata op = OIDCProviderMetadata.parse(jsonObject);
1948
1949                if (! issuer.equals(op.getIssuer())) {
1950                        throw new GeneralException("The returned issuer doesn't match the expected: " + op.getIssuer());
1951                }
1952
1953                return op;
1954        }
1955}