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