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