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