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