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