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