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