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