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