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