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