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