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