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