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