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        @Override
2010        public String toString() {
2011                return toJSONObject().toJSONString();
2012        }
2013        
2014        
2015        /**
2016         * Parses an OpenID Connect provider metadata from the specified JSON 
2017         * object.
2018         *
2019         * @param jsonObject The JSON object to parse. Must not be 
2020         *                   {@code null}.
2021         *
2022         * @return The OpenID Connect provider metadata.
2023         *
2024         * @throws ParseException If the JSON object couldn't be parsed to an
2025         *                        OpenID Connect provider metadata.
2026         */
2027        public static OIDCProviderMetadata parse(final JSONObject jsonObject)
2028                throws ParseException {
2029
2030                // Parse issuer and subject_types_supported first
2031                
2032                List<SubjectType> subjectTypes = new ArrayList<>();
2033                
2034                for (String v: JSONObjectUtils.getStringArray(jsonObject, "subject_types_supported")) {
2035                        subjectTypes.add(SubjectType.parse(v));
2036                }
2037                
2038                Issuer issuer = new Issuer(JSONObjectUtils.getURI(jsonObject, "issuer").toString());
2039
2040                URI jwkSetURI = JSONObjectUtils.getURI(jsonObject, "jwks_uri");
2041                
2042                
2043                OIDCProviderMetadata op = new OIDCProviderMetadata(issuer, Collections.unmodifiableList(subjectTypes), jwkSetURI);
2044
2045                // Endpoints
2046                if (jsonObject.get("authorization_endpoint") != null)
2047                        op.authzEndpoint = JSONObjectUtils.getURI(jsonObject, "authorization_endpoint");
2048
2049                if (jsonObject.get("token_endpoint") != null)
2050                        op.tokenEndpoint = JSONObjectUtils.getURI(jsonObject, "token_endpoint");
2051
2052                if (jsonObject.get("userinfo_endpoint") != null)
2053                        op.userInfoEndpoint = JSONObjectUtils.getURI(jsonObject, "userinfo_endpoint");
2054                
2055                if (jsonObject.get("registration_endpoint") != null)
2056                        op.regEndpoint = JSONObjectUtils.getURI(jsonObject, "registration_endpoint");
2057                
2058                if (jsonObject.get("introspection_endpoint") != null)
2059                        op.introspectionEndpoint = JSONObjectUtils.getURI(jsonObject, "introspection_endpoint");
2060                
2061                if (jsonObject.get("revocation_endpoint") != null)
2062                        op.revocationEndpoint = JSONObjectUtils.getURI(jsonObject, "revocation_endpoint");
2063                
2064                if (jsonObject.get("check_session_iframe") != null)
2065                        op.checkSessionIframe = JSONObjectUtils.getURI(jsonObject, "check_session_iframe");
2066                
2067                if (jsonObject.get("end_session_endpoint") != null)
2068                        op.endSessionEndpoint = JSONObjectUtils.getURI(jsonObject, "end_session_endpoint");
2069
2070                // OIDC capabilities
2071                if (jsonObject.get("scopes_supported") != null) {
2072
2073                        op.scope = new Scope();
2074
2075                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "scopes_supported")) {
2076
2077                                if (v != null)
2078                                        op.scope.add(new Scope.Value(v));
2079                        }
2080                }
2081
2082                if (jsonObject.get("response_types_supported") != null) {
2083
2084                        op.rts = new ArrayList<>();
2085
2086                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "response_types_supported")) {
2087
2088                                if (v != null)
2089                                        op.rts.add(ResponseType.parse(v));
2090                        }
2091                }
2092
2093                if (jsonObject.get("response_modes_supported") != null) {
2094
2095                        op.rms = new ArrayList<>();
2096
2097                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "response_modes_supported")) {
2098
2099                                if (v != null)
2100                                        op.rms.add(new ResponseMode(v));
2101                        }
2102                }
2103                
2104                if (jsonObject.get("grant_types_supported") != null) {
2105                        
2106                        op.gts = new ArrayList<>();
2107                        
2108                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "grant_types_supported")) {
2109                                
2110                                if (v != null)
2111                                        op.gts.add(GrantType.parse(v));
2112                        }
2113                }
2114
2115                if (jsonObject.get("code_challenge_methods_supported") != null) {
2116
2117                        op.codeChallengeMethods = new ArrayList<>();
2118
2119                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "code_challenge_methods_supported")) {
2120
2121                                if (v != null)
2122                                        op.codeChallengeMethods.add(CodeChallengeMethod.parse(v));
2123                        }
2124                }
2125
2126                if (jsonObject.get("acr_values_supported") != null) {
2127
2128                        op.acrValues = new ArrayList<>();
2129
2130                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "acr_values_supported")) {
2131
2132                                if (v != null)
2133                                        op.acrValues.add(new ACR(v));
2134                        }
2135                }
2136
2137                if (jsonObject.get("token_endpoint_auth_methods_supported") != null) {
2138                        
2139                        op.tokenEndpointAuthMethods = new ArrayList<>();
2140                        
2141                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "token_endpoint_auth_methods_supported")) {
2142                                
2143                                if (v != null)
2144                                        op.tokenEndpointAuthMethods.add(ClientAuthenticationMethod.parse(v));
2145                        }
2146                }
2147                
2148                if (jsonObject.get("token_endpoint_auth_signing_alg_values_supported") != null) {
2149                        
2150                        op.tokenEndpointJWSAlgs = new ArrayList<>();
2151                        
2152                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "token_endpoint_auth_signing_alg_values_supported")) {
2153
2154                                if (v != null && v.equals(Algorithm.NONE.getName()))
2155                                        throw new ParseException("The none algorithm is not accepted");
2156                                
2157                                if (v != null)
2158                                        op.tokenEndpointJWSAlgs.add(JWSAlgorithm.parse(v));
2159                        }
2160                }
2161                
2162                
2163                // OpenID Connect request object
2164
2165                if (jsonObject.get("request_object_signing_alg_values_supported") != null) {
2166
2167                        op.requestObjectJWSAlgs = new ArrayList<>();
2168
2169                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "request_object_signing_alg_values_supported")) {
2170
2171                                if (v != null)
2172                                        op.requestObjectJWSAlgs.add(JWSAlgorithm.parse(v));
2173                        }
2174                }
2175
2176
2177                if (jsonObject.get("request_object_encryption_alg_values_supported") != null) {
2178
2179                        op.requestObjectJWEAlgs = new ArrayList<>();
2180
2181                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "request_object_encryption_alg_values_supported")) {
2182
2183                                if (v != null)
2184                                        op.requestObjectJWEAlgs.add(JWEAlgorithm.parse(v));
2185                        }
2186                }
2187
2188
2189                if (jsonObject.get("request_object_encryption_enc_values_supported") != null) {
2190
2191                        op.requestObjectJWEEncs = new ArrayList<>();
2192
2193                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "request_object_encryption_enc_values_supported")) {
2194
2195                                if (v != null)
2196                                        op.requestObjectJWEEncs.add(EncryptionMethod.parse(v));
2197                        }
2198                }
2199                
2200                
2201                // ID token
2202
2203                if (jsonObject.get("id_token_signing_alg_values_supported") != null) {
2204
2205                        op.idTokenJWSAlgs = new ArrayList<>();
2206
2207                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "id_token_signing_alg_values_supported")) {
2208
2209                                if (v != null)
2210                                        op.idTokenJWSAlgs.add(JWSAlgorithm.parse(v));
2211                        }
2212                }
2213
2214
2215                if (jsonObject.get("id_token_encryption_alg_values_supported") != null) {
2216
2217                        op.idTokenJWEAlgs = new ArrayList<>();
2218
2219                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "id_token_encryption_alg_values_supported")) {
2220
2221                                if (v != null)
2222                                        op.idTokenJWEAlgs.add(JWEAlgorithm.parse(v));
2223                        }
2224                }
2225
2226
2227                if (jsonObject.get("id_token_encryption_enc_values_supported") != null) {
2228
2229                        op.idTokenJWEEncs = new ArrayList<>();
2230
2231                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "id_token_encryption_enc_values_supported")) {
2232
2233                                if (v != null)
2234                                        op.idTokenJWEEncs.add(EncryptionMethod.parse(v));
2235                        }
2236                }
2237
2238                // UserInfo
2239
2240                if (jsonObject.get("userinfo_signing_alg_values_supported") != null) {
2241
2242                        op.userInfoJWSAlgs = new ArrayList<>();
2243
2244                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "userinfo_signing_alg_values_supported")) {
2245
2246                                if (v != null)
2247                                        op.userInfoJWSAlgs.add(JWSAlgorithm.parse(v));
2248                        }
2249                }
2250
2251
2252                if (jsonObject.get("userinfo_encryption_alg_values_supported") != null) {
2253
2254                        op.userInfoJWEAlgs = new ArrayList<>();
2255
2256                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "userinfo_encryption_alg_values_supported")) {
2257
2258                                if (v != null)
2259                                        op.userInfoJWEAlgs.add(JWEAlgorithm.parse(v));
2260                        }
2261                }
2262
2263
2264                if (jsonObject.get("userinfo_encryption_enc_values_supported") != null) {
2265
2266                        op.userInfoJWEEncs = new ArrayList<>();
2267
2268                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "userinfo_encryption_enc_values_supported")) {
2269
2270                                        if (v != null)
2271                                                op.userInfoJWEEncs.add(EncryptionMethod.parse(v));
2272                        }
2273                }
2274
2275                
2276                // Misc
2277
2278                if (jsonObject.get("display_values_supported") != null) {
2279
2280                        op.displays = new ArrayList<>();
2281
2282                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "display_values_supported")) {
2283
2284                                if (v != null)
2285                                        op.displays.add(Display.parse(v));
2286                        }
2287                }
2288                
2289                if (jsonObject.get("claim_types_supported") != null) {
2290                        
2291                        op.claimTypes = new ArrayList<>();
2292                        
2293                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "claim_types_supported")) {
2294                                
2295                                if (v != null)
2296                                        op.claimTypes.add(ClaimType.parse(v));
2297                        }
2298                }
2299
2300
2301                if (jsonObject.get("claims_supported") != null) {
2302
2303                        op.claims = new ArrayList<>();
2304
2305                        for (String v: JSONObjectUtils.getStringArray(jsonObject, "claims_supported")) {
2306
2307                                if (v != null)
2308                                        op.claims.add(v);
2309                        }
2310                }
2311                
2312                if (jsonObject.get("claims_locales_supported") != null) {
2313                        
2314                        op.claimsLocales = new ArrayList<>();
2315                        
2316                        for (String v : JSONObjectUtils.getStringArray(jsonObject, "claims_locales_supported")) {
2317                                
2318                                if (v != null) {
2319                                        
2320                                        try {
2321                                                op.claimsLocales.add(LangTag.parse(v));
2322                                        
2323                                        } catch (LangTagException e) {
2324                                                
2325                                                throw new ParseException("Invalid claims_locales_supported field: " + e.getMessage(), e);
2326                                        }
2327                                }
2328                        }
2329                }
2330                
2331                if (jsonObject.get("ui_locales_supported") != null) {
2332                        
2333                        op.uiLocales = new ArrayList<>();
2334                        
2335                        for (String v : JSONObjectUtils.getStringArray(jsonObject, "ui_locales_supported")) {
2336                                
2337                                if (v != null) {
2338                                        
2339                                        try {
2340                                                op.uiLocales.add(LangTag.parse(v));
2341                                        
2342                                        } catch (LangTagException e) {
2343                                                
2344                                                throw new ParseException("Invalid ui_locales_supported field: " + e.getMessage(), e);
2345                                        }
2346                                }
2347                        }
2348                }
2349
2350
2351                if (jsonObject.get("service_documentation") != null)
2352                        op.serviceDocsURI = JSONObjectUtils.getURI(jsonObject, "service_documentation");
2353                
2354                if (jsonObject.get("op_policy_uri") != null)
2355                        op.policyURI = JSONObjectUtils.getURI(jsonObject, "op_policy_uri");
2356                
2357                if (jsonObject.get("op_tos_uri") != null)
2358                        op.tosURI = JSONObjectUtils.getURI(jsonObject, "op_tos_uri");
2359                
2360                if (jsonObject.get("claims_parameter_supported") != null)
2361                        op.claimsParamSupported = JSONObjectUtils.getBoolean(jsonObject, "claims_parameter_supported");
2362                
2363                if (jsonObject.get("request_parameter_supported") != null)
2364                        op.requestParamSupported = JSONObjectUtils.getBoolean(jsonObject, "request_parameter_supported");
2365                
2366                if (jsonObject.get("request_uri_parameter_supported") != null)
2367                        op.requestURIParamSupported = JSONObjectUtils.getBoolean(jsonObject, "request_uri_parameter_supported");
2368                
2369                if (jsonObject.get("require_request_uri_registration") != null)
2370                        op.requireRequestURIReg = JSONObjectUtils.getBoolean(jsonObject, "require_request_uri_registration");
2371                
2372                // optional front and back-channel logout
2373                if (jsonObject.get("frontchannel_logout_supported") != null)
2374                        op.frontChannelLogoutSupported = JSONObjectUtils.getBoolean(jsonObject, "frontchannel_logout_supported");
2375                
2376                if (op.frontChannelLogoutSupported && jsonObject.get("frontchannel_logout_session_supported") != null)
2377                        op.frontChannelLogoutSessionSupported = JSONObjectUtils.getBoolean(jsonObject, "frontchannel_logout_session_supported");
2378                
2379                if (jsonObject.get("backchannel_logout_supported") != null)
2380                        op.backChannelLogoutSupported = JSONObjectUtils.getBoolean(jsonObject, "backchannel_logout_supported");
2381                
2382                if (op.frontChannelLogoutSupported && jsonObject.get("backchannel_logout_session_supported") != null)
2383                        op.backChannelLogoutSessionSupported = JSONObjectUtils.getBoolean(jsonObject, "backchannel_logout_session_supported");
2384                
2385                if (jsonObject.get("mutual_tls_sender_constrained_access_tokens") != null)
2386                        op.mutualTLSSenderConstrainedAccessTokens = JSONObjectUtils.getBoolean(jsonObject, "mutual_tls_sender_constrained_access_tokens");
2387                
2388                // Parse custom (not registered) parameters
2389                JSONObject customParams = new JSONObject(jsonObject);
2390                customParams.keySet().removeAll(REGISTERED_PARAMETER_NAMES);
2391                for (Map.Entry<String,Object> customEntry: customParams.entrySet()) {
2392                        op.setCustomParameter(customEntry.getKey(), customEntry.getValue());
2393                }
2394
2395                return op;
2396        }
2397
2398
2399        /**
2400         * Parses an OpenID Connect provider metadata from the specified JSON 
2401         * object string.
2402         *
2403         * @param s The JSON object sting to parse. Must not be {@code null}.
2404         *
2405         * @return The OpenID Connect provider metadata.
2406         *
2407         * @throws ParseException If the JSON object string couldn't be parsed
2408         *                        to an OpenID Connect provider metadata.
2409         */
2410        public static OIDCProviderMetadata parse(final String s)
2411                throws ParseException {
2412
2413                return parse(JSONObjectUtils.parse(s));
2414        }
2415        
2416        
2417        /**
2418         * Resolves OpenID Provider metadata from the specified issuer
2419         * identifier. The metadata is downloaded by HTTP GET from
2420         * {@code [issuer-url]/.well-known/openid-configuration}.
2421         *
2422         * @param issuer The OpenID Provider issuer identifier. Must represent
2423         *               a valid HTTPS or HTTP URL. Must not be {@code null}.
2424         *
2425         * @return The OpenID Provider metadata.
2426         *
2427         * @throws GeneralException If the issuer identifier or the downloaded
2428         *                          metadata are invalid.
2429         * @throws IOException      On a HTTP exception.
2430         */
2431        public static OIDCProviderMetadata resolve(final Issuer issuer)
2432                throws GeneralException, IOException {
2433                
2434                return resolve(issuer, 0, 0);
2435        }
2436        
2437        
2438        /**
2439         * Resolves OpenID Provider metadata from the specified issuer
2440         * identifier. The metadata is downloaded by HTTP GET from
2441         * {@code [issuer-url]/.well-known/openid-configuration}, using the
2442         * specified HTTP timeouts.
2443         *
2444         * @param issuer         The OpenID Provider issuer identifier. Must
2445         *                       represent a valid HTTPS or HTTP URL. Must not
2446         *                       be {@code null}.
2447         * @param connectTimeout The HTTP connect timeout, in milliseconds.
2448         *                       Zero implies no timeout. Must not be negative.
2449         * @param readTimeout    The HTTP response read timeout, in
2450         *                       milliseconds. Zero implies no timeout. Must
2451         *                       not be negative.
2452         *
2453         * @return The OpenID Provider metadata.
2454         *
2455         * @throws GeneralException If the issuer identifier or the downloaded
2456         *                          metadata are invalid.
2457         * @throws IOException      On a HTTP exception.
2458         */
2459        public static OIDCProviderMetadata resolve(final Issuer issuer,
2460                                                   final int connectTimeout,
2461                                                   final int readTimeout)
2462                throws GeneralException, IOException {
2463                
2464                URL configURL;
2465                
2466                try {
2467                        URL issuerURL = new URL(issuer.getValue());
2468                        
2469                        // Validate but don't insist on HTTPS, see
2470                        // http://openid.net/specs/openid-connect-core-1_0.html#Terminology
2471                        if (issuerURL.getQuery() != null && ! issuerURL.getQuery().trim().isEmpty()) {
2472                                throw new GeneralException("The issuer identifier must not contain a query component");
2473                        }
2474                        
2475                        if (issuerURL.getPath() != null && issuerURL.getPath().endsWith("/")) {
2476                                configURL = new URL(issuerURL + ".well-known/openid-configuration");
2477                        } else {
2478                                configURL = new URL(issuerURL + "/.well-known/openid-configuration");
2479                        }
2480                        
2481                } catch (MalformedURLException e) {
2482                        throw new GeneralException("The issuer identifier doesn't represent a valid URL: " + e.getMessage(), e);
2483                }
2484                
2485                HTTPRequest httpRequest = new HTTPRequest(HTTPRequest.Method.GET, configURL);
2486                httpRequest.setConnectTimeout(connectTimeout);
2487                httpRequest.setReadTimeout(readTimeout);
2488                
2489                HTTPResponse httpResponse = httpRequest.send();
2490                
2491                if (httpResponse.getStatusCode() != 200) {
2492                        throw new IOException("Couldn't download OpenID Provider metadata from " + configURL +
2493                                ": Status code " + httpResponse.getStatusCode());
2494                }
2495                
2496                JSONObject jsonObject = httpResponse.getContentAsJSONObject();
2497                
2498                return OIDCProviderMetadata.parse(jsonObject);
2499        }
2500}