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