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