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