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