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