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