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