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