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