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