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