001package com.nimbusds.openid.connect.sdk.op;
002
003
004import java.net.MalformedURLException;
005import java.net.URL;
006import java.util.ArrayList;
007import java.util.Collections;
008import java.util.List;
009
010import net.minidev.json.JSONObject;
011
012import com.nimbusds.jose.EncryptionMethod;
013import com.nimbusds.jose.JWEAlgorithm;
014import com.nimbusds.jose.JWSAlgorithm;
015
016import com.nimbusds.langtag.LangTag;
017import com.nimbusds.langtag.LangTagException;
018
019import com.nimbusds.oauth2.sdk.GrantType;
020import com.nimbusds.oauth2.sdk.ParseException;
021import com.nimbusds.oauth2.sdk.Scope;
022import com.nimbusds.oauth2.sdk.ResponseType;
023import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
024import com.nimbusds.oauth2.sdk.id.Issuer;
025import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
026
027import com.nimbusds.openid.connect.sdk.Display;
028import com.nimbusds.openid.connect.sdk.SubjectType;
029import com.nimbusds.openid.connect.sdk.claims.ACR;
030import com.nimbusds.openid.connect.sdk.claims.ClaimType;
031
032
033/**
034 * OpenID Connect provider metadata. This class is immutable.
035 *
036 * <p>Related specifications:
037 *
038 * <ul>
039 *     <li>OpenID Connect Discovery 1.0, section 3.
040 * </ul>
041 *
042 * @author Vladimir Dzhuvinov
043 */
044public class OIDCProviderMetadata {
045
046
047        /**
048         * The version, set to "3.0".
049         */
050        public final static String VERSION = "3.0";
051
052
053        /**
054         * The issuer.
055         */
056        private final Issuer issuer;
057
058
059        /**
060         * The authorisation endpoint.
061         */
062        private URL authzEndpoint;
063
064
065        /**
066         * The token endpoint.
067         */
068        private URL tokenEndpoint;
069
070
071        /**
072         * The UserInfo endpoint.
073         */
074        private URL userInfoEndpoint;
075
076
077        /**
078         * The registration endpoint.
079         */
080        private URL regEndpoint;
081        
082        
083        /**
084         * The cross-origin check session iframe.
085         */
086        private URL checkSessionIframe;
087        
088        
089        /**
090         * The logout endpoint.
091         */
092        private URL endSessionEndpoint;
093
094
095        /**
096         * The JWK set URL.
097         */
098        private final URL jwkSetURI;
099
100
101        /**
102         * The supported scope values.
103         */
104        private Scope scope;
105
106
107        /**
108         * The supported response types.
109         */
110        private List<ResponseType> rts;
111        
112        
113        /**
114         * The supported grant types.
115         */
116        private List<GrantType> gts;
117
118
119        /**
120         * The supported ACRs.
121         */
122        private List<ACR> acrValues;
123
124
125        /**
126         * The supported subject types.
127         */
128        private final List<SubjectType> subjectTypes;
129
130
131        /**
132         * The supported token endpoint authentication methods.
133         */
134        private List<ClientAuthenticationMethod> tokenEndpointAuthMethods;
135
136
137        /**
138         * The supported JWS algorithms for the {@code private_key_jwt} and 
139         * {@code client_secret_jwt} token endpoint authentication methods.
140         */
141        private List<JWSAlgorithm> tokenEndpointJWSAlgs;
142
143
144        /**
145         * The supported JWS algorithms for OpenID Connect request objects.
146         */
147        private List<JWSAlgorithm> requestObjectJWSAlgs;
148
149
150        /**
151         * The supported JWE algorithms for OpenID Connect request objects.
152         */
153        private List<JWEAlgorithm> requestObjectJWEAlgs;
154
155
156        /**
157         * The supported encryption methods for OpenID Connect request objects.
158         */
159        private List<EncryptionMethod> requestObjectJWEEncs;
160
161
162        /**
163         * The supported ID token JWS algorithms.
164         */
165        private List<JWSAlgorithm> idTokenJWSAlgs;
166
167
168        /**
169         * The supported ID token JWE algorithms.
170         */
171        private List<JWEAlgorithm> idTokenJWEAlgs;
172
173
174        /**
175         * The supported ID token encryption methods.
176         */
177        private List<EncryptionMethod> idTokenJWEEncs;
178
179
180        /**
181         * The supported UserInfo JWS algorithms.
182         */
183        private List<JWSAlgorithm> userInfoJWSAlgs;
184
185
186        /**
187         * The supported UserInfo JWE algorithms.
188         */
189        private List<JWEAlgorithm> userInfoJWEAlgs;
190
191
192        /**
193         * The supported UserInfo encryption methods.
194         */
195        private List<EncryptionMethod> userInfoJWEEncs;
196
197
198        /**
199         * The supported displays.
200         */
201        private List<Display> displays;
202        
203        
204        /**
205         * The supported claim types.
206         */
207        private List<ClaimType> claimTypes;
208
209
210        /**
211         * The supported claims names.
212         */
213        private List<String> claims;
214        
215        
216        /**
217         * The supported claims locales.
218         */
219        private List<LangTag> claimsLocales;
220        
221        
222        /**
223         * The supported UI locales.
224         */
225        private List<LangTag> uiLocales;
226
227
228        /**
229         * The service documentation URL.
230         */
231        private URL serviceDocsURL;
232        
233        
234        /**
235         * The provider's policy regarding relying party use of data.
236         */
237        private URL policyURI;
238        
239        
240        /**
241         * The provider's terms of service.
242         */
243        private URL tosURI;
244        
245        
246        /**
247         * If {@code true} the {@code claims} parameter is supported, else not.
248         */
249        private boolean claimsParamSupported;
250        
251        
252        /**
253         * If {@code true} the {@code request} parameter is supported, else 
254         * not.
255         */
256        private boolean requestParamSupported;
257        
258        
259        /**
260         * If {@code true} the {@code request_uri} parameter is supported, else
261         * not.
262         */
263        private boolean requestURIParamSupported;
264        
265        
266        /**
267         * If {@code true} the {@code request_uri} parameters must be
268         * pre-registered with the provider, else not.
269         */
270        private boolean requireRequestURIReg;
271
272
273        /**
274         * Creates a new OpenID Connect provider metadata instance.
275         * 
276         * @param issuer       The issuer identifier. Must be an URL using the 
277         *                     https scheme with no query or fragment 
278         *                     component. Must not be {@code null}.
279         * @param subjectTypes The supported subject types. At least one must
280         *                     be specified. Must not be {@code null}.
281         */
282        public OIDCProviderMetadata(final Issuer issuer,
283                                    final List<SubjectType> subjectTypes,
284                                    final URL jwkSetURI) {
285        
286                URL url;
287                
288                try {
289                        url = new URL(issuer.getValue());
290                        
291                } catch (MalformedURLException e) {
292                        
293                        throw new IllegalArgumentException("The issuer identifier must be a URL: " + e.getMessage(), e);
294                }
295                
296                if (url.getQuery() != null)
297                        throw new IllegalArgumentException("The issuer URL must be without a query component");
298                
299                if (url.getRef() != null) 
300                        throw new IllegalArgumentException("The issuer URL must be without a fragment component ");
301                
302                this.issuer = issuer;
303                
304                
305                if (subjectTypes.size() < 1)
306                        throw new IllegalArgumentException("At least one supported subject type must be specified");
307                
308                this.subjectTypes = subjectTypes;
309
310                if (jwkSetURI == null)
311                        throw new IllegalArgumentException("The public JWK set URI must not be null");
312
313                this.jwkSetURI = jwkSetURI;
314        }
315
316
317        /**
318         * Gets the issuer identifier. Corresponds to the {@code issuer} 
319         * metadata field.
320         *
321         * @return The issuer identifier.
322         */
323        public Issuer getIssuer() {
324
325                return issuer;
326        }
327
328
329        /**
330         * Gets the authorisation endpoint URL. Corresponds the 
331         * {@code authorization_endpoint} metadata field.
332         *
333         * @return The authorisation endpoint URL, {@code null} if not 
334         *         specified.
335         */
336        public URL getAuthorizationEndpointURL() {
337
338                return authzEndpoint;
339        }
340
341
342        /**
343         * Sets the authorisation endpoint URL. Corresponds the
344         * {@code authorization_endpoint} metadata field.
345         *
346         * @param authzEndpoint The authorisation endpoint URL, {@code null} if
347         *                      not specified.
348         */
349        public void setAuthorizationEndpointURL(final URL authzEndpoint) {
350
351                this.authzEndpoint = authzEndpoint;
352        }
353
354
355        /**
356         * Gets the token endpoint URL. Corresponds the {@code token_endpoint}
357         * metadata field.
358         *
359         * @return The token endpoint URL, {@code null} if not specified.
360         */
361        public URL getTokenEndpointURL() {
362
363                return tokenEndpoint;
364        }
365
366
367        /**
368         * Sts the token endpoint URL. Corresponds the {@code token_endpoint}
369         * metadata field.
370         *
371         * @param tokenEndpoint The token endpoint URL, {@code null} if not
372         *                      specified.
373         */
374        public void setTokenEndpointURL(final URL tokenEndpoint) {
375
376                this.tokenEndpoint = tokenEndpoint;
377        }
378
379
380        /**
381         * Gets the UserInfo endpoint URL. Corresponds the 
382         * {@code userinfo_endpoint} metadata field.
383         *
384         * @return The UserInfo endpoint URL, {@code null} if not specified.
385         */
386        public URL getUserInfoEndpointURL() {
387
388                return userInfoEndpoint;
389        }
390
391
392        /**
393         * Sets the UserInfo endpoint URL. Corresponds the
394         * {@code userinfo_endpoint} metadata field.
395         *
396         * @param userInfoEndpoint The UserInfo endpoint URL, {@code null} if
397         *                         not specified.
398         */
399        public void setUserInfoEndpointURL(final URL userInfoEndpoint) {
400
401                this.userInfoEndpoint = userInfoEndpoint;
402        }
403
404
405        /**
406         * Gets the client registration endpoint URL. Corresponds to the
407         * {@code registration_endpoint} metadata field.
408         *
409         * @return The client registration endpoint URL, {@code null} if not
410         *         specified.
411         */
412        public URL getRegistrationEndpointURL() {
413
414                return regEndpoint;
415        }
416
417
418        /**
419         * Sets the client registration endpoint URL. Corresponds to the
420         * {@code registration_endpoint} metadata field.
421         *
422         * @param regEndpoint The client registration endpoint URL,
423         *                    {@code null} if not specified.
424         */
425        public void setRegistrationEndpointURL(final URL regEndpoint) {
426
427                this.regEndpoint = regEndpoint;
428        }
429        
430        
431        /**
432         * Gets the cross-origin check session iframe URL. Corresponds to the
433         * {@code check_session_iframe} metadata field.
434         * 
435         * @return The check session iframe URL, {@code null} if not specified.
436         */
437        public URL getCheckSessionIframeURL() {
438                
439                return checkSessionIframe;
440        }
441
442
443        /**
444         * Sets the cross-origin check session iframe URL. Corresponds to the
445         * {@code check_session_iframe} metadata field.
446         *
447         * @param checkSessionIframe The check session iframe URL, {@code null}
448         *                           if not specified.
449         */
450        public void setCheckSessionIframeURL(final URL checkSessionIframe) {
451
452                this.checkSessionIframe = checkSessionIframe;
453        }
454        
455        
456        /**
457         * Gets the logout endpoint URL. Corresponds to the 
458         * {@code end_session_endpoint} metadata field.
459         * 
460         * @return The logoout endpoint URL, {@code null} if not specified.
461         */
462        public URL getEndSessionEndpointURL() {
463                
464                return endSessionEndpoint;
465        }
466
467
468        /**
469         * Sets the logout endpoint URL. Corresponds to the
470         * {@code end_session_endpoint} metadata field.
471         *
472         * @param endSessionEndpoint The logoout endpoint URL, {@code null} if
473         *                           not specified.
474         */
475        public void setEndSessionEndpointURL(final URL endSessionEndpoint) {
476
477                this.endSessionEndpoint = endSessionEndpoint;
478        }
479
480
481        /**
482         * Gets the JSON Web Key (JWK) set URI. Corresponds to the
483         * {@code jwks_uri} metadata field.
484         *
485         * @return The JWK set URI.
486         */
487        public URL getJWKSetURI() {
488
489                return jwkSetURI;
490        }
491
492
493        /**
494         * Gets the supported scope values. Corresponds to the
495         * {@code scopes_supported} metadata field.
496         *
497         * @return The supported scope values, {@code null} if not specified.
498         */
499        public Scope getScopes() {
500
501                return scope;
502        }
503
504
505        /**
506         * Sets the supported scope values. Corresponds to the
507         * {@code scopes_supported} metadata field.
508         *
509         * @param scope The supported scope values, {@code null} if not
510         *              specified.
511         */
512        public void setScopes(final Scope scope) {
513
514                this.scope = scope;
515        }
516
517
518        /**
519         * Gets the supported response type values. Corresponds to the
520         * {@code response_types_supported} metadata field.
521         *
522         * @return The supported response type values, {@code null} if not 
523         *         specified.
524         */
525        public List<ResponseType> getResponseTypes() {
526
527                return rts;
528        }
529
530
531        /**
532         * Sets the supported response type values. Corresponds to the
533         * {@code response_types_supported} metadata field.
534         *
535         * @param rts The supported response type values, {@code null} if not
536         *            specified.
537         */
538        public void setResponseTypes(final List<ResponseType> rts) {
539
540                this.rts = rts;
541        }
542        
543        
544        /**
545         * Gets the supported OAuth 2.0 grant types. Corresponds to the
546         * {@code grant_types_supported} metadata field.
547         * 
548         * @return The supported grant types, {@code null} if not specified.
549         */
550        public List<GrantType> getGrantTypes() {
551                
552                return gts;
553        }
554
555
556        /**
557         * Sets the supported OAuth 2.0 grant types. Corresponds to the
558         * {@code grant_types_supported} metadata field.
559         *
560         * @param gts The supported grant types, {@code null} if not specified.
561         */
562        public void setGrantTypes(final List<GrantType> gts) {
563
564                this.gts = gts;
565        }
566
567
568        /**
569         * Gets the supported Authentication Context Class References (ACRs).
570         * Corresponds to the {@code acr_values_supported} metadata field.
571         *
572         * @return The supported ACRs, {@code null} if not specified.
573         */
574        public List<ACR> getACRs() {
575
576                return acrValues;
577        }
578
579
580        /**
581         * Sets the supported Authentication Context Class References (ACRs).
582         * Corresponds to the {@code acr_values_supported} metadata field.
583         *
584         * @param acrValues The supported ACRs, {@code null} if not specified.
585         */
586        public void setACRs(final List<ACR> acrValues) {
587
588                this.acrValues = acrValues;
589        }
590
591
592        /**
593         * Gets the supported subject types. Corresponds to the
594         * {@code subject_types_supported} metadata field.
595         *
596         * @return The supported subject types.
597         */
598        public List<SubjectType> getSubjectTypes() {
599
600                return subjectTypes;
601        }
602
603
604        /**
605         * Gets the supported token endpoint authentication methods. 
606         * Corresponds to the {@code token_endpoint_auth_methods_supported} 
607         * metadata field.
608         *
609         * @return The supported token endpoint authentication methods, 
610         *         {@code null} if not specified.
611         */
612        public List<ClientAuthenticationMethod> getTokenEndpointAuthMethods() {
613
614                return tokenEndpointAuthMethods;
615        }
616
617
618        /**
619         * Sets the supported token endpoint authentication methods.
620         * Corresponds to the {@code token_endpoint_auth_methods_supported}
621         * metadata field.
622         *
623         * @param tokenEndpointAuthMethods The supported token endpoint
624         *                                 authentication methods, {@code null}
625         *                                 if not specified.
626         */
627        public void setTokenEndpointAuthMethods(final List<ClientAuthenticationMethod> tokenEndpointAuthMethods) {
628
629                this.tokenEndpointAuthMethods = tokenEndpointAuthMethods;
630        }
631
632
633        /**
634         * Gets the supported JWS algorithms for the {@code private_key_jwt}
635         * and {@code client_secret_jwt} token endpoint authentication methods.
636         * Corresponds to the 
637         * {@code token_endpoint_auth_signing_alg_values_supported} metadata 
638         * field.
639         *
640         * @return The supported JWS algorithms, {@code null} if not specified.
641         */
642        public List<JWSAlgorithm> getTokenEndpointJWSAlgs() {
643
644                return tokenEndpointJWSAlgs;
645        }
646
647
648        /**
649         * Sets the supported JWS algorithms for the {@code private_key_jwt}
650         * and {@code client_secret_jwt} token endpoint authentication methods.
651         * Corresponds to the
652         * {@code token_endpoint_auth_signing_alg_values_supported} metadata
653         * field.
654         *
655         * @param tokenEndpointJWSAlgs The supported JWS algorithms,
656         *                             {@code null} if not specified.
657         */
658        public void setTokenEndpointJWSAlgs(final List<JWSAlgorithm> tokenEndpointJWSAlgs) {
659
660                this.tokenEndpointJWSAlgs = tokenEndpointJWSAlgs;
661        }
662
663
664        /**
665         * Gets the supported JWS algorithms for OpenID Connect request 
666         * objects. Corresponds to the 
667         * {@code request_object_signing_alg_values_supported} metadata field.
668         *
669         * @return The supported JWS algorithms, {@code null} if not specified.
670         */
671        public List<JWSAlgorithm> getRequestObjectJWSAlgs() {
672
673                return requestObjectJWSAlgs;
674        }
675
676
677        /**
678         * Sets the supported JWS algorithms for OpenID Connect request
679         * objects. Corresponds to the
680         * {@code request_object_signing_alg_values_supported} metadata field.
681         *
682         * @param requestObjectJWSAlgs The supported JWS algorithms,
683         *                             {@code null} if not specified.
684         */
685        public void setRequestObjectJWSAlgs(final List<JWSAlgorithm> requestObjectJWSAlgs) {
686
687                this.requestObjectJWSAlgs = requestObjectJWSAlgs;
688        }
689
690
691        /**
692         * Gets the supported JWE algorithms for OpenID Connect request 
693         * objects. Corresponds to the
694         * {@code request_object_encryption_alg_values_supported} metadata 
695         * field.
696         *
697         * @return The supported JWE algorithms, {@code null} if not specified.
698         */
699        public List<JWEAlgorithm> getRequestObjectJWEAlgs() {
700
701                return requestObjectJWEAlgs;
702        }
703
704
705        /**
706         * Sets the supported JWE algorithms for OpenID Connect request
707         * objects. Corresponds to the
708         * {@code request_object_encryption_alg_values_supported} metadata
709         * field.
710         *
711         * @param requestObjectJWEAlgs The supported JWE algorithms,
712         *                            {@code null} if not specified.
713         */
714        public void setRequestObjectJWEAlgs(final List<JWEAlgorithm> requestObjectJWEAlgs) {
715
716                this.requestObjectJWEAlgs = requestObjectJWEAlgs;
717        }
718
719
720        /**
721         * Gets the supported encryption methods for OpenID Connect request 
722         * objects. Corresponds to the 
723         * {@code request_object_encryption_enc_values_supported} metadata 
724         * field.
725         *
726         * @return The supported encryption methods, {@code null} if not 
727         *         specified.
728         */
729        public List<EncryptionMethod> getRequestObjectJWEEncs() {
730
731                return requestObjectJWEEncs;
732        }
733
734
735        /**
736         * Sets the supported encryption methods for OpenID Connect request
737         * objects. Corresponds to the
738         * {@code request_object_encryption_enc_values_supported} metadata
739         * field.
740         *
741         * @param requestObjectJWEEncs The supported encryption methods,
742         *                             {@code null} if not specified.
743         */
744        public void setRequestObjectJWEEncs(final List<EncryptionMethod> requestObjectJWEEncs) {
745
746                this.requestObjectJWEEncs = requestObjectJWEEncs;
747        }
748
749
750        /**
751         * Gets the supported JWS algorithms for ID tokens. Corresponds to the 
752         * {@code id_token_signing_alg_values_supported} metadata field.
753         *
754         * @return The supported JWS algorithms, {@code null} if not specified.
755         */
756        public List<JWSAlgorithm> getIDTokenJWSAlgs() {
757
758                return idTokenJWSAlgs;
759        }
760
761
762        /**
763         * Sets the supported JWS algorithms for ID tokens. Corresponds to the
764         * {@code id_token_signing_alg_values_supported} metadata field.
765         *
766         * @param idTokenJWSAlgs The supported JWS algorithms, {@code null} if
767         *                       not specified.
768         */
769        public void setIdTokenJWSAlgs(final List<JWSAlgorithm> idTokenJWSAlgs) {
770
771                this.idTokenJWSAlgs = idTokenJWSAlgs;
772        }
773
774
775        /**
776         * Gets the supported JWE algorithms for ID tokens. Corresponds to the 
777         * {@code id_token_encryption_alg_values_supported} metadata field.
778         *
779         * @return The supported JWE algorithms, {@code null} if not specified.
780         */
781        public List<JWEAlgorithm> getIDTokenJWEAlgs() {
782
783                return idTokenJWEAlgs;
784        }
785
786
787        /**
788         * Sets the supported JWE algorithms for ID tokens. Corresponds to the
789         * {@code id_token_encryption_alg_values_supported} metadata field.
790         *
791         * @param idTokenJWEAlgs The supported JWE algorithms, {@code null} if
792         *                       not specified.
793         */
794        public void setIdTokenJWEAlgs(final List<JWEAlgorithm> idTokenJWEAlgs) {
795
796                this.idTokenJWEAlgs = idTokenJWEAlgs;
797        }
798
799
800        /**
801         * Gets the supported encryption methods for ID tokens. Corresponds to 
802         * the {@code id_token_encryption_enc_values_supported} metadata field.
803         *
804         * @return The supported encryption methods, {@code null} if not 
805         *         specified.
806         */
807        public List<EncryptionMethod> getIDTokenJWEEncs() {
808
809                return idTokenJWEEncs;
810        }
811
812
813        /**
814         * Sets the supported encryption methods for ID tokens. Corresponds to
815         * the {@code id_token_encryption_enc_values_supported} metadata field.
816         *
817         * @param idTokenJWEEncs The supported encryption methods, {@code null}
818         *                       if not specified.
819         */
820        public void setIdTokenJWEEncs(final List<EncryptionMethod> idTokenJWEEncs) {
821
822                this.idTokenJWEEncs = idTokenJWEEncs;
823        }
824
825
826        /**
827         * Gets the supported JWS algorithms for UserInfo JWTs. Corresponds to 
828         * the {@code userinfo_signing_alg_values_supported} metadata field.
829         *
830         * @return The supported JWS algorithms, {@code null} if not specified.
831         */
832        public List<JWSAlgorithm> getUserInfoJWSAlgs() {
833
834                return userInfoJWSAlgs;
835        }
836
837
838        /**
839         * Sets the supported JWS algorithms for UserInfo JWTs. Corresponds to
840         * the {@code userinfo_signing_alg_values_supported} metadata field.
841         *
842         * @param userInfoJWSAlgs The supported JWS algorithms, {@code null} if
843         *                        not specified.
844         */
845        public void setUserInfoJWSAlgs(final List<JWSAlgorithm> userInfoJWSAlgs) {
846
847                this.userInfoJWSAlgs = userInfoJWSAlgs;
848        }
849
850
851        /**
852         * Gets the supported JWE algorithms for UserInfo JWTs. Corresponds to 
853         * the {@code userinfo_encryption_alg_values_supported} metadata field.
854         *
855         * @return The supported JWE algorithms, {@code null} if not specified.
856         */
857        public List<JWEAlgorithm> getUserInfoJWEAlgs() {
858
859                return userInfoJWEAlgs;
860        }
861
862
863        /**
864         * Sets the supported JWE algorithms for UserInfo JWTs. Corresponds to
865         * the {@code userinfo_encryption_alg_values_supported} metadata field.
866         *
867         * @param userInfoJWEAlgs The supported JWE algorithms, {@code null} if
868         *                        not specified.
869         */
870        public void setUserInfoJWEAlgs(final List<JWEAlgorithm> userInfoJWEAlgs) {
871
872                this.userInfoJWEAlgs = userInfoJWEAlgs;
873        }
874
875
876        /**
877         * Gets the supported encryption methods for UserInfo JWTs. Corresponds 
878         * to the {@code userinfo_encryption_enc_values_supported} metadata 
879         * field.
880         *
881         * @return The supported encryption methods, {@code null} if not 
882         *         specified.
883         */
884        public List<EncryptionMethod> getUserInfoJWEEncs() {
885
886                return userInfoJWEEncs;
887        }
888
889
890        /**
891         * Sets the supported encryption methods for UserInfo JWTs. Corresponds
892         * to the {@code userinfo_encryption_enc_values_supported} metadata
893         * field.
894         *
895         * @param userInfoJWEEncs The supported encryption methods,
896         *                        {@code null} if not specified.
897         */
898        public void setUserInfoJWEEncs(final List<EncryptionMethod> userInfoJWEEncs) {
899
900                this.userInfoJWEEncs = userInfoJWEEncs;
901        }
902
903
904        /**
905         * Gets the supported displays. Corresponds to the 
906         * {@code display_values_supported} metadata field.
907         *
908         * @return The supported displays, {@code null} if not specified.
909         */
910        public List<Display> getDisplays() {
911
912                return displays;
913        }
914
915
916        /**
917         * Sets the supported displays. Corresponds to the
918         * {@code display_values_supported} metadata field.
919         *
920         * @param displays The supported displays, {@code null} if not
921         *                 specified.
922         */
923        public void setDisplays(final List<Display> displays) {
924
925                this.displays = displays;
926        }
927        
928        
929        /**
930         * Gets the supported claim types. Corresponds to the 
931         * {@code claim_types_supported} metadata field.
932         * 
933         * @return The supported claim types, {@code null} if not specified.
934         */
935        public List<ClaimType> getClaimTypes() {
936                
937                return claimTypes;
938        }
939
940
941        /**
942         * Sets the supported claim types. Corresponds to the
943         * {@code claim_types_supported} metadata field.
944         *
945         * @param claimTypes The supported claim types, {@code null} if not
946         *                   specified.
947         */
948        public void setClaimTypes(final List<ClaimType> claimTypes) {
949
950                this.claimTypes = claimTypes;
951        }
952
953
954        /**
955         * Gets the supported claims names. Corresponds to the 
956         * {@code claims_supported} metadata field.
957         *
958         * @return The supported claims names, {@code null} if not specified.
959         */
960        public List<String> getClaims() {
961
962                return claims;
963        }
964
965
966        /**
967         * Sets the supported claims names. Corresponds to the
968         * {@code claims_supported} metadata field.
969         *
970         * @param claims The supported claims names, {@code null} if not
971         *               specified.
972         */
973        public void setClaims(final List<String> claims) {
974
975                this.claims = claims;
976        }
977        
978        
979        /**
980         * Gets the supported claims locales. Corresponds to the
981         * {@code claims_locales_supported} metadata field.
982         * 
983         * @return The supported claims locales, {@code null} if not specified.
984         */
985        public List<LangTag> getClaimsLocales() {
986                
987                return claimsLocales;
988        }
989
990
991        /**
992         * Sets the supported claims locales. Corresponds to the
993         * {@code claims_locales_supported} metadata field.
994         *
995         * @param claimsLocales The supported claims locales, {@code null} if
996         *                      not specified.
997         */
998        public void setClaimLocales(final List<LangTag> claimsLocales) {
999
1000                this.claimsLocales = claimsLocales;
1001        }
1002        
1003        
1004        /**
1005         * Gets the supported UI locales. Corresponds to the 
1006         * {@code ui_locales_supported} metadata field.
1007         * 
1008         * @return The supported UI locales, {@code null} if not specified.
1009         */
1010        public List<LangTag> getUILocales() {
1011                
1012                return uiLocales;
1013        }
1014
1015
1016        /**
1017         * Sets the supported UI locales. Corresponds to the
1018         * {@code ui_locales_supported} metadata field.
1019         *
1020         * @param uiLocales The supported UI locales, {@code null} if not
1021         *                  specified.
1022         */
1023        public void setUILocales(final List<LangTag> uiLocales) {
1024
1025                this.uiLocales = uiLocales;
1026        }
1027
1028
1029        /**
1030         * Gets the service documentation URL. Corresponds to the 
1031         * {@code service_documentation} metadata field.
1032         *
1033         * @return The service documentation URL, {@code null} if not 
1034         *         specified.
1035         */
1036        public URL getServiceDocsURL() {
1037
1038                return serviceDocsURL;
1039        }
1040
1041
1042        /**
1043         * Sets the service documentation URL. Corresponds to the
1044         * {@code service_documentation} metadata field.
1045         *
1046         * @param serviceDocsURL The service documentation URL, {@code null} if
1047         *                       not specified.
1048         */
1049        public void setServiceDocsURL(final URL serviceDocsURL) {
1050
1051                this.serviceDocsURL = serviceDocsURL;
1052        }
1053        
1054        
1055        /**
1056         * Gets the provider's policy regarding relying party use of data.
1057         * Corresponds to the {@code op_policy_uri} metadata field.
1058         * 
1059         * @return The policy URI, {@code null} if not specified.
1060         */
1061        public URL getPolicyURI() {
1062                
1063                return policyURI;
1064        }
1065
1066
1067        /**
1068         * Sets the provider's policy regarding relying party use of data.
1069         * Corresponds to the {@code op_policy_uri} metadata field.
1070         *
1071         * @param policyURI The policy URI, {@code null} if not specified.
1072         */
1073        public void setPolicyURI(final URL policyURI) {
1074
1075                this.policyURI = policyURI;
1076        }
1077        
1078        
1079        /**
1080         * Gets the provider's terms of service. Corresponds to the 
1081         * {@code op_tos_uri} metadata field.
1082         * 
1083         * @return The terms of service URI, {@code null} if not specified.
1084         */
1085        public URL getTermsOfServiceURI() {
1086                
1087                return tosURI;
1088        }
1089
1090
1091        /**
1092         * Sets the provider's terms of service. Corresponds to the
1093         * {@code op_tos_uri} metadata field.
1094         *
1095         * @param tosURI The terms of service URI, {@code null} if not
1096         *               specified.
1097         */
1098        public void setTermsOfServiceURI(final URL tosURI) {
1099
1100                this.tosURI = tosURI;
1101        }
1102        
1103        
1104        /**
1105         * Gets the support for the {@code claims} authorisation request
1106         * parameter. Corresponds to the {@code claims_parameter_supported} 
1107         * metadata field.
1108         * 
1109         * @return {@code true} if the {@code claim} parameter is supported,
1110         *         else {@code false}.
1111         */
1112        public boolean supportsClaimsParam() {
1113                
1114                return claimsParamSupported;
1115        }
1116
1117
1118        /**
1119         * Sets the support for the {@code claims} authorisation request
1120         * parameter. Corresponds to the {@code claims_parameter_supported}
1121         * metadata field.
1122         *
1123         * @param claimsParamSupported {@code true} if the {@code claim}
1124         *                             parameter is supported, else
1125         *                             {@code false}.
1126         */
1127        public void setSupportsClaimsParams(final boolean claimsParamSupported) {
1128
1129                this.claimsParamSupported = claimsParamSupported;
1130        }
1131        
1132        
1133        /**
1134         * Gets the support for the {@code request} authorisation request
1135         * parameter. Corresponds to the {@code request_parameter_supported}
1136         * metadata field.
1137         * 
1138         * @return {@code true} if the {@code reqeust} parameter is supported,
1139         *         else {@code false}.
1140         */
1141        public boolean supportsRequestParam() {
1142                
1143                return requestParamSupported;
1144        }
1145
1146
1147        /**
1148         * Sets the support for the {@code request} authorisation request
1149         * parameter. Corresponds to the {@code request_parameter_supported}
1150         * metadata field.
1151         *
1152         * @param requestParamSupported {@code true} if the {@code reqeust}
1153         *                              parameter is supported, else
1154         *                              {@code false}.
1155         */
1156        public void setSupportsRequestParams(final boolean requestParamSupported) {
1157
1158                this.requestParamSupported = requestParamSupported;
1159        }
1160        
1161        
1162        /**
1163         * Gets the support for the {@code request_uri} authorisation request
1164         * parameter. Corresponds the {@code request_uri_parameter_supported}
1165         * metadata field.
1166         * 
1167         * @return {@code true} if the {@code request_uri} parameter is
1168         *         supported, else {@code false}.
1169         */
1170        public boolean supportsRequestURIParam() {
1171                
1172                return requestURIParamSupported;
1173        }
1174
1175
1176        /**
1177         * Sets the support for the {@code request_uri} authorisation request
1178         * parameter. Corresponds the {@code request_uri_parameter_supported}
1179         * metadata field.
1180         *
1181         * @param requestURIParamSupported {@code true} if the
1182         *                                 {@code request_uri} parameter is
1183         *                                 supported, else {@code false}.
1184         */
1185        public void setSupportsRequestURIParam(final boolean requestURIParamSupported) {
1186
1187                this.requestURIParamSupported = requestURIParamSupported;
1188        }
1189        
1190        
1191        /**
1192         * Gets the requirement for the {@code request_uri} parameter 
1193         * pre-registration. Corresponds to the 
1194         * {@code require_request_uri_registration} metadata field.
1195         * 
1196         * @return {@code true} if the {@code request_uri} parameter values
1197         *         must be pre-registered, else {@code false}.
1198         */
1199        public boolean requiresRequestURIRegistration() {
1200                
1201                return requireRequestURIReg;
1202        }
1203
1204
1205        /**
1206         * Sets the requirement for the {@code request_uri} parameter
1207         * pre-registration. Corresponds to the
1208         * {@code require_request_uri_registration} metadata field.
1209         *
1210         * @param requireRequestURIReg {@code true} if the {@code request_uri}
1211         *                             parameter values must be pre-registered,
1212         *                             else {@code false}.
1213         */
1214        public void setRequiresRequestURIRegistration(final boolean requireRequestURIReg) {
1215
1216                this.requireRequestURIReg = requireRequestURIReg;
1217        }
1218
1219
1220        /**
1221         * Returns the JSON object representation of this OpenID Connect
1222         * provider metadata.
1223         *
1224         * @return The JSON object representation.
1225         */
1226        public JSONObject toJSONObject() {
1227
1228                JSONObject o = new JSONObject();
1229
1230                // Mandatory fields
1231
1232                o.put("version", VERSION);
1233
1234                o.put("issuer", issuer.getValue());
1235
1236                List<String> stringList = new ArrayList<String>(subjectTypes.size());
1237
1238                for (SubjectType st: subjectTypes)
1239                        stringList.add(st.toString());
1240
1241                o.put("subject_types_supported", stringList);
1242
1243                o.put("jwks_uri", jwkSetURI.toString());
1244
1245                // Optional fields
1246
1247                if (authzEndpoint != null)
1248                        o.put("authorization_endpoint", authzEndpoint.toString());
1249
1250                if (tokenEndpoint != null)
1251                        o.put("token_endpoint", tokenEndpoint.toString());
1252
1253                if (userInfoEndpoint != null)
1254                        o.put("userinfo_endpoint", userInfoEndpoint.toString());
1255
1256                if (regEndpoint != null)
1257                        o.put("registration_endpoint", regEndpoint.toString());
1258
1259                if (checkSessionIframe != null)
1260                        o.put("check_session_iframe", checkSessionIframe.toString());
1261
1262                if (endSessionEndpoint != null)
1263                        o.put("end_session_endpoint", endSessionEndpoint.toString());
1264
1265                if (scope != null)
1266                        o.put("scopes_supported", scope.toStringList());
1267
1268                if (rts != null) {
1269
1270                        stringList = new ArrayList<String>(rts.size());
1271
1272                        for (ResponseType rt: rts)
1273                                stringList.add(rt.toString());
1274
1275                        o.put("response_types_supported", stringList);
1276                }
1277
1278                if (gts != null) {
1279
1280                        stringList = new ArrayList<String>(gts.size());
1281
1282                        for (GrantType gt: gts)
1283                                stringList.add(gt.toString());
1284
1285                        o.put("grant_types_supported", stringList);
1286                }
1287
1288                if (acrValues != null) {
1289
1290                        stringList = new ArrayList<String>(acrValues.size());
1291
1292                        for (ACR acr: acrValues)
1293                                stringList.add(acr.getValue());
1294
1295                        o.put("acr_values_supported", stringList);
1296                }
1297
1298
1299                if (tokenEndpointAuthMethods != null) {
1300
1301                        stringList = new ArrayList<String>(tokenEndpointAuthMethods.size());
1302
1303                        for (ClientAuthenticationMethod m: tokenEndpointAuthMethods)
1304                                stringList.add(m.getValue());
1305
1306                        o.put("token_endpoint_auth_methods_supported", stringList);
1307                }
1308
1309                if (tokenEndpointJWSAlgs != null) {
1310
1311                        stringList = new ArrayList<String>(tokenEndpointJWSAlgs.size());
1312
1313                        for (JWSAlgorithm alg: tokenEndpointJWSAlgs)
1314                                stringList.add(alg.getName());
1315
1316                        o.put("token_endpoint_auth_signing_alg_values_supported", stringList);
1317                }
1318
1319                if (requestObjectJWSAlgs != null) {
1320
1321                        stringList = new ArrayList<String>(requestObjectJWSAlgs.size());
1322
1323                        for (JWSAlgorithm alg: requestObjectJWSAlgs)
1324                                stringList.add(alg.getName());
1325
1326                        o.put("request_object_signing_alg_values_supported", stringList);
1327                }
1328
1329                if (requestObjectJWEAlgs != null) {
1330
1331                        stringList = new ArrayList<String>(requestObjectJWEAlgs.size());
1332
1333                        for (JWEAlgorithm alg: requestObjectJWEAlgs)
1334                                stringList.add(alg.getName());
1335
1336                        o.put("request_object_encryption_alg_values_supported", stringList);
1337                }
1338
1339                if (requestObjectJWEEncs != null) {
1340
1341                        stringList = new ArrayList<String>(requestObjectJWEEncs.size());
1342
1343                        for (EncryptionMethod m: requestObjectJWEEncs)
1344                                stringList.add(m.getName());
1345
1346                        o.put("request_object_encryption_enc_values_supported", stringList);
1347                }
1348
1349                if (idTokenJWSAlgs != null) {
1350
1351                        stringList = new ArrayList<String>(idTokenJWEAlgs.size());
1352
1353                        for (JWSAlgorithm alg: idTokenJWSAlgs)
1354                                stringList.add(alg.getName());
1355
1356                        o.put("id_token_signing_alg_values_supported", stringList);
1357                }
1358
1359                if (idTokenJWEAlgs != null) {
1360
1361                        stringList = new ArrayList<String>(idTokenJWEAlgs.size());
1362
1363                        for (JWEAlgorithm alg: idTokenJWEAlgs)
1364                                stringList.add(alg.getName());
1365
1366                        o.put("id_token_encryption_alg_values_supported", stringList);
1367                }
1368
1369                if (idTokenJWEEncs != null) {
1370
1371                        stringList = new ArrayList<String>(idTokenJWEEncs.size());
1372
1373                        for (EncryptionMethod m: idTokenJWEEncs)
1374                                stringList.add(m.getName());
1375
1376                        o.put("id_token_encryption_enc_values_supported", stringList);
1377                }
1378
1379                if (userInfoJWSAlgs != null) {
1380
1381                        stringList = new ArrayList<String>(userInfoJWSAlgs.size());
1382
1383                        for (JWSAlgorithm alg: userInfoJWSAlgs)
1384                                stringList.add(alg.getName());
1385
1386                        o.put("userinfo_signing_alg_values_supported", stringList);
1387                }
1388
1389                if (userInfoJWEAlgs != null) {
1390
1391                        stringList = new ArrayList<String>(userInfoJWEAlgs.size());
1392
1393                        for (JWEAlgorithm alg: userInfoJWEAlgs)
1394                                stringList.add(alg.getName());
1395
1396                        o.put("userinfo_encryption_alg_values_supported", stringList);
1397                }
1398
1399                if (userInfoJWEEncs != null) {
1400
1401                        stringList = new ArrayList<String>(userInfoJWEEncs.size());
1402
1403                        for (EncryptionMethod m: userInfoJWEEncs)
1404                                stringList.add(m.getName());
1405
1406                        o.put("userinfo_encryption_enc_values_supported", stringList);
1407                }
1408
1409                if (displays != null) {
1410
1411                        stringList = new ArrayList<String>(displays.size());
1412
1413                        for (Display d: displays)
1414                                stringList.add(d.toString());
1415
1416                        o.put("display_values_supported", stringList);
1417                }
1418
1419                if (claimTypes != null) {
1420
1421                        stringList = new ArrayList<String>(claimTypes.size());
1422
1423                        for (ClaimType ct: claimTypes)
1424                                stringList.add(ct.toString());
1425
1426                        o.put("claim_types_supported", stringList);
1427                }
1428
1429                if (claims != null)
1430                        o.put("claims_supported", claims);
1431
1432                if (claimsLocales != null) {
1433
1434                        stringList = new ArrayList<String>(claimsLocales.size());
1435
1436                        for (LangTag l: claimsLocales)
1437                                stringList.add(l.toString());
1438
1439                        o.put("claims_locales_supported", stringList);
1440                }
1441
1442                if (uiLocales != null) {
1443
1444                        stringList = new ArrayList<String>(uiLocales.size());
1445
1446                        for (LangTag l: uiLocales)
1447                                stringList.add(l.toString());
1448
1449                        o.put("ui_locales_supported", stringList);
1450                }
1451
1452                if (serviceDocsURL != null)
1453                        o.put("service_documentation", serviceDocsURL.toString());
1454
1455                if (policyURI != null)
1456                        o.put("op_policy_uri", policyURI.toString());
1457
1458                if (tosURI != null)
1459                        o.put("op_tos_uri", tosURI.toString());
1460
1461                o.put("claims_parameter_supported", claimsParamSupported);
1462
1463                o.put("request_parameter_supported", requestParamSupported);
1464
1465                o.put("request_uri_parameter_supported", requestURIParamSupported);
1466
1467                o.put("require_request_uri_registration", requireRequestURIReg);
1468
1469                return o;
1470        }
1471
1472
1473
1474        /**
1475         * Parses an OpenID Connect provider metadata from the specified JSON 
1476         * object.
1477         *
1478         * @param jsonObject The JSON object to parse. Must not be 
1479         *                   {@code null}.
1480         *
1481         * @return The OpenID Connect provider metadata.
1482         *
1483         * @throws ParseException If the JSON object couldn't be parsed to an
1484         *                        OpenID Connect provider metadata.
1485         */
1486        public static OIDCProviderMetadata parse(final JSONObject jsonObject)
1487                throws ParseException {
1488
1489                String version = JSONObjectUtils.getString(jsonObject, "version");
1490
1491                if(! version.equals(VERSION))
1492                        throw new ParseException("The version must be \"3.0\"");
1493
1494                // Parse issuer and subject_types_supported first
1495                
1496                List<SubjectType> subjectTypes = new ArrayList<SubjectType>();
1497                
1498                for (String v: JSONObjectUtils.getStringArray(jsonObject, "subject_types_supported")) {
1499                        subjectTypes.add(SubjectType.parse(v));
1500                }
1501                
1502                Issuer issuer = new Issuer(JSONObjectUtils.getURL(jsonObject, "issuer").toString());
1503
1504                URL jwkSetURI = JSONObjectUtils.getURL(jsonObject, "jwks_uri");
1505                
1506                
1507                OIDCProviderMetadata op = new OIDCProviderMetadata(issuer, Collections.unmodifiableList(subjectTypes), jwkSetURI);
1508
1509                // Endpoints
1510                if (jsonObject.containsKey("authorization_endpoint"))
1511                        op.authzEndpoint = JSONObjectUtils.getURL(jsonObject, "authorization_endpoint");
1512
1513                if (jsonObject.containsKey("token_endpoint"))
1514                        op.tokenEndpoint = JSONObjectUtils.getURL(jsonObject, "token_endpoint");
1515
1516                if (jsonObject.containsKey("userinfo_endpoint"))
1517                        op.userInfoEndpoint = JSONObjectUtils.getURL(jsonObject, "userinfo_endpoint");
1518                
1519                if (jsonObject.containsKey("registration_endpoint"))
1520                        op.regEndpoint = JSONObjectUtils.getURL(jsonObject, "registration_endpoint");
1521                
1522                if (jsonObject.containsKey("check_session_iframe"))
1523                        op.checkSessionIframe = JSONObjectUtils.getURL(jsonObject, "check_session_iframe");
1524                
1525                if (jsonObject.containsKey("end_session_endpoint"))
1526                        op.endSessionEndpoint = JSONObjectUtils.getURL(jsonObject, "end_session_endpoint");
1527
1528                // OIDC capabilities
1529                if (jsonObject.containsKey("scopes_supported")) {
1530
1531                        op.scope = new Scope();
1532
1533                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "scopes_supported")) {
1534
1535                                if (v != null)
1536                                        op.scope.add(new Scope.Value(v));
1537                        }
1538                }
1539
1540                if (jsonObject.containsKey("response_types_supported")) {
1541
1542                        op.rts = new ArrayList<ResponseType>();
1543
1544                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "response_types_supported")) {
1545
1546                                if (v != null)
1547                                        op.rts.add(ResponseType.parse(v));
1548                        }
1549                }
1550                
1551                if (jsonObject.containsKey("grant_types_supported")) {
1552                        
1553                        op.gts = new ArrayList<GrantType>();
1554                        
1555                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "grant_types_supported")) {
1556                                
1557                                if (v != null)
1558                                        op.gts.add(new GrantType(v));
1559                        }
1560                }
1561
1562                if (jsonObject.containsKey("acr_values_supported")) {
1563
1564                        op.acrValues = new ArrayList<ACR>();
1565
1566                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "acr_values_supported")) {
1567
1568                                if (v != null)
1569                                        op.acrValues.add(new ACR(v));
1570                        }
1571                }
1572
1573                if (jsonObject.containsKey("token_endpoint_auth_methods_supported")) {
1574                        
1575                        op.tokenEndpointAuthMethods = new ArrayList<ClientAuthenticationMethod>();
1576                        
1577                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "token_endpoint_auth_methods_supported")) {
1578                                
1579                                if (v != null)
1580                                        op.tokenEndpointAuthMethods.add(new ClientAuthenticationMethod(v));
1581                        }
1582                }
1583                
1584                if (jsonObject.containsKey("token_endpoint_auth_signing_alg_values_supported")) {
1585                        
1586                        op.tokenEndpointJWSAlgs = new ArrayList<JWSAlgorithm>();
1587                        
1588                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "token_endpoint_auth_signing_alg_values_supported")) {
1589                                
1590                                if (v != null)
1591                                        op.tokenEndpointJWSAlgs.add(new JWSAlgorithm(v));
1592                        }
1593                }
1594                
1595                
1596                // OpenID Connect request object
1597
1598                if (jsonObject.containsKey("request_object_signing_alg_values_supported")) {
1599
1600                        op.requestObjectJWSAlgs = new ArrayList<JWSAlgorithm>();
1601
1602                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "request_object_signing_alg_values_supported")) {
1603
1604                                if (v != null)
1605                                        op.requestObjectJWSAlgs.add(new JWSAlgorithm(v));
1606                        }
1607                }
1608
1609
1610                if (jsonObject.containsKey("request_object_encryption_alg_values_supported")) {
1611
1612                        op.requestObjectJWEAlgs = new ArrayList<JWEAlgorithm>();
1613
1614                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "request_object_encryption_alg_values_supported")) {
1615
1616                                if (v != null)
1617                                        op.requestObjectJWEAlgs.add(new JWEAlgorithm(v));
1618                        }
1619                }
1620
1621
1622                if (jsonObject.containsKey("request_object_encryption_enc_values_supported")) {
1623
1624                        op.requestObjectJWEEncs = new ArrayList<EncryptionMethod>();
1625
1626                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "request_object_encryption_enc_values_supported")) {
1627
1628                                if (v != null)
1629                                        op.requestObjectJWEEncs.add(new EncryptionMethod(v));
1630                        }
1631                }
1632                
1633                
1634                // ID token
1635
1636                if (jsonObject.containsKey("id_token_signing_alg_values_supported")) {
1637
1638                        op.idTokenJWSAlgs = new ArrayList<JWSAlgorithm>();
1639
1640                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "id_token_signing_alg_values_supported")) {
1641
1642                                if (v != null)
1643                                        op.idTokenJWSAlgs.add(new JWSAlgorithm(v));
1644                        }
1645                }
1646
1647
1648                if (jsonObject.containsKey("id_token_encryption_alg_values_supported")) {
1649
1650                        op.idTokenJWEAlgs = new ArrayList<JWEAlgorithm>();
1651
1652                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "id_token_encryption_alg_values_supported")) {
1653
1654                                if (v != null)
1655                                        op.idTokenJWEAlgs.add(new JWEAlgorithm(v));
1656                        }
1657                }
1658
1659
1660                if (jsonObject.containsKey("id_token_encryption_enc_values_supported")) {
1661
1662                        op.idTokenJWEEncs = new ArrayList<EncryptionMethod>();
1663
1664                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "id_token_encryption_enc_values_supported")) {
1665
1666                                if (v != null)
1667                                        op.idTokenJWEEncs.add(new EncryptionMethod(v));
1668                        }
1669                }
1670
1671                // UserInfo
1672
1673                if (jsonObject.containsKey("userinfo_signing_alg_values_supported")) {
1674
1675                        op.userInfoJWSAlgs = new ArrayList<JWSAlgorithm>();
1676
1677                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "userinfo_signing_alg_values_supported")) {
1678
1679                                if (v != null)
1680                                        op.userInfoJWSAlgs.add(new JWSAlgorithm(v));
1681                        }
1682                }
1683
1684
1685                if (jsonObject.containsKey("userinfo_encryption_alg_values_supported")) {
1686
1687                        op.userInfoJWEAlgs = new ArrayList<JWEAlgorithm>();
1688
1689                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "userinfo_encryption_alg_values_supported")) {
1690
1691                                if (v != null)
1692                                        op.userInfoJWEAlgs.add(new JWEAlgorithm(v));
1693                        }
1694                }
1695
1696
1697                if (jsonObject.containsKey("userinfo_encryption_enc_values_supported")) {
1698
1699                        op.userInfoJWEEncs = new ArrayList<EncryptionMethod>();
1700
1701                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "userinfo_encryption_enc_values_supported")) {
1702
1703                                        if (v != null)
1704                                                op.userInfoJWEEncs.add(new EncryptionMethod(v));
1705                        }
1706                }
1707
1708                
1709                // Misc
1710
1711                if (jsonObject.containsKey("display_values_supported")) {
1712
1713                        op.displays = new ArrayList<Display>();
1714
1715                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "display_values_supported")) {
1716
1717                                if (v != null)
1718                                        op.displays.add(Display.parse(v));
1719                        }
1720                }
1721                
1722                if (jsonObject.containsKey("claim_types_supported")) {
1723                        
1724                        op.claimTypes = new ArrayList<ClaimType>();
1725                        
1726                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "claim_types_supported")) {
1727                                
1728                                if (v != null)
1729                                        op.claimTypes.add(ClaimType.parse(v));
1730                        }
1731                }
1732
1733
1734                if (jsonObject.containsKey("claims_supported")) {
1735
1736                        op.claims = new ArrayList<String>();
1737
1738                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "claims_supported")) {
1739
1740                                if (v != null)
1741                                        op.claims.add(v);
1742                        }
1743                }
1744                
1745                if (jsonObject.containsKey("claims_locales_supported")) {
1746                        
1747                        op.claimsLocales = new ArrayList<LangTag>();
1748                        
1749                        for (String v : JSONObjectUtils.getStringArray(jsonObject, "claims_locales_supported")) {
1750                                
1751                                if (v != null) {
1752                                        
1753                                        try {
1754                                                op.claimsLocales.add(LangTag.parse(v));
1755                                        
1756                                        } catch (LangTagException e) {
1757                                                
1758                                                throw new ParseException("Invalid claims_locales_supported field: " + e.getMessage(), e);
1759                                        }
1760                                }
1761                        }
1762                }
1763                
1764                if (jsonObject.containsKey("ui_locales_supported")) {
1765                        
1766                        op.uiLocales = new ArrayList<LangTag>();
1767                        
1768                        for (String v : JSONObjectUtils.getStringArray(jsonObject, "ui_locales_supported")) {
1769                                
1770                                if (v != null) {
1771                                        
1772                                        try {
1773                                                op.uiLocales.add(LangTag.parse(v));
1774                                        
1775                                        } catch (LangTagException e) {
1776                                                
1777                                                throw new ParseException("Invalid ui_locales_supported field: " + e.getMessage(), e);
1778                                        }
1779                                }
1780                        }
1781                }
1782
1783
1784                if (jsonObject.containsKey("service_documentation"))
1785                        op.serviceDocsURL = JSONObjectUtils.getURL(jsonObject, "service_documentation");
1786                
1787                if (jsonObject.containsKey("op_policy_uri"))
1788                        op.policyURI = JSONObjectUtils.getURL(jsonObject, "op_policy_uri");
1789                
1790                if (jsonObject.containsKey("op_tos_uri"))
1791                        op.tosURI = JSONObjectUtils.getURL(jsonObject, "op_tos_uri");
1792                
1793                if (jsonObject.containsKey("claims_parameter_supported"))
1794                        op.claimsParamSupported = JSONObjectUtils.getBoolean(jsonObject, "claims_parameter_supported");
1795                
1796                if (jsonObject.containsKey("request_parameter_supported"))
1797                        op.requestParamSupported = JSONObjectUtils.getBoolean(jsonObject, "request_parameter_supported");
1798                
1799                if (jsonObject.containsKey("request_uri_parameter_supported"))
1800                        op.requestURIParamSupported = JSONObjectUtils.getBoolean(jsonObject, "request_uri_parameter_supported");
1801                
1802                if (jsonObject.containsKey("require_request_uri_registration"))
1803                        op.requireRequestURIReg = JSONObjectUtils.getBoolean(jsonObject, "require_request_uri_registration");
1804
1805                return op;
1806        }
1807
1808
1809        /**
1810         * Parses an OpenID Connect provider metadata from the specified JSON 
1811         * object string.
1812         *
1813         * @param s The JSON object sting to parse. Must not be {@code null}.
1814         *
1815         * @return The OpenID Connect provider metadata.
1816         *
1817         * @throws ParseException If the JSON object string couldn't be parsed
1818         *                        to an OpenID Connect provider metadata.
1819         */
1820        public static OIDCProviderMetadata parse(final String s)
1821                throws ParseException {
1822
1823                return parse(JSONObjectUtils.parseJSONObject(s));
1824        }
1825}