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