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