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