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