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.openid.connect.sdk.rp;
019
020
021import java.net.URI;
022import java.net.URISyntaxException;
023import java.util.*;
024
025import com.nimbusds.jose.EncryptionMethod;
026import com.nimbusds.jose.JWEAlgorithm;
027import com.nimbusds.jose.JWSAlgorithm;
028import com.nimbusds.oauth2.sdk.ParseException;
029import com.nimbusds.oauth2.sdk.client.ClientMetadata;
030import com.nimbusds.oauth2.sdk.client.RegistrationError;
031import com.nimbusds.oauth2.sdk.util.CollectionUtils;
032import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
033import com.nimbusds.openid.connect.sdk.SubjectType;
034import com.nimbusds.openid.connect.sdk.claims.ACR;
035import com.nimbusds.openid.connect.sdk.id.SectorID;
036import net.minidev.json.JSONArray;
037import net.minidev.json.JSONObject;
038
039
040/**
041 * OpenID Connect client metadata.
042 *
043 * <p>Related specifications:
044 *
045 * <ul>
046 *     <li>OpenID Connect Dynamic Client Registration 1.0, section 2.
047 *     <li>OpenID Connect Session Management 1.0, section 5.1.1 (draft 28).
048 *     <li>OpenID Connect Front-Channel Logout 1.0, section 2 (draft 02).
049 *     <li>OpenID Connect Back-Channel Logout 1.0, section 2.2 (draft 04).
050 *     <li>OAuth 2.0 Dynamic Client Registration Protocol (RFC 7591), section
051 *         2.
052 *     <li>OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound
053 *         Access Tokens (draft-ietf-oauth-mtls-12), sections 2.1.2 and 3.4.
054 *     <li>Financial-grade API: JWT Secured Authorization Response Mode for
055 *         OAuth 2.0 (JARM)
056 * </ul>
057 */
058public class OIDCClientMetadata extends ClientMetadata {
059
060
061        /**
062         * The registered parameter names.
063         */
064        private static final Set<String> REGISTERED_PARAMETER_NAMES;
065
066
067        static {
068                // Start with the base OAuth 2.0 client params
069                Set<String> p = new HashSet<>(ClientMetadata.getRegisteredParameterNames());
070
071                // OIDC params
072                p.add("application_type");
073                p.add("subject_type");
074                p.add("sector_identifier_uri");
075                p.add("request_uris");
076                p.add("request_object_signing_alg");
077                p.add("request_object_encryption_alg");
078                p.add("request_object_encryption_enc");
079                p.add("id_token_signed_response_alg");
080                p.add("id_token_encrypted_response_alg");
081                p.add("id_token_encrypted_response_enc");
082                p.add("userinfo_signed_response_alg");
083                p.add("userinfo_encrypted_response_alg");
084                p.add("userinfo_encrypted_response_enc");
085                p.add("default_max_age");
086                p.add("require_auth_time");
087                p.add("default_acr_values");
088                p.add("initiate_login_uri");
089
090                // OIDC session
091                p.add("post_logout_redirect_uris");
092                
093                // OIDC logout
094                p.add("frontchannel_logout_uri");
095                p.add("frontchannel_logout_session_required");
096                p.add("backchannel_logout_uri");
097                p.add("backchannel_logout_session_required");
098
099                REGISTERED_PARAMETER_NAMES = Collections.unmodifiableSet(p);
100        }
101
102
103        /**
104         * The client application type.
105         */
106        private ApplicationType applicationType;
107
108
109        /**
110         * The subject identifier type for responses to this client.
111         */
112        private SubjectType subjectType;
113
114
115        /**
116         * Sector identifier URI.
117         */
118        private URI sectorIDURI;
119        
120        
121        /**
122         * Pre-registered OpenID Connect request URIs.
123         */
124        private Set<URI> requestObjectURIs;
125
126
127        /**
128         * The JSON Web Signature (JWS) algorithm required for the OpenID 
129         * Connect request objects sent by this client.
130         */
131        private JWSAlgorithm requestObjectJWSAlg;
132
133
134        /**
135         * The JSON Web Encryption (JWE) algorithm required for the OpenID
136         * Connect request objects sent by this client.
137         */
138        private JWEAlgorithm requestObjectJWEAlg;
139
140
141        /**
142         * The JSON Web Encryption (JWE) method required for the OpenID Connect
143         * request objects sent by this client.
144         */
145        private EncryptionMethod requestObjectJWEEnc;
146
147
148        /**
149         * The JSON Web Signature (JWS) algorithm required for the ID Tokens
150         * issued to this client.
151         */
152        private JWSAlgorithm idTokenJWSAlg;
153
154
155        /**
156         * The JSON Web Encryption (JWE) algorithm required for the ID Tokens
157         * issued to this client.
158         */
159        private JWEAlgorithm idTokenJWEAlg;
160
161
162        /**
163         * The JSON Web Encryption (JWE) method required for the ID Tokens
164         * issued to this client.
165         */
166        private EncryptionMethod idTokenJWEEnc;
167
168
169        /**
170         * The JSON Web Signature (JWS) algorithm required for the UserInfo
171         * responses to this client.
172         */
173        private JWSAlgorithm userInfoJWSAlg;
174
175
176        /**
177         * The JSON Web Encryption (JWE) algorithm required for the UserInfo
178         * responses to this client.
179         */
180        private JWEAlgorithm userInfoJWEAlg;
181
182
183        /**
184         * The JSON Web Encryption (JWE) method required for the UserInfo
185         * responses to this client.
186         */
187        private EncryptionMethod userInfoJWEEnc;
188
189
190        /**
191         * The default max authentication age, in seconds. If not specified 0.
192         */
193        private int defaultMaxAge = -1;
194
195
196        /**
197         * If {@code true} the {@code auth_time} claim in the ID Token is
198         * required by default.
199         */
200        private boolean requiresAuthTime;
201
202
203        /**
204         * The default Authentication Context Class Reference (ACR) values, by
205         * order of preference.
206         */
207        private List<ACR> defaultACRs;
208
209
210        /**
211         * Authorisation server initiated login HTTPS URI.
212         */
213        private URI initiateLoginURI;
214
215
216        /**
217         * Logout redirection URIs.
218         */
219        private Set<URI> postLogoutRedirectURIs;
220        
221        
222        /**
223         * Front-channel logout URI.
224         */
225        private URI frontChannelLogoutURI;
226        
227        
228        /**
229         * Indicates requirement for a session identifier on front-channel
230         * logout.
231         */
232        private boolean frontChannelLogoutSessionRequired = false;
233        
234        
235        /**
236         * Back-channel logout URI.
237         */
238        private URI backChannelLogoutURI;
239        
240        
241        /**
242         * Indicates requirement for a session identifier on back-channel
243         * logout.
244         */
245        private boolean backChannelLogoutSessionRequired = false;
246
247
248        /** 
249         * Creates a new OpenID Connect client metadata instance.
250         */
251        public OIDCClientMetadata() {
252
253                super();
254        }
255        
256        
257        /**
258         * Creates a new OpenID Connect client metadata instance from the
259         * specified base OAuth 2.0 client metadata.
260         * 
261         * @param metadata The base OAuth 2.0 client metadata. Must not be
262         *                 {@code null}.
263         */
264        public OIDCClientMetadata(final ClientMetadata metadata) {
265                
266                super(metadata);
267        }
268
269
270        /**
271         * Gets the registered (standard) OpenID Connect client metadata
272         * parameter names.
273         *
274         * @return The registered OpenID Connect parameter names, as an
275         *         unmodifiable set.
276         */
277        public static Set<String> getRegisteredParameterNames() {
278
279                return REGISTERED_PARAMETER_NAMES;
280        }
281
282
283        /**
284         * Gets the client application type. Corresponds to the
285         * {@code application_type} client metadata field.
286         *
287         * @return The client application type, {@code null} if not specified.
288         */
289        public ApplicationType getApplicationType() {
290
291                return applicationType;
292        }
293
294
295        /**
296         * Sets the client application type. Corresponds to the
297         * {@code application_type} client metadata field.
298         *
299         * @param applicationType The client application type, {@code null} if
300         *                        not specified.
301         */
302        public void setApplicationType(final ApplicationType applicationType) {
303
304                this.applicationType = applicationType;
305        }
306
307
308        /**
309         * Gets the subject identifier type for responses to this client. 
310         * Corresponds to the {@code subject_type} client metadata field.
311         *
312         * @return The subject identifier type, {@code null} if not specified.
313         */
314        public SubjectType getSubjectType() {
315
316                return subjectType;
317        }
318
319
320        /**
321         * Sets the subject identifier type for responses to this client. 
322         * Corresponds to the {@code subject_type} client metadata field.
323         *
324         * @param subjectType The subject identifier type, {@code null} if not 
325         *                    specified.
326         */
327        public void setSubjectType(final SubjectType subjectType) {
328
329                this.subjectType = subjectType;
330        }
331
332
333        /**
334         * Gets the sector identifier URI. Corresponds to the 
335         * {@code sector_identifier_uri} client metadata field.
336         *
337         * @return The sector identifier URI, {@code null} if not specified.
338         */
339        public URI getSectorIDURI() {
340
341                return sectorIDURI;
342        }
343
344
345        /**
346         * Sets the sector identifier URI. Corresponds to the 
347         * {@code sector_identifier_uri} client metadata field.
348         *
349         * @param sectorIDURI The sector identifier URI, {@code null} if not 
350         *                    specified.
351         */
352        public void setSectorIDURI(final URI sectorIDURI) {
353
354                if (sectorIDURI != null) {
355                        SectorID.ensureHTTPScheme(sectorIDURI);
356                        SectorID.ensureHostComponent(sectorIDURI);
357                }
358
359                this.sectorIDURI = sectorIDURI;
360        }
361
362
363        /**
364         * Resolves the sector identifier from the client metadata.
365         *
366         * @return The sector identifier, {@code null} if the subject type is
367         *         set to public.
368         *
369         * @throws IllegalStateException If resolution failed due to incomplete
370         *                               or inconsistent metadata.
371         */
372        public SectorID resolveSectorID() {
373
374                if (! SubjectType.PAIRWISE.equals(getSubjectType())) {
375                        // subject type is not pairwise or null
376                        return null;
377                }
378
379                // Check sector identifier URI first
380                if (getSectorIDURI() != null) {
381                        return new SectorID(getSectorIDURI());
382                }
383
384                // Check redirect URIs second
385                if (CollectionUtils.isEmpty(getRedirectionURIs())) {
386                        throw new IllegalStateException("Couldn't resolve sector ID: Missing redirect_uris");
387                }
388
389                if (getRedirectionURIs().size() > 1) {
390                        throw new IllegalStateException("Couldn't resolve sector ID: More than one redirect_uri, sector_identifier_uri not specified");
391                }
392
393                return new SectorID(getRedirectionURIs().iterator().next());
394        }
395        
396        
397        /**
398         * Gets the pre-registered OpenID Connect request object URIs.
399         * Corresponds to the {@code request_uris} client metadata field.
400         * 
401         * @return The request object URIs, {@code null} if not specified.
402         */
403        public Set<URI> getRequestObjectURIs() {
404                
405                return requestObjectURIs;
406        }
407        
408        
409        /**
410         * Sets the pre-registered OpenID Connect request object URIs.
411         * Corresponds to the {@code request_uris} client metadata field.
412         *
413         * @param requestObjectURIs The request object URIs, {@code null} if
414         *                          not specified.
415         */
416        public void setRequestObjectURIs(final Set<URI> requestObjectURIs) {
417
418                this.requestObjectURIs = requestObjectURIs;
419        }
420
421
422        /**
423         * Gets the JSON Web Signature (JWS) algorithm required for the OpenID 
424         * Connect request objects sent by this client. Corresponds to the 
425         * {@code request_object_signing_alg} client metadata field.
426         *
427         * @return The JWS algorithm, {@code null} if not specified.
428         */
429        public JWSAlgorithm getRequestObjectJWSAlg() {
430
431                return requestObjectJWSAlg;
432        }
433
434
435        /**
436         * Sets the JSON Web Signature (JWS) algorithm required for the OpenID 
437         * Connect request objects sent by this client. Corresponds to the 
438         * {@code request_object_signing_alg} client metadata field.
439         *
440         * @param requestObjectJWSAlg The JWS algorithm, {@code null} if not 
441         *                            specified.
442         */
443        public void setRequestObjectJWSAlg(final JWSAlgorithm requestObjectJWSAlg) {
444
445                this.requestObjectJWSAlg = requestObjectJWSAlg;
446        }
447
448
449        /**
450         * Gets the JSON Web Encryption (JWE) algorithm required for the OpenID
451         * Connect request objects sent by this client. Corresponds to the
452         * {@code request_object_encryption_alg} client metadata field.
453         *
454         * @return The JWE algorithm, {@code null} if not specified.
455         */
456        public JWEAlgorithm getRequestObjectJWEAlg() {
457
458                return requestObjectJWEAlg;
459        }
460
461
462        /**
463         * Sets the JSON Web Encryption (JWE) algorithm required for the OpenID
464         * Connect request objects sent by this client. Corresponds to the
465         * {@code request_object_encryption_alg} client metadata field.
466         *
467         * @param requestObjectJWEAlg The JWE algorithm, {@code null} if not
468         *                            specified.
469         */
470        public void setRequestObjectJWEAlg(final JWEAlgorithm requestObjectJWEAlg) {
471
472                this.requestObjectJWEAlg = requestObjectJWEAlg;
473        }
474
475
476        /**
477         * Gets the JSON Web Encryption (JWE) method required for the OpenID
478         * Connect request objects sent by this client. Corresponds to the
479         * {@code request_object_encryption_enc} client metadata field.
480         *
481         * @return The JWE method, {@code null} if not specified.
482         */
483        public EncryptionMethod getRequestObjectJWEEnc() {
484
485                return requestObjectJWEEnc;
486        }
487
488
489        /**
490         * Sets the JSON Web Encryption (JWE) method required for the OpenID
491         * Connect request objects sent by this client. Corresponds to the
492         * {@code request_object_encryption_enc} client metadata field.
493         *
494         * @param requestObjectJWEEnc The JWE method, {@code null} if not
495         *                            specified.
496         */
497        public void setRequestObjectJWEEnc(final EncryptionMethod requestObjectJWEEnc) {
498
499                this.requestObjectJWEEnc = requestObjectJWEEnc;
500        }
501
502
503        /**
504         * Gets the JSON Web Signature (JWS) algorithm required for the ID 
505         * Tokens issued to this client. Corresponds to the 
506         * {@code id_token_signed_response_alg} client metadata field.
507         *
508         * @return The JWS algorithm, {@code null} if not specified.
509         */
510        public JWSAlgorithm getIDTokenJWSAlg() {
511
512                return idTokenJWSAlg;
513        }
514
515
516        /**
517         * Sets the JSON Web Signature (JWS) algorithm required for the ID 
518         * Tokens issued to this client. Corresponds to the 
519         * {@code id_token_signed_response_alg} client metadata field.
520         *
521         * @param idTokenJWSAlg The JWS algorithm, {@code null} if not 
522         *                      specified.
523         */
524        public void setIDTokenJWSAlg(final JWSAlgorithm idTokenJWSAlg) {
525
526                this.idTokenJWSAlg = idTokenJWSAlg;
527        }
528
529
530        /**
531         * Gets the JSON Web Encryption (JWE) algorithm required for the ID 
532         * Tokens issued to this client. Corresponds to the 
533         * {@code id_token_encrypted_response_alg} client metadata field.
534         *
535         * @return The JWE algorithm, {@code null} if not specified.
536         */
537        public JWEAlgorithm getIDTokenJWEAlg() {
538
539                return idTokenJWEAlg;
540        }
541
542
543        /**
544         * Sets the JSON Web Encryption (JWE) algorithm required for the ID 
545         * Tokens issued to this client. Corresponds to the 
546         * {@code id_token_encrypted_response_alg} client metadata field.
547         *
548         * @param idTokenJWEAlg The JWE algorithm, {@code null} if not 
549         *                      specified.
550         */
551        public void setIDTokenJWEAlg(final JWEAlgorithm idTokenJWEAlg) {
552
553                this.idTokenJWEAlg = idTokenJWEAlg;
554        }
555
556
557        /**
558         * Gets the JSON Web Encryption (JWE) method required for the ID Tokens
559         * issued to this client. Corresponds to the 
560         * {@code id_token_encrypted_response_enc} client metadata field.
561         *
562         * @return The JWE method, {@code null} if not specified.
563         */
564        public EncryptionMethod getIDTokenJWEEnc() {
565
566                return idTokenJWEEnc;
567        }
568
569
570        /**
571         * Sets the JSON Web Encryption (JWE) method required for the ID Tokens
572         * issued to this client. Corresponds to the 
573         * {@code id_token_encrypted_response_enc} client metadata field.
574         *
575         * @param idTokenJWEEnc The JWE method, {@code null} if not specified.
576         */
577        public void setIDTokenJWEEnc(final EncryptionMethod idTokenJWEEnc) {
578
579                this.idTokenJWEEnc = idTokenJWEEnc;
580        }
581
582
583        /**
584         * Gets the JSON Web Signature (JWS) algorithm required for the 
585         * UserInfo responses to this client. Corresponds to the 
586         * {@code userinfo_signed_response_alg} client metadata field.
587         *
588         * @return The JWS algorithm, {@code null} if not specified.
589         */
590        public JWSAlgorithm getUserInfoJWSAlg() {
591
592                return userInfoJWSAlg;
593        }
594
595
596        /**
597         * Sets the JSON Web Signature (JWS) algorithm required for the 
598         * UserInfo responses to this client. Corresponds to the
599         * {@code userinfo_signed_response_alg} client metadata field.
600         *
601         * @param userInfoJWSAlg The JWS algorithm, {@code null} if not 
602         *                       specified.
603         */
604        public void setUserInfoJWSAlg(final JWSAlgorithm userInfoJWSAlg) {
605
606                this.userInfoJWSAlg = userInfoJWSAlg;
607        }
608
609
610        /**
611         * Gets the JSON Web Encryption (JWE) algorithm required for the 
612         * UserInfo responses to this client. Corresponds to the 
613         * {@code userinfo_encrypted_response_alg} client metadata field.
614         *
615         * @return The JWE algorithm, {@code null} if not specified.
616         */
617        public JWEAlgorithm getUserInfoJWEAlg() {
618
619                return userInfoJWEAlg;
620        }
621
622
623        /**
624         * Sets the JSON Web Encryption (JWE) algorithm required for the 
625         * UserInfo responses to this client. Corresponds to the 
626         * {@code userinfo_encrypted_response_alg} client metadata field.
627         *
628         * @param userInfoJWEAlg The JWE algorithm, {@code null} if not
629         *                       specified.
630         */
631        public void setUserInfoJWEAlg(final JWEAlgorithm userInfoJWEAlg) {
632
633                this.userInfoJWEAlg = userInfoJWEAlg;
634        }
635
636
637        /**
638         * Gets the JSON Web Encryption (JWE) method required for the UserInfo
639         * responses to this client. Corresponds to the 
640         * {@code userinfo_encrypted_response_enc} client metadata field.
641         *
642         * @return The JWE method, {@code null} if not specified.
643         */
644        public EncryptionMethod getUserInfoJWEEnc() {
645
646                return userInfoJWEEnc;
647        }
648
649
650        /**
651         * Sets the JSON Web Encryption (JWE) method required for the UserInfo
652         * responses to this client. Corresponds to the 
653         * {@code userinfo_encrypted_response_enc} client metadata field.
654         *
655         * @param userInfoJWEEnc The JWE method, {@code null} if not specified.
656         */
657        public void setUserInfoJWEEnc(final EncryptionMethod userInfoJWEEnc) {
658
659                this.userInfoJWEEnc = userInfoJWEEnc;
660        }
661
662
663        /**
664         * Gets the default maximum authentication age. Corresponds to the 
665         * {@code default_max_age} client metadata field.
666         *
667         * @return The default max authentication age, in seconds. If not
668         *         specified -1.
669         */
670        public int getDefaultMaxAge() {
671
672                return defaultMaxAge;
673        }
674
675
676        /**
677         * Sets the default maximum authentication age. Corresponds to the 
678         * {@code default_max_age} client metadata field.
679         *
680         * @param defaultMaxAge The default max authentication age, in seconds.
681         *                      If not specified -1.
682         */
683        public void setDefaultMaxAge(final int defaultMaxAge) {
684
685                this.defaultMaxAge = defaultMaxAge;
686        }
687
688
689        /**
690         * Gets the default requirement for the {@code auth_time} claim in the
691         * ID Token. Corresponds to the {@code require_auth_time} client 
692         * metadata field.
693         *
694         * @return If {@code true} the {@code auth_Time} claim in the ID Token 
695         *         is required by default.
696         */
697        public boolean requiresAuthTime() {
698
699                return requiresAuthTime;
700        }
701
702
703        /**
704         * Sets the default requirement for the {@code auth_time} claim in the
705         * ID Token. Corresponds to the {@code require_auth_time} client 
706         * metadata field.
707         *
708         * @param requiresAuthTime If {@code true} the {@code auth_Time} claim 
709         *                         in the ID Token is required by default.
710         */
711        public void requiresAuthTime(final boolean requiresAuthTime) {
712
713                this.requiresAuthTime = requiresAuthTime;
714        }
715
716
717        /**
718         * Gets the default Authentication Context Class Reference (ACR) 
719         * values. Corresponds to the {@code default_acr_values} client 
720         * metadata field.
721         *
722         * @return The default ACR values, by order of preference, 
723         *         {@code null} if not specified.
724         */
725        public List<ACR> getDefaultACRs() {
726
727                return defaultACRs;
728        }
729
730
731        /**
732         * Sets the default Authentication Context Class Reference (ACR)
733         * values. Corresponds to the {@code default_acr_values} client 
734         * metadata field.
735         *
736         * @param defaultACRs The default ACRs, by order of preference, 
737         *                    {@code null} if not specified.
738         */
739        public void setDefaultACRs(final List<ACR> defaultACRs) {
740
741                this.defaultACRs = defaultACRs;
742        }
743
744
745        /**
746         * Gets the HTTPS URI that the authorisation server can call to
747         * initiate a login at the client. Corresponds to the 
748         * {@code initiate_login_uri} client metadata field.
749         *
750         * @return The login URI, {@code null} if not specified.
751         */
752        public URI getInitiateLoginURI() {
753
754                return initiateLoginURI;
755        }
756
757
758        /**
759         * Sets the HTTPS URI that the authorisation server can call to
760         * initiate a login at the client. Corresponds to the 
761         * {@code initiate_login_uri} client metadata field.
762         *
763         * @param loginURI The login URI, {@code null} if not specified.
764         */
765        public void setInitiateLoginURI(final URI loginURI) {
766
767                this.initiateLoginURI = loginURI;
768        }
769
770
771        /**
772         * Gets the post logout redirection URIs. Corresponds to the
773         * {@code post_logout_redirect_uris} client metadata field.
774         *
775         * @return The logout redirection URIs, {@code null} if not specified.
776         */
777        public Set<URI> getPostLogoutRedirectionURIs() {
778
779                return postLogoutRedirectURIs;
780        }
781
782
783        /**
784         * Sets the post logout redirection URIs. Corresponds to the
785         * {@code post_logout_redirect_uris} client metadata field.
786         *
787         * @param logoutURIs The logout redirection URIs, {@code null} if not
788         *                   specified.
789         */
790        public void setPostLogoutRedirectionURIs(final Set<URI> logoutURIs) {
791
792                postLogoutRedirectURIs = logoutURIs;
793        }
794        
795        
796        /**
797         * Gets the front-channel logout URI. Corresponds to the
798         * {@code frontchannel_logout_uri} client metadata field.
799         *
800         * @return The front-channel logout URI, {@code null} if not specified.
801         */
802        public URI getFrontChannelLogoutURI() {
803                
804                return frontChannelLogoutURI;
805        }
806        
807        
808        /**
809         * Sets the front-channel logout URI. Corresponds to the
810         * {@code frontchannel_logout_uri} client metadata field.
811         *
812         * @param frontChannelLogoutURI The front-channel logout URI,
813         *                              {@code null} if not specified.
814         */
815        public void setFrontChannelLogoutURI(final URI frontChannelLogoutURI) {
816                
817                this.frontChannelLogoutURI = frontChannelLogoutURI;
818        }
819        
820        
821        /**
822         * Gets the requirement for a session identifier on front-channel
823         * logout. Corresponds to
824         * the {@code frontchannel_logout_session_required} client metadata
825         * field.
826         *
827         * @return {@code true} if a session identifier is required, else
828         *         {@code false}.
829         */
830        public boolean requiresFrontChannelLogoutSession() {
831                
832                return frontChannelLogoutSessionRequired;
833        }
834        
835        
836        /**
837         * Sets the requirement for a session identifier on front-channel
838         * logout. Corresponds to
839         * the {@code frontchannel_logout_session_required} client metadata
840         * field.
841         *
842         * @param requiresSession  {@code true} if a session identifier is
843         *                         required, else {@code false}.
844         */
845        public void requiresFrontChannelLogoutSession(boolean requiresSession) {
846                
847                frontChannelLogoutSessionRequired = requiresSession;
848        }
849        
850        
851        /**
852         * Gets the back-channel logout URI. Corresponds to the
853         * {@code backchannel_logout_uri} client metadata field.
854         *
855         * @return The back-channel logout URI, {@code null} if not specified.
856         */
857        public URI getBackChannelLogoutURI() {
858                
859                return backChannelLogoutURI;
860        }
861        
862        
863        /**
864         * Sets the back-channel logout URI. Corresponds to the
865         * {@code backchannel_logout_uri} client metadata field.
866         *
867         * @param backChannelLogoutURI The back-channel logout URI,
868         *                             {@code null} if not specified.
869         */
870        public void setBackChannelLogoutURI(final URI backChannelLogoutURI) {
871                
872                this.backChannelLogoutURI = backChannelLogoutURI;
873        }
874        
875        
876        /**
877         * Gets the requirement for a session identifier on back-channel
878         * logout. Corresponds to
879         * the {@code backchannel_logout_session_required} client metadata
880         * field.
881         *
882         * @return {@code true} if a session identifier is required, else
883         *         {@code false}.
884         */
885        public boolean requiresBackChannelLogoutSession() {
886                
887                return backChannelLogoutSessionRequired;
888        }
889        
890        
891        /**
892         * Sets the requirement for a session identifier on back-channel
893         * logout. Corresponds to
894         * the {@code backchannel_logout_session_required} client metadata
895         * field.
896         *
897         * @param requiresSession  {@code true} if a session identifier is
898         *                         required, else {@code false}.
899         */
900        public void requiresBackChannelLogoutSession(final boolean requiresSession) {
901                
902                backChannelLogoutSessionRequired = requiresSession;
903        }
904        
905        
906        /**
907         * Applies the client metadata defaults where no values have been
908         * specified.
909         * 
910         * <ul>
911         *     <li>The response types default to {@code ["code"]}.
912         *     <li>The grant types default to {@code "authorization_code".}
913         *     <li>The client authentication method defaults to
914         *         "client_secret_basic".
915         *     <li>The application type defaults to
916         *         {@link ApplicationType#WEB}.
917         *     <li>The ID token JWS algorithm defaults to "RS256".
918         * </ul>
919         */
920        @Override
921        public void applyDefaults() {
922                
923                super.applyDefaults();
924
925                if (applicationType == null) {
926                        applicationType = ApplicationType.WEB;
927                }
928                
929                if (idTokenJWSAlg == null) {
930                        idTokenJWSAlg = JWSAlgorithm.RS256;
931                }
932        }
933
934
935        @Override
936        public JSONObject toJSONObject(boolean includeCustomFields) {
937
938                JSONObject o = super.toJSONObject(includeCustomFields);
939
940                o.putAll(getCustomFields());
941
942                if (applicationType != null)
943                        o.put("application_type", applicationType.toString());
944
945                if (subjectType != null)
946                        o.put("subject_type", subjectType.toString());
947
948
949                if (sectorIDURI != null)
950                        o.put("sector_identifier_uri", sectorIDURI.toString());
951                
952                
953                if (requestObjectURIs != null) {
954                        
955                        JSONArray uriList = new JSONArray();
956                        
957                        for (URI uri: requestObjectURIs)
958                                uriList.add(uri.toString());
959                        
960                        o.put("request_uris", uriList);
961                }
962
963
964                if (requestObjectJWSAlg != null)
965                        o.put("request_object_signing_alg", requestObjectJWSAlg.getName());
966
967                if (requestObjectJWEAlg != null)
968                        o.put("request_object_encryption_alg", requestObjectJWEAlg.getName());
969
970                if (requestObjectJWEEnc != null)
971                        o.put("request_object_encryption_enc", requestObjectJWEEnc.getName());
972
973
974                if (idTokenJWSAlg != null)
975                        o.put("id_token_signed_response_alg", idTokenJWSAlg.getName());
976
977
978                if (idTokenJWEAlg != null)
979                        o.put("id_token_encrypted_response_alg", idTokenJWEAlg.getName());
980
981
982                if (idTokenJWEEnc != null)
983                        o.put("id_token_encrypted_response_enc", idTokenJWEEnc.getName());
984
985
986                if (userInfoJWSAlg != null)
987                        o.put("userinfo_signed_response_alg", userInfoJWSAlg.getName());
988
989
990                if (userInfoJWEAlg != null)
991                        o.put("userinfo_encrypted_response_alg", userInfoJWEAlg.getName());
992
993
994                if (userInfoJWEEnc != null)
995                        o.put("userinfo_encrypted_response_enc", userInfoJWEEnc.getName());
996
997
998                if (defaultMaxAge > 0)
999                        o.put("default_max_age", defaultMaxAge);
1000
1001
1002                if (requiresAuthTime())
1003                        o.put("require_auth_time", requiresAuthTime);
1004
1005
1006                if (defaultACRs != null) {
1007
1008                        JSONArray acrList = new JSONArray();
1009                        acrList.addAll(defaultACRs);
1010                        o.put("default_acr_values", acrList);
1011                }
1012
1013
1014                if (initiateLoginURI != null)
1015                        o.put("initiate_login_uri", initiateLoginURI.toString());
1016
1017
1018                if (postLogoutRedirectURIs != null) {
1019
1020                        JSONArray uriList = new JSONArray();
1021
1022                        for (URI uri: postLogoutRedirectURIs)
1023                                uriList.add(uri.toString());
1024
1025                        o.put("post_logout_redirect_uris", uriList);
1026                }
1027                
1028                if (frontChannelLogoutURI != null) {
1029                        o.put("frontchannel_logout_uri", frontChannelLogoutURI.toString());
1030                        o.put("frontchannel_logout_session_required", frontChannelLogoutSessionRequired);
1031                }
1032                
1033                if (backChannelLogoutURI != null) {
1034                        o.put("backchannel_logout_uri", backChannelLogoutURI.toString());
1035                        o.put("backchannel_logout_session_required", backChannelLogoutSessionRequired);
1036                }
1037
1038                return o;
1039        }
1040
1041
1042        /**
1043         * Parses an OpenID Connect client metadata instance from the specified
1044         * JSON object.
1045         *
1046         * @param jsonObject The JSON object to parse. Must not be 
1047         *                   {@code null}.
1048         *
1049         * @return The OpenID Connect client metadata.
1050         *
1051         * @throws ParseException If the JSON object couldn't be parsed to an
1052         *                        OpenID Connect client metadata instance.
1053         */
1054        public static OIDCClientMetadata parse(final JSONObject jsonObject)
1055                throws ParseException {
1056
1057                ClientMetadata baseMetadata = ClientMetadata.parse(jsonObject);
1058                
1059                OIDCClientMetadata metadata = new OIDCClientMetadata(baseMetadata);
1060
1061                // Parse the OIDC-specific fields from the custom OAuth 2.0 dyn
1062                // reg fields
1063
1064                JSONObject oidcFields = baseMetadata.getCustomFields();
1065
1066                try {
1067                        if (jsonObject.get("application_type") != null) {
1068                                metadata.setApplicationType(JSONObjectUtils.getEnum(jsonObject, "application_type", ApplicationType.class));
1069                                oidcFields.remove("application_type");
1070                        }
1071
1072                        if (jsonObject.get("subject_type") != null) {
1073                                metadata.setSubjectType(JSONObjectUtils.getEnum(jsonObject, "subject_type", SubjectType.class));
1074                                oidcFields.remove("subject_type");
1075                        }
1076
1077                        if (jsonObject.get("sector_identifier_uri") != null) {
1078                                metadata.setSectorIDURI(JSONObjectUtils.getURI(jsonObject, "sector_identifier_uri"));
1079                                oidcFields.remove("sector_identifier_uri");
1080                        }
1081
1082                        if (jsonObject.get("request_uris") != null) {
1083
1084                                Set<URI> requestURIs = new LinkedHashSet<>();
1085
1086                                for (String uriString : JSONObjectUtils.getStringArray(jsonObject, "request_uris")) {
1087
1088                                        try {
1089                                                requestURIs.add(new URI(uriString));
1090
1091                                        } catch (URISyntaxException e) {
1092
1093                                                throw new ParseException("Invalid \"request_uris\" parameter");
1094                                        }
1095                                }
1096
1097                                metadata.setRequestObjectURIs(requestURIs);
1098                                oidcFields.remove("request_uris");
1099                        }
1100
1101                        if (jsonObject.get("request_object_signing_alg") != null) {
1102                                metadata.setRequestObjectJWSAlg(JWSAlgorithm.parse(
1103                                        JSONObjectUtils.getString(jsonObject, "request_object_signing_alg")));
1104
1105                                oidcFields.remove("request_object_signing_alg");
1106                        }
1107
1108                        if (jsonObject.get("request_object_encryption_alg") != null) {
1109                                metadata.setRequestObjectJWEAlg(JWEAlgorithm.parse(
1110                                        JSONObjectUtils.getString(jsonObject, "request_object_encryption_alg")));
1111
1112                                oidcFields.remove("request_object_encryption_alg");
1113                        }
1114
1115                        if (jsonObject.get("request_object_encryption_enc") != null) {
1116                                metadata.setRequestObjectJWEEnc(EncryptionMethod.parse(
1117                                        JSONObjectUtils.getString(jsonObject, "request_object_encryption_enc")));
1118
1119                                oidcFields.remove("request_object_encryption_enc");
1120                        }
1121
1122                        if (jsonObject.get("id_token_signed_response_alg") != null) {
1123                                metadata.setIDTokenJWSAlg(JWSAlgorithm.parse(
1124                                        JSONObjectUtils.getString(jsonObject, "id_token_signed_response_alg")));
1125
1126                                oidcFields.remove("id_token_signed_response_alg");
1127                        }
1128
1129                        if (jsonObject.get("id_token_encrypted_response_alg") != null) {
1130                                metadata.setIDTokenJWEAlg(JWEAlgorithm.parse(
1131                                        JSONObjectUtils.getString(jsonObject, "id_token_encrypted_response_alg")));
1132
1133                                oidcFields.remove("id_token_encrypted_response_alg");
1134                        }
1135
1136                        if (jsonObject.get("id_token_encrypted_response_enc") != null) {
1137                                metadata.setIDTokenJWEEnc(EncryptionMethod.parse(
1138                                        JSONObjectUtils.getString(jsonObject, "id_token_encrypted_response_enc")));
1139
1140                                oidcFields.remove("id_token_encrypted_response_enc");
1141                        }
1142
1143                        if (jsonObject.get("userinfo_signed_response_alg") != null) {
1144                                metadata.setUserInfoJWSAlg(JWSAlgorithm.parse(
1145                                        JSONObjectUtils.getString(jsonObject, "userinfo_signed_response_alg")));
1146
1147                                oidcFields.remove("userinfo_signed_response_alg");
1148                        }
1149
1150                        if (jsonObject.get("userinfo_encrypted_response_alg") != null) {
1151                                metadata.setUserInfoJWEAlg(JWEAlgorithm.parse(
1152                                        JSONObjectUtils.getString(jsonObject, "userinfo_encrypted_response_alg")));
1153
1154                                oidcFields.remove("userinfo_encrypted_response_alg");
1155                        }
1156
1157                        if (jsonObject.get("userinfo_encrypted_response_enc") != null) {
1158                                metadata.setUserInfoJWEEnc(EncryptionMethod.parse(
1159                                        JSONObjectUtils.getString(jsonObject, "userinfo_encrypted_response_enc")));
1160
1161                                oidcFields.remove("userinfo_encrypted_response_enc");
1162                        }
1163
1164                        if (jsonObject.get("default_max_age") != null) {
1165                                metadata.setDefaultMaxAge(JSONObjectUtils.getInt(jsonObject, "default_max_age"));
1166                                oidcFields.remove("default_max_age");
1167                        }
1168
1169                        if (jsonObject.get("require_auth_time") != null) {
1170                                metadata.requiresAuthTime(JSONObjectUtils.getBoolean(jsonObject, "require_auth_time"));
1171                                oidcFields.remove("require_auth_time");
1172                        }
1173
1174                        if (jsonObject.get("default_acr_values") != null) {
1175
1176                                List<ACR> acrValues = new LinkedList<>();
1177
1178                                for (String acrString : JSONObjectUtils.getStringArray(jsonObject, "default_acr_values"))
1179                                        acrValues.add(new ACR(acrString));
1180
1181                                metadata.setDefaultACRs(acrValues);
1182
1183                                oidcFields.remove("default_acr_values");
1184                        }
1185
1186                        if (jsonObject.get("initiate_login_uri") != null) {
1187                                metadata.setInitiateLoginURI(JSONObjectUtils.getURI(jsonObject, "initiate_login_uri"));
1188                                oidcFields.remove("initiate_login_uri");
1189                        }
1190
1191                        if (jsonObject.get("post_logout_redirect_uris") != null) {
1192
1193                                Set<URI> logoutURIs = new LinkedHashSet<>();
1194
1195                                for (String uriString : JSONObjectUtils.getStringArray(jsonObject, "post_logout_redirect_uris")) {
1196
1197                                        try {
1198                                                logoutURIs.add(new URI(uriString));
1199
1200                                        } catch (URISyntaxException e) {
1201
1202                                                throw new ParseException("Invalid \"post_logout_redirect_uris\" parameter");
1203                                        }
1204                                }
1205
1206                                metadata.setPostLogoutRedirectionURIs(logoutURIs);
1207                                oidcFields.remove("post_logout_redirect_uris");
1208                        }
1209                        
1210                        if (jsonObject.get("frontchannel_logout_uri") != null) {
1211                                
1212                                metadata.setFrontChannelLogoutURI(JSONObjectUtils.getURI(jsonObject, "frontchannel_logout_uri"));
1213                                oidcFields.remove("frontchannel_logout_uri");
1214                        
1215                                if (jsonObject.get("frontchannel_logout_session_required") != null) {
1216                                        metadata.requiresFrontChannelLogoutSession(JSONObjectUtils.getBoolean(jsonObject, "frontchannel_logout_session_required"));
1217                                        oidcFields.remove("frontchannel_logout_session_required");
1218                                }
1219                        }
1220                        
1221                        
1222                        if (jsonObject.get("backchannel_logout_uri") != null) {
1223                                
1224                                metadata.setBackChannelLogoutURI(JSONObjectUtils.getURI(jsonObject, "backchannel_logout_uri"));
1225                                oidcFields.remove("backchannel_logout_uri");
1226                                
1227                                if (jsonObject.get("backchannel_logout_session_required") != null) {
1228                                        metadata.requiresBackChannelLogoutSession(JSONObjectUtils.getBoolean(jsonObject, "backchannel_logout_session_required"));
1229                                        oidcFields.remove("backchannel_logout_session_required");
1230                                }
1231                        }
1232                        
1233                        
1234                } catch (ParseException e) {
1235                        // Insert client_client_metadata error code so that it
1236                        // can be reported back to the client if we have a
1237                        // registration event
1238                        throw new ParseException(e.getMessage(), RegistrationError.INVALID_CLIENT_METADATA.appendDescription(": " + e.getMessage()), e.getCause());
1239                }
1240
1241                // The remaining fields are custom
1242                metadata.setCustomFields(oidcFields);
1243
1244                return metadata;
1245        }
1246}