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.client;
019
020
021import java.net.URI;
022import java.net.URISyntaxException;
023import java.util.*;
024
025import net.minidev.json.JSONArray;
026import net.minidev.json.JSONObject;
027
028import com.nimbusds.jose.EncryptionMethod;
029import com.nimbusds.jose.JWEAlgorithm;
030import com.nimbusds.jose.JWSAlgorithm;
031import com.nimbusds.jose.jwk.JWKSet;
032import com.nimbusds.langtag.LangTag;
033import com.nimbusds.langtag.LangTagUtils;
034import com.nimbusds.oauth2.sdk.GrantType;
035import com.nimbusds.oauth2.sdk.ParseException;
036import com.nimbusds.oauth2.sdk.ResponseType;
037import com.nimbusds.oauth2.sdk.Scope;
038import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
039import com.nimbusds.oauth2.sdk.id.Identifier;
040import com.nimbusds.oauth2.sdk.id.SoftwareID;
041import com.nimbusds.oauth2.sdk.id.SoftwareVersion;
042import com.nimbusds.oauth2.sdk.util.CollectionUtils;
043import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
044import com.nimbusds.oauth2.sdk.util.URIUtils;
045import com.nimbusds.openid.connect.sdk.federation.entities.EntityID;
046import com.nimbusds.openid.connect.sdk.federation.registration.ClientRegistrationType;
047
048
049/**
050 * Client metadata.
051 * 
052 * <p>Example client metadata, serialised to a JSON object:
053 * 
054 * <pre>
055 * {
056 *  "redirect_uris"              : ["https://client.example.org/callback",
057 *                                  "https://client.example.org/callback2"],
058 *  "client_name"                : "My Example Client",
059 *  "client_name#ja-Jpan-JP"     : "\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u540D",
060 *  "token_endpoint_auth_method" : "client_secret_basic",
061 *  "scope"                      : "read write dolphin",
062 *  "logo_uri"                   : "https://client.example.org/logo.png",
063 *  "jwks_uri"                   : "https://client.example.org/my_public_keys.jwks"
064 * }
065 * </pre>
066 * 
067 * <p>Related specifications:
068 *
069 * <ul>
070 *     <li>OAuth 2.0 Dynamic Client Registration Protocol (RFC 7591), section
071 *         2.
072 *     <li>OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound
073 *         Access Tokens (RFC 8705), sections 2.1.2 and 3.4.
074 *     <li>Financial-grade API: JWT Secured Authorization Response Mode for
075 *         OAuth 2.0 (JARM).
076 *     <li>OAuth 2.0 Pushed Authorization Requests (draft-ietf-oauth-par-02)
077 *     <li>OpenID Connect Federation 1.0 (draft 11)
078 * </ul>
079 */
080public class ClientMetadata {
081
082
083        /**
084         * The registered parameter names.
085         */
086        private static final Set<String> REGISTERED_PARAMETER_NAMES;
087        
088        
089        /**
090         * Prohibited URI schemes in redirection URIs. See
091         * https://security.lauritz-holtmann.de/post/sso-security-redirect-uri/.
092         */
093        public static final Set<String> PROHIBITED_REDIRECT_URI_SCHEMES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("data", "javascript", "vbscript")));
094
095
096        static {
097                Set<String> p = new HashSet<>();
098
099                p.add("redirect_uris");
100                p.add("scope");
101                p.add("response_types");
102                p.add("grant_types");
103                p.add("contacts");
104                p.add("client_name");
105                p.add("logo_uri");
106                p.add("client_uri");
107                p.add("policy_uri");
108                p.add("tos_uri");
109                p.add("token_endpoint_auth_method");
110                p.add("token_endpoint_auth_signing_alg");
111                p.add("jwks_uri");
112                p.add("jwks");
113                p.add("request_uris");
114                p.add("request_object_signing_alg");
115                p.add("request_object_encryption_alg");
116                p.add("request_object_encryption_enc");
117                p.add("require_pushed_authorization_requests");
118                p.add("software_id");
119                p.add("software_version");
120                p.add("tls_client_certificate_bound_access_tokens");
121                p.add("tls_client_auth_subject_dn");
122                p.add("tls_client_auth_san_dns");
123                p.add("tls_client_auth_san_uri");
124                p.add("tls_client_auth_san_ip");
125                p.add("tls_client_auth_san_email");
126                p.add("authorization_signed_response_alg");
127                p.add("authorization_encrypted_response_alg");
128                p.add("authorization_encrypted_response_enc");
129                
130                // OIDC federation
131                p.add("client_registration_types");
132                p.add("organization_name");
133                p.add("trust_anchor_id");
134
135                REGISTERED_PARAMETER_NAMES = Collections.unmodifiableSet(p);
136        }
137        
138        
139        /**
140         * Redirect URIs.
141         */
142        private Set<URI> redirectURIs;
143
144
145        /**
146         * The client OAuth 2.0 scope.
147         */
148        private Scope scope;
149
150
151        /**
152         * The expected OAuth 2.0 response types.
153         */
154        private Set<ResponseType> responseTypes;
155
156
157        /**
158         * The expected OAuth 2.0 grant types.
159         */
160        private Set<GrantType> grantTypes;
161
162
163        /**
164         * Administrator email contacts for the client.
165         */
166        private List<String> contacts;
167
168
169        /**
170         * The client name.
171         */
172        private final Map<LangTag,String> nameEntries;
173
174
175        /**
176         * The client application logo.
177         */
178        private final Map<LangTag,URI> logoURIEntries;
179
180
181        /**
182         * The client URI entries.
183         */
184        private final Map<LangTag,URI> uriEntries;
185
186
187        /**
188         * The client policy for use of end-user data.
189         */
190        private Map<LangTag,URI> policyURIEntries;
191
192
193        /**
194         * The client terms of service.
195         */
196        private final Map<LangTag,URI> tosURIEntries;
197
198
199        /**
200         * Token endpoint authentication method.
201         */
202        private ClientAuthenticationMethod authMethod;
203
204
205        /**
206         * The JSON Web Signature (JWS) algorithm required for
207         * {@code private_key_jwt} and {@code client_secret_jwt}
208         * authentication at the Token endpoint.
209         */
210        private JWSAlgorithm authJWSAlg;
211
212
213        /**
214         * URI for this client's JSON Web Key (JWK) set containing key(s) that
215         * are used in signing requests to the server and key(s) for encrypting
216         * responses.
217         */
218        private URI jwkSetURI;
219
220
221        /**
222         * Client's JSON Web Key (JWK) set containing key(s) that are used in
223         * signing requests to the server and key(s) for encrypting responses.
224         * Intended as an alternative to {@link #jwkSetURI} for native clients.
225         */
226        private JWKSet jwkSet;
227        
228        
229        /**
230         * Pre-registered request object URIs.
231         */
232        private Set<URI> requestObjectURIs;
233        
234        
235        /**
236         * The JSON Web Signature (JWS) algorithm required for request objects
237         * sent by this client.
238         */
239        private JWSAlgorithm requestObjectJWSAlg;
240        
241        
242        /**
243         * The JSON Web Encryption (JWE) algorithm required for request objects
244         * sent by this client.
245         */
246        private JWEAlgorithm requestObjectJWEAlg;
247        
248        
249        /**
250         * The JSON Web Encryption (JWE) method required for request objects
251         * sent by this client.
252         */
253        private EncryptionMethod requestObjectJWEEnc;
254
255
256        /**
257         * Identifier for the OAuth 2.0 client software.
258         */
259        private SoftwareID softwareID;
260
261
262        /**
263         * Version identifier for the OAuth 2.0 client software.
264         */
265        private SoftwareVersion softwareVersion;
266        
267        
268        /**
269         * Preference for TLS client certificate bound access tokens.
270         */
271        private boolean tlsClientCertificateBoundAccessTokens = false;
272        
273        
274        /**
275         * The expected subject distinguished name (DN) of the client X.509
276         * certificate the in mutual TLS authentication.
277         */
278        private String tlsClientAuthSubjectDN = null;
279        
280        
281        /**
282         * The expected dNSName SAN entry in the X.509 certificate, which
283         * the OAuth client will use in mutual TLS authentication.
284         */
285        private String tlsClientAuthSanDNS = null;
286        
287        
288        /**
289         * The expected uniformResourceIdentifier SAN entry in the X.509
290         * certificate, which the OAuth client will use in mutual TLS
291         * authentication.
292         */
293        private String tlsClientAuthSanURI = null;
294        
295        
296        /**
297         * The expected iPAddress SAN entry in the X.509 certificate, which
298         * the OAuth client will use in mutual TLS authentication.
299         */
300        private String tlsClientAuthSanIP = null;
301        
302        
303        /**
304         * The expected rfc822Name SAN entry in the X.509 certificate, which
305         * the OAuth client will use in mutual TLS authentication.
306         */
307        private String tlsClientAuthSanEmail = null;
308        
309        
310        /**
311         * The JWS algorithm for JWT-encoded authorisation responses.
312         */
313        private JWSAlgorithm authzJWSAlg;
314        
315        
316        /**
317         * The JWE algorithm for JWT-encoded authorisation responses.
318         */
319        private JWEAlgorithm authzJWEAlg;
320        
321        
322        /**
323         * The encryption method for JWT-encoded authorisation responses.
324         */
325        private EncryptionMethod authzJWEEnc;
326        
327        
328        /**
329         * If {@code true} PAR is required, else not.
330         */
331        private boolean requirePAR = false;
332        
333        
334        /**
335         * The supported OpenID Connect Federation 1.0 client registration
336         * types.
337         */
338        private List<ClientRegistrationType> clientRegistrationTypes;
339        
340        
341        /**
342         * The organisation name in OpenID Connect Federation 1.0.
343         */
344        private String organizationName;
345        
346        
347        /**
348         * The used trust anchor in a explicit client registration in OpenID
349         * Connect Federation 1.0.
350         */
351        private EntityID trustAnchorID;
352
353
354        /**
355         * The custom metadata fields.
356         */
357        private JSONObject customFields;
358
359
360        /**
361         * Creates a new OAuth 2.0 client metadata instance.
362         */
363        public ClientMetadata() {
364
365                nameEntries = new HashMap<>();
366                logoURIEntries = new HashMap<>();
367                uriEntries = new HashMap<>();
368                policyURIEntries = new HashMap<>();
369                policyURIEntries = new HashMap<>();
370                tosURIEntries = new HashMap<>();
371                customFields = new JSONObject();
372        }
373
374
375        /**
376         * Creates a shallow copy of the specified OAuth 2.0 client metadata
377         * instance.
378         *
379         * @param metadata The client metadata to copy. Must not be
380         *                 {@code null}.
381         */
382        public ClientMetadata(final ClientMetadata metadata) {
383
384                redirectURIs = metadata.redirectURIs;
385                scope = metadata.scope;
386                responseTypes = metadata.responseTypes;
387                grantTypes = metadata.grantTypes;
388                contacts = metadata.contacts;
389                nameEntries = metadata.nameEntries;
390                logoURIEntries = metadata.logoURIEntries;
391                uriEntries = metadata.uriEntries;
392                policyURIEntries = metadata.policyURIEntries;
393                tosURIEntries = metadata.tosURIEntries;
394                authMethod = metadata.authMethod;
395                authJWSAlg = metadata.authJWSAlg;
396                jwkSetURI = metadata.jwkSetURI;
397                jwkSet = metadata.getJWKSet();
398                requestObjectURIs = metadata.requestObjectURIs;
399                requestObjectJWSAlg = metadata.requestObjectJWSAlg;
400                requestObjectJWEAlg = metadata.requestObjectJWEAlg;
401                requestObjectJWEEnc = metadata.requestObjectJWEEnc;
402                softwareID = metadata.softwareID;
403                softwareVersion = metadata.softwareVersion;
404                tlsClientCertificateBoundAccessTokens = metadata.tlsClientCertificateBoundAccessTokens;
405                tlsClientAuthSubjectDN = metadata.tlsClientAuthSubjectDN;
406                tlsClientAuthSanDNS = metadata.tlsClientAuthSanDNS;
407                tlsClientAuthSanURI = metadata.tlsClientAuthSanURI;
408                tlsClientAuthSanIP = metadata.tlsClientAuthSanIP;
409                tlsClientAuthSanEmail = metadata.tlsClientAuthSanEmail;
410                authzJWSAlg = metadata.authzJWSAlg;
411                authzJWEAlg = metadata.authzJWEAlg;
412                authzJWEEnc = metadata.authzJWEEnc;
413                requirePAR = metadata.requirePAR;
414                clientRegistrationTypes = metadata.clientRegistrationTypes;
415                organizationName = metadata.organizationName;
416                trustAnchorID = metadata.trustAnchorID;
417                customFields = metadata.customFields;
418        }
419
420
421        /**
422         * Gets the registered (standard) OAuth 2.0 client metadata parameter
423         * names.
424         *
425         * @return The registered parameter names, as an unmodifiable set.
426         */
427        public static Set<String> getRegisteredParameterNames() {
428
429                return REGISTERED_PARAMETER_NAMES;
430        }
431
432
433        /**
434         * Gets the redirection URIs for this client. Corresponds to the
435         * {@code redirect_uris} client metadata field.
436         *
437         * @return The redirection URIs, {@code null} if not specified.
438         */
439        public Set<URI> getRedirectionURIs() {
440
441                return redirectURIs;
442        }
443        
444        
445        /**
446         * Gets one of the redirection URIs for this client. Corresponds to the
447         * {@code redirect_uris} client metadata field.
448         *
449         * @return The redirection URI, {@code null} if not specified.
450         */
451        public URI getRedirectionURI() {
452                
453                if (redirectURIs != null && ! redirectURIs.isEmpty()) {
454                        return redirectURIs.iterator().next();
455                } else {
456                        return null;
457                }
458        }
459
460
461        /**
462         * Gets the redirection URIs for this client as strings. Corresponds to
463         * the {@code redirect_uris} client metadata field.
464         *
465         * <p>This short-hand method is intended to enable string-based URI
466         * comparison.
467         *
468         * @return The redirection URIs as strings, {@code null} if not
469         *         specified.
470         */
471        public Set<String> getRedirectionURIStrings() {
472
473                if (redirectURIs == null)
474                        return null;
475
476                Set<String> uriStrings = new HashSet<>();
477
478                for (URI uri: redirectURIs)
479                        uriStrings.add(uri.toString());
480
481                return uriStrings;
482        }
483
484
485        /**
486         * Sets the redirection URIs for this client. Corresponds to the
487         * {@code redirect_uris} client metadata field.
488         *
489         * @param redirectURIs The redirection URIs, {@code null} if not
490         *                     specified. Valid redirection URIs must not
491         *                     contain a fragment.
492         */
493        public void setRedirectionURIs(final Set<URI> redirectURIs) {
494
495                if (redirectURIs != null) {
496                        // check URIs
497                        for (URI uri: redirectURIs) {
498                                if (uri == null) {
499                                        throw new IllegalArgumentException("The redirect_uri must not be null");
500                                }
501                                if (uri.getFragment() != null) {
502                                        throw new IllegalArgumentException("The redirect_uri must not contain fragment");
503                                }
504                                URIUtils.ensureSchemeIsNotProhibited(uri, PROHIBITED_REDIRECT_URI_SCHEMES);
505                        }
506                        this.redirectURIs = Collections.unmodifiableSet(redirectURIs);
507                } else {
508                        this.redirectURIs = null;
509                }
510        }
511
512
513        /**
514         * Sets a single redirection URI for this client. Corresponds to the
515         * {@code redirect_uris} client metadata field.
516         *
517         * @param redirectURI The redirection URIs, {@code null} if not
518         *                    specified. A valid redirection URI must not
519         *                    contain a fragment.
520         */
521        public void setRedirectionURI(final URI redirectURI) {
522
523                setRedirectionURIs(redirectURI != null ? Collections.singleton(redirectURI) : null);
524        }
525
526
527        /**
528         * Gets the scope values that the client can use when requesting access
529         * tokens. Corresponds to the {@code scope} client metadata field.
530         *
531         * @return The scope, {@code null} if not specified.
532         */
533        public Scope getScope() {
534
535                return scope;
536        }
537
538
539        /**
540         * Checks if the scope matadata field is set and contains the specified
541         * scope value.
542         *
543         * @param scopeValue The scope value. Must not be {@code null}.
544         *
545         * @return {@code true} if the scope value is contained, else
546         *         {@code false}.
547         */
548        public boolean hasScopeValue(final Scope.Value scopeValue) {
549
550                return scope != null && scope.contains(scopeValue);
551        }
552
553
554        /**
555         * Sets the scope values that the client can use when requesting access
556         * tokens. Corresponds to the {@code scope} client metadata field.
557         *
558         * @param scope The scope, {@code null} if not specified.
559         */
560        public void setScope(final Scope scope) {
561
562                this.scope = scope;
563        }
564
565
566        /**
567         * Gets the expected OAuth 2.0 response types. Corresponds to the
568         * {@code response_types} client metadata field.
569         *
570         * @return The response types, {@code null} if not specified.
571         */
572        public Set<ResponseType> getResponseTypes() {
573
574                return responseTypes;
575        }
576
577
578        /**
579         * Sets the expected OAuth 2.0 response types. Corresponds to the
580         * {@code response_types} client metadata field.
581         *
582         * @param responseTypes The response types, {@code null} if not
583         *                      specified.
584         */
585        public void setResponseTypes(final Set<ResponseType> responseTypes) {
586
587                this.responseTypes = responseTypes;
588        }
589
590
591        /**
592         * Gets the expected OAuth 2.0 grant types. Corresponds to the
593         * {@code grant_types} client metadata field.
594         *
595         * @return The grant types, {@code null} if not specified.
596         */
597        public Set<GrantType> getGrantTypes() {
598
599                return grantTypes;
600        }
601
602
603        /**
604         * Sets the expected OAuth 2.0 grant types. Corresponds to the
605         * {@code grant_types} client metadata field.
606         *
607         * @param grantTypes The grant types, {@code null} if not specified.
608         */
609        public void setGrantTypes(final Set<GrantType> grantTypes) {
610
611                this.grantTypes = grantTypes;
612        }
613
614
615        /**
616         * Gets the administrator email contacts for the client. Corresponds to
617         * the {@code contacts} client metadata field.
618         *
619         * @return The administrator email contacts, {@code null} if not
620         *         specified.
621         */
622        public List<String> getEmailContacts() {
623
624                return contacts;
625        }
626
627
628        /**
629         * Sets the administrator email contacts for the client. Corresponds to
630         * the {@code contacts} client metadata field.
631         *
632         * @param contacts The administrator email contacts, {@code null} if
633         *                 not specified.
634         */
635        public void setEmailContacts(final List<String> contacts) {
636
637                this.contacts = contacts;
638        }
639
640
641        /**
642         * Gets the client name. Corresponds to the {@code client_name} client
643         * metadata field, with no language tag.
644         *
645         * @return The client name, {@code null} if not specified.
646         */
647        public String getName() {
648
649                return getName(null);
650        }
651
652
653        /**
654         * Gets the client name. Corresponds to the {@code client_name} client
655         * metadata field, with an optional language tag.
656         *
657         * @param langTag The language tag of the entry, {@code null} to get
658         *                the non-tagged entry.
659         *
660         * @return The client name, {@code null} if not specified.
661         */
662        public String getName(final LangTag langTag) {
663
664                return nameEntries.get(langTag);
665        }
666
667
668        /**
669         * Gets the client name entries. Corresponds to the {@code client_name}
670         * client metadata field.
671         *
672         * @return The client name entries, empty map if none.
673         */
674        public Map<LangTag,String> getNameEntries() {
675
676                return nameEntries;
677        }
678
679
680        /**
681         * Sets the client name. Corresponds to the {@code client_name} client
682         * metadata field, with no language tag.
683         *
684         * @param name The client name, {@code null} if not specified.
685         */
686        public void setName(final String name) {
687
688                nameEntries.put(null, name);
689        }
690
691
692        /**
693         * Sets the client name. Corresponds to the {@code client_name} client
694         * metadata field, with an optional language tag.
695         *
696         * @param name    The client name. Must not be {@code null}.
697         * @param langTag The language tag, {@code null} if not specified.
698         */
699        public void setName(final String name, final LangTag langTag) {
700
701                nameEntries.put(langTag, name);
702        }
703
704
705        /**
706         * Gets the client application logo. Corresponds to the
707         * {@code logo_uri} client metadata field, with no language
708         * tag.
709         *
710         * @return The logo URI, {@code null} if not specified.
711         */
712        public URI getLogoURI() {
713
714                return getLogoURI(null);
715        }
716
717
718        /**
719         * Gets the client application logo. Corresponds to the
720         * {@code logo_uri} client metadata field, with an optional
721         * language tag.
722         *
723         * @param langTag The language tag, {@code null} if not specified.
724         *
725         * @return The logo URI, {@code null} if not specified.
726         */
727        public URI getLogoURI(final LangTag langTag) {
728
729                return logoURIEntries.get(langTag);
730        }
731
732
733        /**
734         * Gets the client application logo entries. Corresponds to the
735         * {@code logo_uri} client metadata field.
736         *
737         * @return The logo URI entries, empty map if none.
738         */
739        public Map<LangTag,URI> getLogoURIEntries() {
740
741                return logoURIEntries;
742        }
743
744
745        /**
746         * Sets the client application logo. Corresponds to the
747         * {@code logo_uri} client metadata field, with no language
748         * tag.
749         *
750         * @param logoURI The logo URI, {@code null} if not specified.
751         */
752        public void setLogoURI(final URI logoURI) {
753
754                logoURIEntries.put(null, logoURI);
755        }
756
757
758        /**
759         * Sets the client application logo. Corresponds to the
760         * {@code logo_uri} client metadata field, with an optional
761         * language tag.
762         *
763         * @param logoURI The logo URI. Must not be {@code null}.
764         * @param langTag The language tag, {@code null} if not specified.
765         */
766        public void setLogoURI(final URI logoURI, final LangTag langTag) {
767
768                logoURIEntries.put(langTag, logoURI);
769        }
770
771
772        /**
773         * Gets the client home page. Corresponds to the {@code client_uri}
774         * client metadata field, with no language tag.
775         *
776         * @return The client URI, {@code null} if not specified.
777         */
778        public URI getURI() {
779
780                return getURI(null);
781        }
782
783
784        /**
785         * Gets the client home page. Corresponds to the {@code client_uri}
786         * client metadata field, with an optional language tag.
787         *
788         * @param langTag The language tag, {@code null} if not specified.
789         *
790         * @return The client URI, {@code null} if not specified.
791         */
792        public URI getURI(final LangTag langTag) {
793
794                return uriEntries.get(langTag);
795        }
796
797
798        /**
799         * Gets the client home page entries. Corresponds to the
800         * {@code client_uri} client metadata field.
801         *
802         * @return The client URI entries, empty map if none.
803         */
804        public Map<LangTag,URI> getURIEntries() {
805
806                return uriEntries;
807        }
808
809
810        /**
811         * Sets the client home page. Corresponds to the {@code client_uri}
812         * client metadata field, with no language tag.
813         *
814         * @param uri The client URI, {@code null} if not specified. The URI
815         *            scheme must be https or http.
816         */
817        public void setURI(final URI uri) {
818
819                URIUtils.ensureSchemeIsHTTPSorHTTP(uri);
820                uriEntries.put(null, uri);
821        }
822
823
824        /**
825         * Sets the client home page. Corresponds to the {@code client_uri}
826         * client metadata field, with an optional language tag.
827         *
828         * @param uri     The URI. The URI scheme must be https or http. Must
829         *                not be {@code null}.
830         * @param langTag The language tag, {@code null} if not specified.
831         */
832        public void setURI(final URI uri, final LangTag langTag) {
833                
834                URIUtils.ensureSchemeIsHTTPSorHTTP(uri);
835                uriEntries.put(langTag, uri);
836        }
837
838
839        /**
840         * Gets the client policy for use of end-user data. Corresponds to the
841         * {@code policy_uri} client metadata field, with no language
842         * tag.
843         *
844         * @return The policy URI, {@code null} if not specified.
845         */
846        public URI getPolicyURI() {
847
848                return getPolicyURI(null);
849        }
850
851
852        /**
853         * Gets the client policy for use of end-user data. Corresponds to the
854         * {@code policy_uri} client metadata field, with an optional
855         * language tag.
856         *
857         * @param langTag The language tag, {@code null} if not specified.
858         *
859         * @return The policy URI, {@code null} if not specified.
860         */
861        public URI getPolicyURI(final LangTag langTag) {
862
863                return policyURIEntries.get(langTag);
864        }
865
866
867        /**
868         * Gets the client policy entries for use of end-user data.
869         * Corresponds to the {@code policy_uri} client metadata field.
870         *
871         * @return The policy URI entries, empty map if none.
872         */
873        public Map<LangTag,URI> getPolicyURIEntries() {
874
875                return policyURIEntries;
876        }
877
878
879        /**
880         * Sets the client policy for use of end-user data. Corresponds to the
881         * {@code policy_uri} client metadata field, with no language
882         * tag.
883         *
884         * @param policyURI The policy URI, {@code null} if not specified. The
885         *                  URI scheme must be https or http.
886         */
887        public void setPolicyURI(final URI policyURI) {
888
889                URIUtils.ensureSchemeIsHTTPSorHTTP(policyURI);
890                policyURIEntries.put(null, policyURI);
891        }
892
893
894        /**
895         * Sets the client policy for use of end-user data. Corresponds to the
896         * {@code policy_uri} client metadata field, with an optional
897         * language tag.
898         *
899         * @param policyURI The policy URI. The URI scheme must be https or
900         *                  http. Must not be {@code null}.
901         * @param langTag   The language tag, {@code null} if not specified.
902         */
903        public void setPolicyURI(final URI policyURI, final LangTag langTag) {
904
905                URIUtils.ensureSchemeIsHTTPSorHTTP(policyURI);
906                policyURIEntries.put(langTag, policyURI);
907        }
908
909
910        /**
911         * Gets the client's terms of service. Corresponds to the
912         * {@code tos_uri} client metadata field, with no language
913         * tag.
914         *
915         * @return The terms of service URI, {@code null} if not specified.
916         */
917        public URI getTermsOfServiceURI() {
918
919                return getTermsOfServiceURI(null);
920        }
921
922
923        /**
924         * Gets the client's terms of service. Corresponds to the
925         * {@code tos_uri} client metadata field, with an optional
926         * language tag.
927         *
928         * @param langTag The language tag, {@code null} if not specified.
929         *
930         * @return The terms of service URI, {@code null} if not specified.
931         */
932        public URI getTermsOfServiceURI(final LangTag langTag) {
933
934                return tosURIEntries.get(langTag);
935        }
936
937
938        /**
939         * Gets the client's terms of service entries. Corresponds to the
940         * {@code tos_uri} client metadata field.
941         *
942         * @return The terms of service URI entries, empty map if none.
943         */
944        public Map<LangTag,URI> getTermsOfServiceURIEntries() {
945
946                return tosURIEntries;
947        }
948
949
950        /**
951         * Sets the client's terms of service. Corresponds to the
952         * {@code tos_uri} client metadata field, with no language
953         * tag.
954         *
955         * @param tosURI The terms of service URI, {@code null} if not
956         *               specified. The URI scheme must be https or http.
957         */
958        public void setTermsOfServiceURI(final URI tosURI) {
959
960                URIUtils.ensureSchemeIsHTTPSorHTTP(tosURI);
961                tosURIEntries.put(null, tosURI);
962        }
963
964
965        /**
966         * Sets the client's terms of service. Corresponds to the
967         * {@code tos_uri} client metadata field, with an optional
968         * language tag.
969         *
970         * @param tosURI  The terms of service URI. The URI scheme must not be
971         *                https or http. Must not be {@code null}.
972         * @param langTag The language tag, {@code null} if not specified.
973         */
974        public void setTermsOfServiceURI(final URI tosURI, final LangTag langTag) {
975                
976                URIUtils.ensureSchemeIsHTTPSorHTTP(tosURI);
977                tosURIEntries.put(langTag, tosURI);
978        }
979
980
981        /**
982         * Gets the Token endpoint authentication method. Corresponds to the
983         * {@code token_endpoint_auth_method} client metadata field.
984         *
985         * @return The Token endpoint authentication method, {@code null} if
986         *         not specified.
987         */
988        public ClientAuthenticationMethod getTokenEndpointAuthMethod() {
989
990                return authMethod;
991        }
992
993
994        /**
995         * Sets the Token endpoint authentication method. Corresponds to the
996         * {@code token_endpoint_auth_method} client metadata field.
997         *
998         * @param authMethod The Token endpoint authentication  method,
999         *                   {@code null} if not specified.
1000         */
1001        public void setTokenEndpointAuthMethod(final ClientAuthenticationMethod authMethod) {
1002
1003                this.authMethod = authMethod;
1004        }
1005
1006
1007        /**
1008         * Gets the JSON Web Signature (JWS) algorithm required for
1009         * {@code private_key_jwt} and {@code client_secret_jwt}
1010         * authentication at the Token endpoint. Corresponds to the
1011         * {@code token_endpoint_auth_signing_alg} client metadata field.
1012         *
1013         * @return The JWS algorithm, {@code null} if not specified.
1014         */
1015        public JWSAlgorithm getTokenEndpointAuthJWSAlg() {
1016
1017                return authJWSAlg;
1018        }
1019
1020
1021        /**
1022         * Sets the JSON Web Signature (JWS) algorithm required for
1023         * {@code private_key_jwt} and {@code client_secret_jwt}
1024         * authentication at the Token endpoint. Corresponds to the
1025         * {@code token_endpoint_auth_signing_alg} client metadata field.
1026         *
1027         * @param authJWSAlg The JWS algorithm, {@code null} if not specified.
1028         */
1029        public void setTokenEndpointAuthJWSAlg(final JWSAlgorithm authJWSAlg) {
1030
1031                this.authJWSAlg = authJWSAlg;
1032        }
1033
1034
1035        /**
1036         * Gets the URI for this client's JSON Web Key (JWK) set containing
1037         * key(s) that are used in signing requests to the server and key(s)
1038         * for encrypting responses. Corresponds to the {@code jwks_uri} client
1039         * metadata field.
1040         *
1041         * @return The JWK set URI, {@code null} if not specified.
1042         */
1043        public URI getJWKSetURI() {
1044
1045                return jwkSetURI;
1046        }
1047
1048
1049        /**
1050         * Sets the URI for this client's JSON Web Key (JWK) set containing
1051         * key(s) that are used in signing requests to the server and key(s)
1052         * for encrypting responses. Corresponds to the {@code jwks_uri} client
1053         * metadata field.
1054         *
1055         * @param jwkSetURI The JWK set URI, {@code null} if not specified.
1056         */
1057        public void setJWKSetURI(final URI jwkSetURI) {
1058
1059                this.jwkSetURI = jwkSetURI;
1060        }
1061
1062
1063        /**
1064         * Gets this client's JSON Web Key (JWK) set containing key(s) that are
1065         * used in signing requests to the server and key(s) for encrypting
1066         * responses. Intended as an alternative to {@link #getJWKSetURI} for
1067         * native clients. Corresponds to the {@code jwks} client metadata
1068         * field.
1069         *
1070         * @return The JWK set, {@code null} if not specified.
1071         */
1072        public JWKSet getJWKSet() {
1073
1074                return jwkSet;
1075        }
1076
1077
1078        /**
1079         * Sets this client's JSON Web Key (JWK) set containing key(s) that are
1080         * used in signing requests to the server and key(s) for encrypting
1081         * responses. Intended as an alternative to {@link #getJWKSetURI} for
1082         * native clients. Corresponds to the {@code jwks} client metadata
1083         * field.
1084         *
1085         * @param jwkSet The JWK set, {@code null} if not specified.
1086         */
1087        public void setJWKSet(final JWKSet jwkSet) {
1088
1089                this.jwkSet = jwkSet;
1090        }
1091        
1092        
1093        /**
1094         * Gets the pre-registered request object URIs. Corresponds to the
1095         * {@code request_uris} client metadata field.
1096         *
1097         * @return The request object URIs, {@code null} if not specified.
1098         */
1099        public Set<URI> getRequestObjectURIs() {
1100                
1101                return requestObjectURIs;
1102        }
1103        
1104        
1105        /**
1106         * Sets the pre-registered request object URIs. Corresponds to the
1107         * {@code request_uris} client metadata field.
1108         *
1109         * @param requestObjectURIs The request object URIs, {@code null} if
1110         *                          not specified.
1111         */
1112        public void setRequestObjectURIs(final Set<URI> requestObjectURIs) {
1113                
1114                this.requestObjectURIs = requestObjectURIs;
1115        }
1116        
1117        
1118        /**
1119         * Gets the JSON Web Signature (JWS) algorithm required for request
1120         * objects sent by this client. Corresponds to the
1121         * {@code request_object_signing_alg} client metadata field.
1122         *
1123         * @return The JWS algorithm, {@code null} if not specified.
1124         */
1125        public JWSAlgorithm getRequestObjectJWSAlg() {
1126                
1127                return requestObjectJWSAlg;
1128        }
1129        
1130        
1131        /**
1132         * Sets the JSON Web Signature (JWS) algorithm required for request
1133         * objects sent by this client. Corresponds to the
1134         * {@code request_object_signing_alg} client metadata field.
1135         *
1136         * @param requestObjectJWSAlg The JWS algorithm, {@code null} if not
1137         *                            specified.
1138         */
1139        public void setRequestObjectJWSAlg(final JWSAlgorithm requestObjectJWSAlg) {
1140                
1141                this.requestObjectJWSAlg = requestObjectJWSAlg;
1142        }
1143        
1144        
1145        /**
1146         * Gets the JSON Web Encryption (JWE) algorithm required for request
1147         * objects sent by this client. Corresponds to the
1148         * {@code request_object_encryption_alg} client metadata field.
1149         *
1150         * @return The JWE algorithm, {@code null} if not specified.
1151         */
1152        public JWEAlgorithm getRequestObjectJWEAlg() {
1153                
1154                return requestObjectJWEAlg;
1155        }
1156        
1157        
1158        /**
1159         * Sets the JSON Web Encryption (JWE) algorithm required for request
1160         * objects sent by this client. Corresponds to the
1161         * {@code request_object_encryption_alg} client metadata field.
1162         *
1163         * @param requestObjectJWEAlg The JWE algorithm, {@code null} if not
1164         *                            specified.
1165         */
1166        public void setRequestObjectJWEAlg(final JWEAlgorithm requestObjectJWEAlg) {
1167                
1168                this.requestObjectJWEAlg = requestObjectJWEAlg;
1169        }
1170        
1171        
1172        /**
1173         * Gets the JSON Web Encryption (JWE) method required for request
1174         * objects sent by this client. Corresponds to the
1175         * {@code request_object_encryption_enc} client metadata field.
1176         *
1177         * @return The JWE method, {@code null} if not specified.
1178         */
1179        public EncryptionMethod getRequestObjectJWEEnc() {
1180                
1181                return requestObjectJWEEnc;
1182        }
1183        
1184        
1185        /**
1186         * Sets the JSON Web Encryption (JWE) method required for request
1187         * objects sent by this client. Corresponds to the
1188         * {@code request_object_encryption_enc} client metadata field.
1189         *
1190         * @param requestObjectJWEEnc The JWE method, {@code null} if not
1191         *                            specified.
1192         */
1193        public void setRequestObjectJWEEnc(final EncryptionMethod requestObjectJWEEnc) {
1194                
1195                this.requestObjectJWEEnc = requestObjectJWEEnc;
1196        }
1197
1198
1199        /**
1200         * Gets the identifier for the OAuth 2.0 client software. Corresponds
1201         * to the {@code software_id} client metadata field.
1202         *
1203         * @return The software identifier, {@code null} if not specified.
1204         */
1205        public SoftwareID getSoftwareID() {
1206
1207                return softwareID;
1208        }
1209
1210
1211        /**
1212         * Sets the identifier for the OAuth 2.0 client software. Corresponds
1213         * to the {@code software_id} client metadata field.
1214         *
1215         * @param softwareID The software identifier, {@code null} if not
1216         *                   specified.
1217         */
1218        public void setSoftwareID(final SoftwareID softwareID) {
1219
1220                this.softwareID = softwareID;
1221        }
1222
1223
1224        /**
1225         * Gets the version identifier for the OAuth 2.0 client software.
1226         * Corresponds to the {@code software_version} client metadata field.
1227         *
1228         * @return The version identifier, {@code null} if not specified.
1229         */
1230        public SoftwareVersion getSoftwareVersion() {
1231
1232                return softwareVersion;
1233        }
1234
1235
1236        /**
1237         * Sets the version identifier for the OAuth 2.0 client software.
1238         * Corresponds to the {@code software_version} client metadata field.
1239         *
1240         * @param softwareVersion The version identifier, {@code null} if not
1241         *                        specified.
1242         */
1243        public void setSoftwareVersion(final SoftwareVersion softwareVersion) {
1244
1245                this.softwareVersion = softwareVersion;
1246        }
1247        
1248        
1249        /**
1250         * Sets the preference for TLS client certificate bound access tokens.
1251         * Corresponds to the
1252         * {@code tls_client_certificate_bound_access_tokens} client metadata
1253         * field.
1254         *
1255         * @return {@code true} indicates a preference for TLS client
1256         *         certificate bound access tokens, {@code false} if none.
1257         */
1258        public boolean getTLSClientCertificateBoundAccessTokens() {
1259                
1260                return tlsClientCertificateBoundAccessTokens;
1261        }
1262        
1263        
1264        /**
1265         * Gets the preference for TLS client certificate bound access tokens.
1266         * Corresponds to the
1267         * {@code tls_client_certificate_bound_access_tokens} client metadata
1268         * field.
1269         *
1270         * @param tlsClientCertBoundTokens {@code true} indicates a preference
1271         *                                 for TLS client certificate bound
1272         *                                 access tokens, {@code false} if
1273         *                                 none.
1274         */
1275        public void setTLSClientCertificateBoundAccessTokens(final boolean tlsClientCertBoundTokens) {
1276                
1277                tlsClientCertificateBoundAccessTokens = tlsClientCertBoundTokens;
1278        }
1279        
1280        
1281        /**
1282         * Sets the preference for TLS client certificate bound access tokens.
1283         * Corresponds to the
1284         * {@code tls_client_certificate_bound_access_tokens} client metadata
1285         * field.
1286         *
1287         * @return {@code true} indicates a preference for TLS client
1288         *         certificate bound access tokens, {@code false} if none.
1289         */
1290        @Deprecated
1291        public boolean getMutualTLSSenderConstrainedAccessTokens() {
1292                
1293                return tlsClientCertificateBoundAccessTokens;
1294        }
1295        
1296        
1297        /**
1298         * Gets the preference for TLS client certificate bound access tokens.
1299         * Corresponds to the
1300         * {@code tls_client_certificate_bound_access_tokens} client metadata
1301         * field.
1302         *
1303         * @param tlsSenderAccessTokens {@code true} indicates a preference for
1304         *                              TLS client certificate bound access
1305         *                              tokens, {@code false} if none.
1306         */
1307        @Deprecated
1308        public void setMutualTLSSenderConstrainedAccessTokens(final boolean tlsSenderAccessTokens) {
1309                
1310                tlsClientCertificateBoundAccessTokens = tlsSenderAccessTokens;
1311        }
1312        
1313        
1314        /**
1315         * Gets the expected subject distinguished name (DN) of the client
1316         * X.509 certificate in mutual TLS authentication. Corresponds to the
1317         * {@code tls_client_auth_subject_dn} client metadata field.
1318         *
1319         * @return The expected subject distinguished name (DN) of the client
1320         *         X.509 certificate, {@code null} if not specified.
1321         */
1322        public String getTLSClientAuthSubjectDN() {
1323                
1324                return tlsClientAuthSubjectDN;
1325        }
1326        
1327        
1328        /**
1329         * Sets the expected subject distinguished name (DN) of the client
1330         * X.509 certificate in mutual TLS authentication. Corresponds to the
1331         * {@code tls_client_auth_subject_dn} client metadata field.
1332         *
1333         * @param subjectDN The expected subject distinguished name (DN) of the
1334         *                  client X.509 certificate, {@code null} if not
1335         *                  specified.
1336         */
1337        public void setTLSClientAuthSubjectDN(final String subjectDN) {
1338                
1339                this.tlsClientAuthSubjectDN = subjectDN;
1340        }
1341        
1342        
1343        /**
1344         * Gets the expected dNSName SAN entry in the X.509 certificate, which
1345         * the OAuth client will use in mutual TLS authentication. Corresponds
1346         * to the {@code tls_client_auth_san_dns} client metadata field.
1347         *
1348         * @return The expected dNSName SAN entry in the X.509 certificate,
1349         *         {@code null} if not specified.
1350         */
1351        public String getTLSClientAuthSanDNS() {
1352                
1353                return tlsClientAuthSanDNS;
1354        }
1355        
1356        
1357        /**
1358         * Sets the expected dNSName SAN entry in the X.509 certificate, which
1359         * the OAuth client will use in mutual TLS authentication. Corresponds
1360         * to the {@code tls_client_auth_san_dns} client metadata field.
1361         *
1362         * @param dns The expected dNSName SAN entry in the X.509 certificate,
1363         *            {@code null} if not specified.
1364         */
1365        public void setTLSClientAuthSanDNS(final String dns) {
1366                
1367                this.tlsClientAuthSanDNS = dns;
1368        }
1369        
1370        
1371        /**
1372         * Gets the expected uniformResourceIdentifier SAN entry in the X.509
1373         * certificate, which the OAuth client will use in mutual TLS
1374         * authentication. Corresponds to the {@code tls_client_auth_san_uri}
1375         * client metadata field.
1376         *
1377         * @return The expected uniformResourceIdentifier SAN entry in the X.509
1378         *         certificate, {@code null} if not specified.
1379         */
1380        public String getTLSClientAuthSanURI() {
1381                
1382                return tlsClientAuthSanURI;
1383        }
1384        
1385        
1386        /**
1387         * Sets the expected uniformResourceIdentifier SAN entry in the X.509
1388         * certificate, which the OAuth client will use in mutual TLS
1389         * authentication. Corresponds to the {@code tls_client_auth_san_uri}
1390         * client metadata field.
1391         *
1392         * @param uri The expected uniformResourceIdentifier SAN entry in the X.509
1393         *            certificate, {@code null} if not specified.
1394         */
1395        public void setTLSClientAuthSanURI(final String uri) {
1396                
1397                this.tlsClientAuthSanURI = uri;
1398        }
1399        
1400        
1401        /**
1402         * Gets the expected iPAddress SAN entry in the X.509 certificate, which
1403         * the OAuth client will use in mutual TLS authentication. Corresponds
1404         * to the {@code tls_client_auth_san_ip} client metadata field.
1405         *
1406         * @return The expected iPAddress SAN entry in the X.509 certificate,
1407         *         {@code null} if not specified.
1408         */
1409        public String getTLSClientAuthSanIP() {
1410                
1411                return tlsClientAuthSanIP;
1412        }
1413        
1414        
1415        /**
1416         * Sets the expected iPAddress SAN entry in the X.509 certificate, which
1417         * the OAuth client will use in mutual TLS authentication. Corresponds
1418         * to the {@code tls_client_auth_san_ip} client metadata field.
1419         *
1420         * @param ip The expected iPAddress SAN entry in the X.509
1421         *           certificate, {@code null} if not specified.
1422         */
1423        public void setTLSClientAuthSanIP(final String ip) {
1424                
1425                this.tlsClientAuthSanIP = ip;
1426        }
1427        
1428        
1429        /**
1430         * Gets the expected rfc822Name SAN entry in the X.509 certificate, which
1431         * the OAuth client will use in mutual TLS authentication. Corresponds
1432         * to the {@code tls_client_auth_san_email} client metadata field.
1433         *
1434         * @return The expected rfc822Name SAN entry in the X.509 certificate,
1435         *         {@code null} if not specified.
1436         */
1437        public String getTLSClientAuthSanEmail() {
1438                
1439                return tlsClientAuthSanEmail;
1440        }
1441        
1442        
1443        /**
1444         * Sets the expected rfc822Name SAN entry in the X.509 certificate, which
1445         * the OAuth client will use in mutual TLS authentication. Corresponds
1446         * to the {@code tls_client_auth_san_email} client metadata field.
1447         *
1448         * @param email The expected rfc822Name SAN entry in the X.509
1449         *              certificate, {@code null} if not specified.
1450         */
1451        public void setTLSClientAuthSanEmail(final String email) {
1452                
1453                this.tlsClientAuthSanEmail = email;
1454        }
1455        
1456        
1457        /**
1458         * Ensures that for {@code tls_client_auth} a certificate field for the
1459         * subject is specified. See
1460         * https://www.rfc-editor.org/rfc/rfc8705.html#section-2.1.2
1461         */
1462        private void ensureExactlyOneCertSubjectFieldForTLSClientAuth()
1463                throws IllegalStateException {
1464                
1465                if (! ClientAuthenticationMethod.TLS_CLIENT_AUTH.equals(getTokenEndpointAuthMethod())) {
1466                        // Not tls_client_auth, ignore
1467                        return;
1468                }
1469                
1470                if (tlsClientAuthSubjectDN == null && tlsClientAuthSanDNS == null && tlsClientAuthSanURI == null && tlsClientAuthSanIP == null && tlsClientAuthSanEmail == null) {
1471                        throw new IllegalStateException("A certificate field must be specified to indicate the subject in tls_client_auth: " +
1472                                "tls_client_auth_subject_dn, tls_client_auth_san_dns, tls_client_auth_san_uri, tls_client_auth_san_ip or tls_client_auth_san_email");
1473                }
1474                
1475                String exceptionMessage = "Exactly one certificate field must be specified to indicate the subject in tls_client_auth: " +
1476                        "tls_client_auth_subject_dn, tls_client_auth_san_dns, tls_client_auth_san_uri, tls_client_auth_san_ip or tls_client_auth_san_email";
1477                
1478                if (tlsClientAuthSubjectDN != null) {
1479                        if (tlsClientAuthSanDNS != null || tlsClientAuthSanURI != null || tlsClientAuthSanIP != null || tlsClientAuthSanEmail != null) {
1480                                throw new IllegalStateException(exceptionMessage);
1481                        }
1482                }
1483                
1484                if (tlsClientAuthSanDNS != null) {
1485                        if (tlsClientAuthSanURI != null || tlsClientAuthSanIP != null || tlsClientAuthSanEmail != null) {
1486                                throw new IllegalStateException(exceptionMessage);
1487                        }
1488                }
1489                
1490                if (tlsClientAuthSanURI != null) {
1491                        if (tlsClientAuthSanIP != null || tlsClientAuthSanEmail != null) {
1492                                throw new IllegalStateException(exceptionMessage);
1493                        }
1494                }
1495                
1496                if (tlsClientAuthSanIP != null) {
1497                        if (tlsClientAuthSanEmail != null) {
1498                                throw new IllegalStateException(exceptionMessage);
1499                        }
1500                }
1501        }
1502        
1503        
1504        /**
1505         * Gets the JWS algorithm for JWT-encoded authorisation responses.
1506         * Corresponds to the {@code authorization_signed_response_alg} client
1507         * metadata field.
1508         *
1509         * @return The JWS algorithm, {@code null} if not specified.
1510         */
1511        public JWSAlgorithm getAuthorizationJWSAlg() {
1512                
1513                return authzJWSAlg;
1514        }
1515        
1516        
1517        /**
1518         * Sets the JWS algorithm for JWT-encoded authorisation responses.
1519         * Corresponds to the {@code authorization_signed_response_alg} client
1520         * metadata field.
1521         *
1522         * @param authzJWSAlg The JWS algorithm, {@code null} if not specified.
1523         *                    Must not be {@code "none"}.
1524         */
1525        public void setAuthorizationJWSAlg(final JWSAlgorithm authzJWSAlg) {
1526                
1527                if (new JWSAlgorithm("none").equals(authzJWSAlg)) {
1528                        // Prevent passing none as JWS alg
1529                        throw new IllegalArgumentException("The JWS algorithm must not be \"none\"");
1530                }
1531                
1532                this.authzJWSAlg = authzJWSAlg;
1533        }
1534        
1535        
1536        /**
1537         * Gets the JWE algorithm for JWT-encoded authorisation responses.
1538         * Corresponds to the {@code authorization_encrypted_response_alg}
1539         * client metadata field.
1540         *
1541         * @return The JWE algorithm, {@code null} if not specified.
1542         */
1543        public JWEAlgorithm getAuthorizationJWEAlg() {
1544                
1545                return authzJWEAlg;
1546        }
1547        
1548        
1549        /**
1550         * Sets the JWE algorithm for JWT-encoded authorisation responses.
1551         * Corresponds to the {@code authorization_encrypted_response_alg}
1552         * client metadata field.
1553         *
1554         * @param authzJWEAlg The JWE algorithm, {@code null} if not specified.
1555         */
1556        public void setAuthorizationJWEAlg(final JWEAlgorithm authzJWEAlg) {
1557                
1558                this.authzJWEAlg = authzJWEAlg;
1559        }
1560        
1561        
1562        /**
1563         * Sets the encryption method for JWT-encoded authorisation responses.
1564         * Corresponds to the {@code authorization_encrypted_response_enc}
1565         * client metadata field.
1566         *
1567         * @return The encryption method, {@code null} if specified.
1568         */
1569        public EncryptionMethod getAuthorizationJWEEnc() {
1570                
1571                return authzJWEEnc;
1572        }
1573        
1574        
1575        /**
1576         * Sets the encryption method for JWT-encoded authorisation responses.
1577         * Corresponds to the {@code authorization_encrypted_response_enc}
1578         * client metadata field.
1579         *
1580         * @param authzJWEEnc The encryption method, {@code null} if specified.
1581         */
1582        public void setAuthorizationJWEEnc(final EncryptionMethod authzJWEEnc) {
1583                
1584                this.authzJWEEnc = authzJWEEnc;
1585        }
1586        
1587        
1588        /**
1589         * Gets the requirement for pushed authorisation requests (PAR).
1590         * Corresponds to the {@code pushed_authorization_request_endpoint}
1591         * client metadata field.
1592         *
1593         * @return {@code true} if PAR is required, else {@code false}.
1594         */
1595        public boolean requiresPushedAuthorizationRequests() {
1596                
1597                return requirePAR;
1598        }
1599        
1600        
1601        /**
1602         * Sets the requirement for pushed authorisation requests (PAR).
1603         * Corresponds to the {@code pushed_authorization_request_endpoint}
1604         * client metadata field.
1605         *
1606         * @param requirePAR {@code true} if PAR is required, else
1607         *                   {@code false}.
1608         */
1609        public void requiresPushedAuthorizationRequests(final boolean requirePAR) {
1610                
1611                this.requirePAR = requirePAR;
1612        }
1613        
1614        
1615        /**
1616         * Gets the supported OpenID Connect Federation 1.0 client registration
1617         * types. Corresponds to the {@code client_registration_types} metadata
1618         * field.
1619         *
1620         * @return The supported registration types, {@code null} if not
1621         *         specified.
1622         */
1623        public List<ClientRegistrationType> getClientRegistrationTypes() {
1624                
1625                return clientRegistrationTypes;
1626        }
1627        
1628        
1629        /**
1630         * Sets the supported OpenID Connect Federation 1.0 client registration
1631         * types. Corresponds to the {@code client_registration_types} metadata
1632         * field.
1633         *
1634         * @param regTypes The supported registration types, {@code null} if
1635         *                 not specified.
1636         */
1637        public void setClientRegistrationTypes(final List<ClientRegistrationType> regTypes) {
1638                
1639                this.clientRegistrationTypes = regTypes;
1640        }
1641        
1642        
1643        /**
1644         * Gets the organisation name in OpenID Connect Federation 1.0.
1645         * Corresponds to the {@code organization_name} metadata field.
1646         *
1647         * @return The organisation name, {@code null} if not specified.
1648         */
1649        public String getOrganizationName() {
1650                
1651                return organizationName;
1652        }
1653        
1654        
1655        /**
1656         * Sets the organisation name in OpenID Connect Federation 1.0.
1657         * Corresponds to the {@code organization_name} metadata field.
1658         *
1659         * @param organizationName The organisation name, {@code null} if not
1660         *                         specified.
1661         */
1662        public void setOrganizationName(final String organizationName) {
1663                
1664                this.organizationName = organizationName;
1665        }
1666        
1667        
1668        /**
1669         * Gets the used trust anchor in a explicit client registration in
1670         * OpenID Connect Federation 1.0. Corresponds to the
1671         * {@code trust_anchor_id} client metadata field.
1672         *
1673         * @return The trust anchor ID, {@code null} if not specified.
1674         */
1675        public EntityID getTrustAnchorID() {
1676                
1677                return trustAnchorID;
1678        }
1679        
1680        
1681        /**
1682         * Sets the used trust anchor in a explicit client registration in
1683         * OpenID Connect Federation 1.0. Corresponds to the
1684         * {@code trust_anchor_id} client metadata field.
1685         *
1686         * @param trustAnchorID The trust anchor ID, {@code null} if not
1687         *                      specified.
1688         */
1689        public void setTrustAnchorID(final EntityID trustAnchorID) {
1690                
1691                this.trustAnchorID = trustAnchorID;
1692        }
1693        
1694        
1695        /**
1696         * Gets the specified custom metadata field.
1697         *
1698         * @param name The field name. Must not be {@code null}.
1699         *
1700         * @return The field value, typically serialisable to a JSON entity,
1701         *         {@code null} if none.
1702         */
1703        public Object getCustomField(final String name) {
1704
1705                return customFields.get(name);
1706        }
1707
1708
1709        /**
1710         * Gets the custom metadata fields.
1711         *
1712         * @return The custom metadata fields, as a JSON object, empty object
1713         *         if none.
1714         */
1715        public JSONObject getCustomFields() {
1716
1717                return customFields;
1718        }
1719
1720
1721        /**
1722         * Sets the specified custom metadata field.
1723         *
1724         * @param name  The field name. Must not be {@code null}.
1725         * @param value The field value. Should serialise to a JSON entity.
1726         */
1727        public void setCustomField(final String name, final Object value) {
1728
1729                customFields.put(name, value);
1730        }
1731
1732
1733        /**
1734         * Sets the custom metadata fields.
1735         *
1736         * @param customFields The custom metadata fields, as a JSON object,
1737         *                     empty object if none. Must not be {@code null}.
1738         */
1739        public void setCustomFields(final JSONObject customFields) {
1740
1741                if (customFields == null)
1742                        throw new IllegalArgumentException("The custom fields JSON object must not be null");
1743
1744                this.customFields = customFields;
1745        }
1746
1747
1748        /**
1749         * Applies the client metadata defaults where no values have been
1750         * specified.
1751         *
1752         * <ul>
1753         *     <li>The response types default to {@code ["code"]}.
1754         *     <li>The grant types default to {@code ["authorization_code"]}.
1755         *     <li>The client authentication method defaults to
1756         *         "client_secret_basic", unless the grant type is "implicit"
1757         *         only.
1758         *     <li>The encryption method for JWT-encoded authorisation
1759         *         responses defaults to {@code A128CBC-HS256} if a JWE
1760         *         algorithm is set.
1761         * </ul>
1762         */
1763        public void applyDefaults() {
1764
1765                if (responseTypes == null) {
1766                        responseTypes = new HashSet<>();
1767                        responseTypes.add(ResponseType.getDefault());
1768                }
1769
1770                if (grantTypes == null) {
1771                        grantTypes = new HashSet<>();
1772                        grantTypes.add(GrantType.AUTHORIZATION_CODE);
1773                }
1774
1775                if (authMethod == null) {
1776
1777                        if (grantTypes.contains(GrantType.IMPLICIT) && grantTypes.size() == 1) {
1778                                authMethod = ClientAuthenticationMethod.NONE;
1779                        } else {
1780                                authMethod = ClientAuthenticationMethod.getDefault();
1781                        }
1782                }
1783                
1784                if (authzJWEAlg != null && authzJWEEnc == null) {
1785                        authzJWEEnc = EncryptionMethod.A128CBC_HS256;
1786                }
1787        }
1788
1789
1790        /**
1791         * Returns the JSON object representation of this client metadata,
1792         * including any custom fields.
1793         *
1794         * @return The JSON object.
1795         */
1796        public JSONObject toJSONObject() {
1797
1798                return toJSONObject(true);
1799        }
1800
1801
1802        /**
1803         * Returns the JSON object representation of this client metadata.
1804         *
1805         * @param includeCustomFields {@code true} to include any custom
1806         *                            metadata fields, {@code false} to omit
1807         *                            them.
1808         *
1809         * @return The JSON object.
1810         */
1811        public JSONObject toJSONObject(final boolean includeCustomFields) {
1812
1813                JSONObject o;
1814
1815                if (includeCustomFields)
1816                        o = new JSONObject(customFields);
1817                else
1818                        o = new JSONObject();
1819
1820
1821                if (redirectURIs != null) {
1822
1823                        JSONArray uriList = new JSONArray();
1824
1825                        for (URI uri: redirectURIs)
1826                                uriList.add(uri.toString());
1827
1828                        o.put("redirect_uris", uriList);
1829                }
1830
1831
1832                if (scope != null)
1833                        o.put("scope", scope.toString());
1834
1835
1836                if (responseTypes != null) {
1837
1838                        JSONArray rtList = new JSONArray();
1839
1840                        for (ResponseType rt: responseTypes)
1841                                rtList.add(rt.toString());
1842
1843                        o.put("response_types", rtList);
1844                }
1845
1846
1847                if (grantTypes != null) {
1848
1849                        JSONArray grantList = new JSONArray();
1850
1851                        for (GrantType grant: grantTypes)
1852                                grantList.add(grant.toString());
1853
1854                        o.put("grant_types", grantList);
1855                }
1856
1857
1858                if (contacts != null) {
1859                        o.put("contacts", contacts);
1860                }
1861
1862
1863                if (! nameEntries.isEmpty()) {
1864
1865                        for (Map.Entry<LangTag,String> entry: nameEntries.entrySet()) {
1866
1867                                LangTag langTag = entry.getKey();
1868                                String name = entry.getValue();
1869
1870                                if (name == null)
1871                                        continue;
1872
1873                                if (langTag == null)
1874                                        o.put("client_name", entry.getValue());
1875                                else
1876                                        o.put("client_name#" + langTag, entry.getValue());
1877                        }
1878                }
1879
1880
1881                if (! logoURIEntries.isEmpty()) {
1882
1883                        for (Map.Entry<LangTag,URI> entry: logoURIEntries.entrySet()) {
1884
1885                                LangTag langTag = entry.getKey();
1886                                URI uri = entry.getValue();
1887
1888                                if (uri == null)
1889                                        continue;
1890
1891                                if (langTag == null)
1892                                        o.put("logo_uri", entry.getValue().toString());
1893                                else
1894                                        o.put("logo_uri#" + langTag, entry.getValue().toString());
1895                        }
1896                }
1897
1898
1899                if (! uriEntries.isEmpty()) {
1900
1901                        for (Map.Entry<LangTag,URI> entry: uriEntries.entrySet()) {
1902
1903                                LangTag langTag = entry.getKey();
1904                                URI uri = entry.getValue();
1905
1906                                if (uri == null)
1907                                        continue;
1908
1909                                if (langTag == null)
1910                                        o.put("client_uri", entry.getValue().toString());
1911                                else
1912                                        o.put("client_uri#" + langTag, entry.getValue().toString());
1913                        }
1914                }
1915
1916
1917                if (! policyURIEntries.isEmpty()) {
1918
1919                        for (Map.Entry<LangTag,URI> entry: policyURIEntries.entrySet()) {
1920
1921                                LangTag langTag = entry.getKey();
1922                                URI uri = entry.getValue();
1923
1924                                if (uri == null)
1925                                        continue;
1926
1927                                if (langTag == null)
1928                                        o.put("policy_uri", entry.getValue().toString());
1929                                else
1930                                        o.put("policy_uri#" + langTag, entry.getValue().toString());
1931                        }
1932                }
1933
1934
1935                if (! tosURIEntries.isEmpty()) {
1936
1937                        for (Map.Entry<LangTag,URI> entry: tosURIEntries.entrySet()) {
1938
1939                                LangTag langTag = entry.getKey();
1940                                URI uri = entry.getValue();
1941
1942                                if (uri == null)
1943                                        continue;
1944
1945                                if (langTag == null)
1946                                        o.put("tos_uri", entry.getValue().toString());
1947                                else
1948                                        o.put("tos_uri#" + langTag, entry.getValue().toString());
1949                        }
1950                }
1951
1952
1953                if (authMethod != null)
1954                        o.put("token_endpoint_auth_method", authMethod.toString());
1955
1956
1957                if (authJWSAlg != null)
1958                        o.put("token_endpoint_auth_signing_alg", authJWSAlg.getName());
1959
1960
1961                if (jwkSetURI != null)
1962                        o.put("jwks_uri", jwkSetURI.toString());
1963
1964
1965                if (jwkSet != null)
1966                        o.put("jwks", jwkSet.toJSONObject(true)); // prevent private keys from leaking
1967                
1968                
1969                if (requestObjectURIs != null) {
1970                        
1971                        JSONArray uriList = new JSONArray();
1972                        
1973                        for (URI uri: requestObjectURIs)
1974                                uriList.add(uri.toString());
1975                        
1976                        o.put("request_uris", uriList);
1977                }
1978                
1979                
1980                if (requestObjectJWSAlg != null)
1981                        o.put("request_object_signing_alg", requestObjectJWSAlg.getName());
1982                
1983                if (requestObjectJWEAlg != null)
1984                        o.put("request_object_encryption_alg", requestObjectJWEAlg.getName());
1985                
1986                if (requestObjectJWEEnc != null)
1987                        o.put("request_object_encryption_enc", requestObjectJWEEnc.getName());
1988
1989
1990                if (softwareID != null)
1991                        o.put("software_id", softwareID.getValue());
1992
1993                if (softwareVersion != null)
1994                        o.put("software_version", softwareVersion.getValue());
1995                
1996                if (getTLSClientCertificateBoundAccessTokens()) {
1997                        o.put("tls_client_certificate_bound_access_tokens", tlsClientCertificateBoundAccessTokens);
1998                }
1999                
2000                if (tlsClientAuthSubjectDN != null)
2001                        o.put("tls_client_auth_subject_dn", tlsClientAuthSubjectDN);
2002                
2003                if (tlsClientAuthSanDNS != null)
2004                        o.put("tls_client_auth_san_dns", tlsClientAuthSanDNS);
2005                
2006                if (tlsClientAuthSanURI != null)
2007                        o.put("tls_client_auth_san_uri", tlsClientAuthSanURI);
2008                
2009                if (tlsClientAuthSanIP != null)
2010                        o.put("tls_client_auth_san_ip", tlsClientAuthSanIP);
2011                
2012                if (tlsClientAuthSanEmail != null)
2013                        o.put("tls_client_auth_san_email", tlsClientAuthSanEmail);
2014                
2015                if (authzJWSAlg != null) {
2016                        o.put("authorization_signed_response_alg", authzJWSAlg.getName());
2017                }
2018                
2019                if (authzJWEAlg != null) {
2020                        o.put("authorization_encrypted_response_alg", authzJWEAlg.getName());
2021                }
2022                
2023                if (authzJWEEnc != null) {
2024                        o.put("authorization_encrypted_response_enc", authzJWEEnc.getName());
2025                }
2026                
2027                // PAR
2028                if (requirePAR) {
2029                        o.put("require_pushed_authorization_requests", true);
2030                }
2031                
2032                // Federation
2033                
2034                if (CollectionUtils.isNotEmpty(clientRegistrationTypes)) {
2035                        o.put("client_registration_types", Identifier.toStringList(clientRegistrationTypes));
2036                        o.put("federation_type", Identifier.toStringList(clientRegistrationTypes)); // TODO deprecated
2037                }
2038                if (organizationName != null) {
2039                        o.put("organization_name", organizationName);
2040                }
2041                
2042                if (trustAnchorID != null) {
2043                        o.put("trust_anchor_id", trustAnchorID.getValue());
2044                }
2045
2046                return o;
2047        }
2048        
2049        
2050        @Override
2051        public String toString() {
2052                return toJSONObject().toJSONString();
2053        }
2054        
2055        
2056        /**
2057         * Parses an client metadata instance from the specified JSON object.
2058         *
2059         * @param jsonObject The JSON object to parse. Must not be
2060         *                   {@code null}.
2061         *
2062         * @return The client metadata.
2063         *
2064         * @throws ParseException If the JSON object couldn't be parsed to a
2065         *                        client metadata instance.
2066         */
2067        public static ClientMetadata parse(final JSONObject jsonObject)
2068                throws ParseException {
2069
2070                // Copy JSON object, then parse
2071                return parseFromModifiableJSONObject(new JSONObject(jsonObject));
2072        }
2073
2074
2075        /**
2076         * Parses an client metadata instance from the specified JSON object.
2077         *
2078         * @param jsonObject The JSON object to parse, will be modified by
2079         *                   the parse routine. Must not be {@code null}.
2080         *
2081         * @return The client metadata.
2082         *
2083         * @throws ParseException If the JSON object couldn't be parsed to a
2084         *                        client metadata instance.
2085         */
2086        private static ClientMetadata parseFromModifiableJSONObject(final JSONObject jsonObject)
2087                throws ParseException {
2088
2089                ClientMetadata metadata = new ClientMetadata();
2090
2091                if (jsonObject.get("redirect_uris") != null) {
2092
2093                        Set<URI> redirectURIs = new LinkedHashSet<>();
2094
2095                        for (String uriString: JSONObjectUtils.getStringArray(jsonObject, "redirect_uris")) {
2096                                URI uri;
2097                                try {
2098                                        uri = new URI(uriString);
2099                                } catch (URISyntaxException e) {
2100                                        throw new ParseException("Invalid \"redirect_uris\" parameter: " + e.getMessage(), RegistrationError.INVALID_REDIRECT_URI.appendDescription(": " + e.getMessage()));
2101                                }
2102                                redirectURIs.add(uri);
2103                        }
2104                        try {
2105                                metadata.setRedirectionURIs(redirectURIs);
2106                        } catch (IllegalArgumentException e) {
2107                                throw new ParseException("Invalid \"redirect_uris\" parameter: " + e.getMessage(), RegistrationError.INVALID_REDIRECT_URI.appendDescription(": " + e.getMessage()));
2108                        }
2109                        jsonObject.remove("redirect_uris");
2110                }
2111
2112                try {
2113
2114                        if (jsonObject.get("scope") != null) {
2115                                metadata.setScope(Scope.parse(JSONObjectUtils.getString(jsonObject, "scope")));
2116                                jsonObject.remove("scope");
2117                        }
2118
2119
2120                        if (jsonObject.get("response_types") != null) {
2121
2122                                Set<ResponseType> responseTypes = new LinkedHashSet<>();
2123
2124                                for (String rt : JSONObjectUtils.getStringArray(jsonObject, "response_types")) {
2125
2126                                        responseTypes.add(ResponseType.parse(rt));
2127                                }
2128
2129                                metadata.setResponseTypes(responseTypes);
2130                                jsonObject.remove("response_types");
2131                        }
2132
2133
2134                        if (jsonObject.get("grant_types") != null) {
2135
2136                                Set<GrantType> grantTypes = new LinkedHashSet<>();
2137
2138                                for (String grant : JSONObjectUtils.getStringArray(jsonObject, "grant_types")) {
2139
2140                                        grantTypes.add(GrantType.parse(grant));
2141                                }
2142
2143                                metadata.setGrantTypes(grantTypes);
2144                                jsonObject.remove("grant_types");
2145                        }
2146
2147
2148                        if (jsonObject.get("contacts") != null) {
2149                                metadata.setEmailContacts(JSONObjectUtils.getStringList(jsonObject, "contacts"));
2150                                jsonObject.remove("contacts");
2151                        }
2152
2153
2154                        // Find lang-tagged client_name params
2155                        Map<LangTag, Object> matches = LangTagUtils.find("client_name", jsonObject);
2156
2157                        for (Map.Entry<LangTag, Object> entry : matches.entrySet()) {
2158
2159                                try {
2160                                        metadata.setName((String) entry.getValue(), entry.getKey());
2161
2162                                } catch (ClassCastException e) {
2163
2164                                        throw new ParseException("Invalid \"client_name\" (language tag) parameter");
2165                                }
2166
2167                                removeMember(jsonObject, "client_name", entry.getKey());
2168                        }
2169
2170
2171                        matches = LangTagUtils.find("logo_uri", jsonObject);
2172
2173                        for (Map.Entry<LangTag, Object> entry : matches.entrySet()) {
2174
2175                                if (entry.getValue() == null) continue;
2176                                
2177                                try {
2178                                        metadata.setLogoURI(new URI((String) entry.getValue()), entry.getKey());
2179                                } catch (Exception e) {
2180                                        throw new ParseException("Invalid \"logo_uri\" (language tag) parameter");
2181                                }
2182
2183                                removeMember(jsonObject, "logo_uri", entry.getKey());
2184                        }
2185
2186
2187                        matches = LangTagUtils.find("client_uri", jsonObject);
2188
2189                        for (Map.Entry<LangTag, Object> entry : matches.entrySet()) {
2190                                
2191                                if (entry.getValue() == null) continue;
2192
2193                                try {
2194                                        metadata.setURI(new URI((String) entry.getValue()), entry.getKey());
2195                                } catch (Exception e) {
2196                                        throw new ParseException("Invalid \"client_uri\" (language tag) parameter: " + e.getMessage());
2197                                }
2198
2199                                removeMember(jsonObject, "client_uri", entry.getKey());
2200                        }
2201
2202
2203                        matches = LangTagUtils.find("policy_uri", jsonObject);
2204
2205                        for (Map.Entry<LangTag, Object> entry : matches.entrySet()) {
2206                                
2207                                if (entry.getValue() == null) continue;
2208
2209                                try {
2210                                        metadata.setPolicyURI(new URI((String) entry.getValue()), entry.getKey());
2211                                } catch (Exception e) {
2212                                        throw new ParseException("Invalid \"policy_uri\" (language tag) parameter: " + e.getMessage());
2213                                }
2214
2215                                removeMember(jsonObject, "policy_uri", entry.getKey());
2216                        }
2217
2218
2219                        matches = LangTagUtils.find("tos_uri", jsonObject);
2220
2221                        for (Map.Entry<LangTag, Object> entry : matches.entrySet()) {
2222                                
2223                                if (entry.getValue() == null) continue;
2224
2225                                try {
2226                                        metadata.setTermsOfServiceURI(new URI((String) entry.getValue()), entry.getKey());
2227                                } catch (Exception e) {
2228                                        throw new ParseException("Invalid \"tos_uri\" (language tag) parameter: " + e.getMessage());
2229                                }
2230
2231                                removeMember(jsonObject, "tos_uri", entry.getKey());
2232                        }
2233
2234
2235                        if (jsonObject.get("token_endpoint_auth_method") != null) {
2236                                metadata.setTokenEndpointAuthMethod(ClientAuthenticationMethod.parse(
2237                                        JSONObjectUtils.getString(jsonObject, "token_endpoint_auth_method")));
2238
2239                                jsonObject.remove("token_endpoint_auth_method");
2240                        }
2241
2242
2243                        if (jsonObject.get("token_endpoint_auth_signing_alg") != null) {
2244                                metadata.setTokenEndpointAuthJWSAlg(JWSAlgorithm.parse(
2245                                        JSONObjectUtils.getString(jsonObject, "token_endpoint_auth_signing_alg")));
2246
2247                                jsonObject.remove("token_endpoint_auth_signing_alg");
2248                        }
2249
2250
2251                        if (jsonObject.get("jwks_uri") != null) {
2252                                metadata.setJWKSetURI(JSONObjectUtils.getURI(jsonObject, "jwks_uri"));
2253                                jsonObject.remove("jwks_uri");
2254                        }
2255
2256                        if (jsonObject.get("jwks") != null) {
2257
2258                                try {
2259                                        metadata.setJWKSet(JWKSet.parse(JSONObjectUtils.getJSONObject(jsonObject, "jwks")));
2260
2261                                } catch (java.text.ParseException e) {
2262                                        throw new ParseException(e.getMessage(), e);
2263                                }
2264
2265                                jsonObject.remove("jwks");
2266                        }
2267                        
2268                        if (jsonObject.get("request_uris") != null) {
2269                                
2270                                Set<URI> requestURIs = new LinkedHashSet<>();
2271                                
2272                                for (String uriString : JSONObjectUtils.getStringArray(jsonObject, "request_uris")) {
2273                                        
2274                                        try {
2275                                                requestURIs.add(new URI(uriString));
2276                                                
2277                                        } catch (URISyntaxException e) {
2278                                                
2279                                                throw new ParseException("Invalid \"request_uris\" parameter");
2280                                        }
2281                                }
2282                                
2283                                metadata.setRequestObjectURIs(requestURIs);
2284                                jsonObject.remove("request_uris");
2285                        }
2286                        
2287                        if (jsonObject.get("request_object_signing_alg") != null) {
2288                                metadata.setRequestObjectJWSAlg(JWSAlgorithm.parse(
2289                                        JSONObjectUtils.getString(jsonObject, "request_object_signing_alg")));
2290                                
2291                                jsonObject.remove("request_object_signing_alg");
2292                        }
2293                        
2294                        if (jsonObject.get("request_object_encryption_alg") != null) {
2295                                metadata.setRequestObjectJWEAlg(JWEAlgorithm.parse(
2296                                        JSONObjectUtils.getString(jsonObject, "request_object_encryption_alg")));
2297                                
2298                                jsonObject.remove("request_object_encryption_alg");
2299                        }
2300                        
2301                        if (jsonObject.get("request_object_encryption_enc") != null) {
2302                                metadata.setRequestObjectJWEEnc(EncryptionMethod.parse(
2303                                        JSONObjectUtils.getString(jsonObject, "request_object_encryption_enc")));
2304                                
2305                                jsonObject.remove("request_object_encryption_enc");
2306                        }
2307
2308                        if (jsonObject.get("software_id") != null) {
2309                                metadata.setSoftwareID(new SoftwareID(JSONObjectUtils.getString(jsonObject, "software_id")));
2310                                jsonObject.remove("software_id");
2311                        }
2312
2313                        if (jsonObject.get("software_version") != null) {
2314                                metadata.setSoftwareVersion(new SoftwareVersion(JSONObjectUtils.getString(jsonObject, "software_version")));
2315                                jsonObject.remove("software_version");
2316                        }
2317                        
2318                        if (jsonObject.get("tls_client_certificate_bound_access_tokens") != null) {
2319                                metadata.setTLSClientCertificateBoundAccessTokens(JSONObjectUtils.getBoolean(jsonObject, "tls_client_certificate_bound_access_tokens"));
2320                                jsonObject.remove("tls_client_certificate_bound_access_tokens");
2321                        }
2322                        
2323                        if (jsonObject.get("tls_client_auth_subject_dn") != null) {
2324                                metadata.setTLSClientAuthSubjectDN(JSONObjectUtils.getString(jsonObject, "tls_client_auth_subject_dn"));
2325                                jsonObject.remove("tls_client_auth_subject_dn");
2326                        }
2327                        
2328                        if (jsonObject.get("tls_client_auth_san_dns") != null) {
2329                                metadata.setTLSClientAuthSanDNS(JSONObjectUtils.getString(jsonObject, "tls_client_auth_san_dns"));
2330                                jsonObject.remove("tls_client_auth_san_dns");
2331                        }
2332                        
2333                        if (jsonObject.get("tls_client_auth_san_uri") != null) {
2334                                metadata.setTLSClientAuthSanURI(JSONObjectUtils.getString(jsonObject, "tls_client_auth_san_uri"));
2335                                jsonObject.remove("tls_client_auth_san_uri");
2336                        }
2337                        
2338                        if (jsonObject.get("tls_client_auth_san_ip") != null) {
2339                                metadata.setTLSClientAuthSanIP(JSONObjectUtils.getString(jsonObject, "tls_client_auth_san_ip"));
2340                                jsonObject.remove("tls_client_auth_san_ip");
2341                        }
2342                        
2343                        if (jsonObject.get("tls_client_auth_san_email") != null) {
2344                                metadata.setTLSClientAuthSanEmail(JSONObjectUtils.getString(jsonObject, "tls_client_auth_san_email"));
2345                                jsonObject.remove("tls_client_auth_san_email");
2346                        }
2347                        
2348                        metadata.ensureExactlyOneCertSubjectFieldForTLSClientAuth();
2349                        
2350                        if (jsonObject.get("authorization_signed_response_alg") != null) {
2351                                metadata.setAuthorizationJWSAlg(JWSAlgorithm.parse(JSONObjectUtils.getString(jsonObject, "authorization_signed_response_alg")));
2352                                jsonObject.remove("authorization_signed_response_alg");
2353                        }
2354                        
2355                        if (jsonObject.get("authorization_encrypted_response_alg") != null) {
2356                                metadata.setAuthorizationJWEAlg(JWEAlgorithm.parse(JSONObjectUtils.getString(jsonObject, "authorization_encrypted_response_alg")));
2357                                jsonObject.remove("authorization_encrypted_response_alg");
2358                        }
2359                        
2360                        if (jsonObject.get("authorization_encrypted_response_enc") != null) {
2361                                metadata.setAuthorizationJWEEnc(EncryptionMethod.parse(JSONObjectUtils.getString(jsonObject, "authorization_encrypted_response_enc")));
2362                                jsonObject.remove("authorization_encrypted_response_enc");
2363                        }
2364                        
2365                        // PAR
2366                        if (jsonObject.get("require_pushed_authorization_requests") != null) {
2367                                metadata.requiresPushedAuthorizationRequests(JSONObjectUtils.getBoolean(jsonObject, "require_pushed_authorization_requests"));
2368                                jsonObject.remove("require_pushed_authorization_requests");
2369                        }
2370                        
2371                        // Federation
2372                        
2373                        if (jsonObject.get("client_registration_types") != null) {
2374                                List<ClientRegistrationType> types = new LinkedList<>();
2375                                for (String v: JSONObjectUtils.getStringList(jsonObject, "client_registration_types")) {
2376                                        types.add(new ClientRegistrationType(v));
2377                                }
2378                                metadata.setClientRegistrationTypes(types);
2379                                jsonObject.remove("client_registration_types");
2380                        } else if (jsonObject.get("federation_type") != null) {
2381                                // TODO deprecated
2382                                List<ClientRegistrationType> types = new LinkedList<>();
2383                                for (String v: JSONObjectUtils.getStringList(jsonObject, "federation_type")) {
2384                                        types.add(new ClientRegistrationType(v));
2385                                }
2386                                metadata.setClientRegistrationTypes(types);
2387                                jsonObject.remove("federation_type");
2388                        }
2389                        
2390                        if (jsonObject.get("organization_name") != null) {
2391                                metadata.setOrganizationName(JSONObjectUtils.getString(jsonObject, "organization_name"));
2392                                jsonObject.remove("organization_name");
2393                        }
2394                        
2395                        if (jsonObject.get("trust_anchor_id") != null) {
2396                                metadata.setTrustAnchorID(EntityID.parse(JSONObjectUtils.getString(jsonObject, "trust_anchor_id")));
2397                                jsonObject.remove("trust_anchor_id");
2398                        }
2399
2400                } catch (ParseException | IllegalStateException e) {
2401                        // Insert client_client_metadata error code so that it
2402                        // can be reported back to the client if we have a
2403                        // registration event
2404                        throw new ParseException(e.getMessage(), RegistrationError.INVALID_CLIENT_METADATA.appendDescription(": " + e.getMessage()), e.getCause());
2405                }
2406
2407                // The remaining fields are custom
2408                metadata.customFields = jsonObject;
2409
2410                return metadata;
2411        }
2412
2413
2414        /**
2415         * Removes a JSON object member with the specified base name and
2416         * optional language tag.
2417         *
2418         * @param jsonObject The JSON object. Must not be {@code null}.
2419         * @param name       The base member name. Must not be {@code null}.
2420         * @param langTag    The language tag, {@code null} if none.
2421         */
2422        private static void removeMember(final JSONObject jsonObject, final String name, final LangTag langTag) {
2423
2424                if (langTag == null)
2425                        jsonObject.remove(name);
2426                else
2427                        jsonObject.remove(name + "#" + langTag);
2428        }
2429}