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.federation.entities;
019
020
021import java.util.Date;
022import java.util.LinkedList;
023import java.util.List;
024
025import net.minidev.json.JSONObject;
026
027import com.nimbusds.jose.jwk.JWKSet;
028import com.nimbusds.jwt.JWTClaimsSet;
029import com.nimbusds.oauth2.sdk.ParseException;
030import com.nimbusds.oauth2.sdk.as.AuthorizationServerMetadata;
031import com.nimbusds.oauth2.sdk.client.ClientMetadata;
032import com.nimbusds.oauth2.sdk.id.Identifier;
033import com.nimbusds.oauth2.sdk.id.Issuer;
034import com.nimbusds.oauth2.sdk.id.Subject;
035import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
036import com.nimbusds.oauth2.sdk.util.MapUtils;
037import com.nimbusds.openid.connect.sdk.claims.CommonClaimsSet;
038import com.nimbusds.openid.connect.sdk.federation.policy.MetadataPolicy;
039import com.nimbusds.openid.connect.sdk.federation.policy.language.PolicyViolationException;
040import com.nimbusds.openid.connect.sdk.federation.trust.constraints.TrustChainConstraints;
041import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
042import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;
043
044
045/**
046 * Federation entity statement claims set, serialisable to a JSON object.
047 *
048 * <p>Example claims set:
049 *
050 * <pre>
051 * {
052 *   "iss": "https://feide.no",
053 *   "sub": "https://ntnu.no",
054 *   "iat": 1516239022,
055 *   "exp": 1516298022,
056 *   "crit": ["jti"],
057 *   "jti": "7l2lncFdY6SlhNia",
058 *   "policy_language_crit": ["regexp"],
059 *   "metadata_policy": {
060 *     "openid_provider": {
061 *       "issuer": {"value": "https://ntnu.no"},
062 *       "organization_name": {"value": "NTNU"},
063 *       "id_token_signing_alg_values_supported":
064 *         {"subset_of": ["RS256", "RS384", "RS512"]},
065 *       "op_policy_uri": {
066 *         "regexp": "^https:\/\/[\w-]+\.example\.com\/[\w-]+\.html"}
067 *     },
068 *     "openid_relying_party": {
069 *       "organization_name": {"value": "NTNU"},
070 *       "grant_types_supported": {
071 *         "subset_of": ["authorization_code", "implicit"]},
072 *       "scopes": {
073 *         "subset_of": ["openid", "profile", "email", "phone"]}
074 *     }
075 *   },
076 *   "constraints": {
077 *     "max_path_length": 2
078 *   }
079 *   "jwks": {
080 *     "keys": [
081 *       {
082 *         "alg": "RS256",
083 *         "e": "AQAB",
084 *         "ext": true,
085 *         "key_ops": ["verify"],
086 *         "kid": "key1",
087 *         "kty": "RSA",
088 *         "n": "pnXBOusEANuug6ewezb9J_...",
089 *         "use": "sig"
090 *       }
091 *     ]
092 *   },
093 *   "authority_hints": [
094 *     "https://edugain.org/federation"
095 *   ]
096 * }
097 * </pre>
098 *
099 * <p>Related specifications:
100 *
101 * <ul>
102 *     <li>OpenID Connect Federation 1.0, section 2.1.
103 * </ul>
104 */
105public class EntityStatementClaimsSet extends CommonClaimsSet {
106        
107        
108        /**
109         * The expiration time claim name.
110         */
111        public static final String EXP_CLAIM_NAME = "exp";
112        
113        
114        /**
115         * The JWK set claim name.
116         */
117        public static final String JWKS_CLAIM_NAME = "jwks";
118        
119        
120        /**
121         * The authority hints claim name.
122         */
123        public static final String AUTHORITY_HINTS_CLAIM_NAME = "authority_hints";
124        
125        
126        /**
127         * The metadata claim name.
128         */
129        public static final String METADATA_CLAIM_NAME = "metadata";
130        
131        
132        /**
133         * The metadata policy claim name.
134         */
135        public static final String METADATA_POLICY_CLAIM_NAME = "metadata_policy";
136        
137        
138        /**
139         * The assumed trust anchor in a explicit client registration. Intended
140         * for entity statements issued by an OP for RP performing explicit
141         * client registration only.
142         */
143        public static final String TRUST_ANCHOR_ID_CLAIM_NAME = "trust_anchor_id";
144        
145        
146        /**
147         * The constraints claim name.
148         */
149        public static final String CONSTRAINTS_CLAIM_NAME = "constraints";
150        
151        
152        /**
153         * The critical claim name.
154         */
155        public static final String CRITICAL_CLAIM_NAME = "crit";
156        
157        
158        /**
159         * The policy critical claim name.
160         */
161        public static final String POLICY_LANGUAGE_CRITICAL_CLAIM_NAME = "policy_language_crit";
162        
163        
164        /**
165         * Creates a new federation entity statement claims set with the
166         * minimum required claims.
167         *
168         * @param iss  The issuer. Must not be {@code null}.
169         * @param sub  The subject. Must not be {@code null}.
170         * @param iat  The issue time. Must not be {@code null}.
171         * @param exp  The expiration time. Must not be {@code null}.
172         * @param jwks The entity public JWK set, {@code null} if not required.
173         */
174        public EntityStatementClaimsSet(final Issuer iss,
175                                        final Subject sub,
176                                        final Date iat,
177                                        final Date exp,
178                                        final JWKSet jwks) {
179                
180                this(new EntityID(iss.getValue()), new EntityID(sub.getValue()), iat, exp, jwks);
181        }
182        
183        
184        /**
185         * Creates a new federation entity statement claims set with the
186         * minimum required claims.
187         *
188         * @param iss  The issuer. Must not be {@code null}.
189         * @param sub  The subject. Must not be {@code null}.
190         * @param iat  The issue time. Must not be {@code null}.
191         * @param exp  The expiration time. Must not be {@code null}.
192         * @param jwks The entity public JWK set, {@code null} if not required.
193         */
194        public EntityStatementClaimsSet(final EntityID iss,
195                                        final EntityID sub,
196                                        final Date iat,
197                                        final Date exp,
198                                        final JWKSet jwks) {
199                
200                setClaim(ISS_CLAIM_NAME, iss.getValue());
201                setClaim(SUB_CLAIM_NAME, sub.getValue());
202                setDateClaim(IAT_CLAIM_NAME, iat);
203                setDateClaim(EXP_CLAIM_NAME, exp);
204                if (jwks != null) {
205                        setClaim(JWKS_CLAIM_NAME, new JSONObject(jwks.toJSONObject(true))); // public JWKs only
206                }
207        }
208        
209        
210        /**
211         * Creates a new federation entity statement claims set from the
212         * specified JWT claims set.
213         *
214         * @param jwtClaimsSet The JWT claims set. Must not be {@code null}.
215         *
216         * @throws ParseException If the JWT claims set doesn't represent a
217         *                        valid federation entity statement claims set.
218         */
219        public EntityStatementClaimsSet(final JWTClaimsSet jwtClaimsSet)
220                throws ParseException {
221                
222                super(JSONObjectUtils.toJSONObject(jwtClaimsSet));
223                
224                validateRequiredClaimsPresence();
225        }
226        
227        
228        /**
229         * Validates this claims set for having all minimum required claims for
230         * an entity statement. If a {@link #isSelfStatement() selt-statement}
231         * check for the {@link #hasMetadata() presence of metadata}. If
232         * {@link #getCriticalExtensionClaims() critical extension claims} are
233         * listed their presence is also checked.
234         *
235         * @throws ParseException If the validation failed and a required claim
236         *                        is missing.
237         */
238        public void validateRequiredClaimsPresence()
239                throws ParseException {
240                
241                if (getIssuer() == null) {
242                        throw new ParseException("Missing iss (issuer) claim");
243                }
244                
245                EntityID.parse(getIssuer()); // ensure URI
246                
247                if (getSubject() == null) {
248                        throw new ParseException("Missing sub (subject) claim");
249                }
250                
251                EntityID.parse(getSubject()); // ensure URI
252                
253                if (getIssueTime() == null) {
254                        throw new ParseException("Missing iat (issued-at) claim");
255                }
256                
257                if (getExpirationTime() == null) {
258                        throw new ParseException("Missing exp (expiration) claim");
259                }
260                
261                // jwks always required for self-statements
262                if (isSelfStatement() && getJWKSet() == null) {
263                        throw new ParseException("Missing jwks (JWK set) claim");
264                }
265                
266                if (isSelfStatement() && ! hasMetadata()) {
267                        throw new ParseException("Missing required metadata claim for self-statement");
268                }
269                
270                List<String> crit = getCriticalExtensionClaims();
271                
272                if (crit != null) {
273                        for (String claimName: crit) {
274                                if (getClaim(claimName) == null) {
275                                        throw new ParseException("Missing critical " + claimName + " claim");
276                                }
277                        }
278                }
279        }
280        
281        
282        /**
283         * Returns {@code true} if this is a self-statement (issuer and subject
284         * match).
285         *
286         * @return {@code true} for a self-statement, {@code false} if not.
287         */
288        public boolean isSelfStatement() {
289                
290                Issuer issuer = getIssuer();
291                Subject subject = getSubject();
292                
293                return issuer != null && subject != null && issuer.getValue().equals(subject.getValue());
294        }
295        
296        
297        /**
298         * Returns the issuer as entity ID.
299         *
300         * @return The issuer as entity ID.
301         */
302        public EntityID getIssuerEntityID() {
303                
304                return new EntityID(getIssuer().getValue());
305        }
306        
307        
308        /**
309         * Returns the subject as entity ID.
310         *
311         * @return The subject as entity ID.
312         */
313        public EntityID getSubjectEntityID() {
314                
315                return new EntityID(getSubject().getValue());
316        }
317        
318        
319        /**
320         * Gets the entity statement expiration time. Corresponds to the
321         * {@code exp} claim.
322         *
323         * @return The expiration time, {@code null} if not specified or
324         *         parsing failed.
325         */
326        public Date getExpirationTime() {
327                
328                return getDateClaim(EXP_CLAIM_NAME);
329        }
330        
331        
332        /**
333         * Gets the entity JWK set.
334         *
335         * @return The entity JWK set, {@code null} if not specified or parsing
336         *         failed.
337         */
338        public JWKSet getJWKSet() {
339                
340                JSONObject jwkSetJSONObject = getJSONObjectClaim(JWKS_CLAIM_NAME);
341                if (jwkSetJSONObject == null) {
342                        return null;
343                }
344                try {
345                        return JWKSet.parse(jwkSetJSONObject);
346                } catch (java.text.ParseException e) {
347                        return null;
348                }
349        }
350        
351        
352        /**
353         * Gets the entity IDs of the intermediate entities or trust anchors.
354         *
355         * @return The entity IDs, {@code null} or empty list for a trust
356         *         anchor, or if parsing failed.
357         */
358        public List<EntityID> getAuthorityHints() {
359                
360                List<String> strings = getStringListClaim(AUTHORITY_HINTS_CLAIM_NAME);
361                
362                if (strings == null) {
363                        return null;
364                }
365                
366                List<EntityID> trustChain = new LinkedList<>();
367                for (String s: strings) {
368                        trustChain.add(new EntityID(s));
369                }
370                return trustChain;
371        }
372        
373        
374        /**
375         * Sets the entity IDs of the intermediate entities or trust anchors.
376         *
377         * @param trustChain The entity IDs, {@code null} or empty list for a
378         *                   trust anchor.
379         */
380        public void setAuthorityHints(final List<EntityID> trustChain) {
381                
382                if (trustChain != null) {
383                        setClaim(AUTHORITY_HINTS_CLAIM_NAME, Identifier.toStringList(trustChain));
384                } else {
385                        setClaim(AUTHORITY_HINTS_CLAIM_NAME, null);
386                }
387        }
388        
389        
390        /**
391         * Returns {@code true} if a metadata field is present.
392         *
393         * @return {@code true} if for a metadata field for an OpenID relying
394         *         party, OpenID provider, OAuth authorisation server, OAuth
395         *         client, OAuth protected resource or a federation entity is
396         *         present.
397         */
398        public boolean hasMetadata() {
399        
400                JSONObject metadataObject = getJSONObjectClaim(METADATA_CLAIM_NAME);
401                
402                if (MapUtils.isEmpty(metadataObject)) {
403                        return false;
404                }
405                
406                if (metadataObject.get(FederationMetadataType.OPENID_RELYING_PARTY.getValue()) != null) return true;
407                if (metadataObject.get(FederationMetadataType.OPENID_PROVIDER.getValue()) != null) return true;
408                if (metadataObject.get(FederationMetadataType.OAUTH_AUTHORIZATION_SERVER.getValue()) != null) return true;
409                if (metadataObject.get(FederationMetadataType.OAUTH_CLIENT.getValue()) != null) return true;
410                if (metadataObject.get(FederationMetadataType.OAUTH_RESOURCE.getValue()) != null) return true;
411                if (metadataObject.get(FederationMetadataType.FEDERATION_ENTITY.getValue()) != null) return true;
412                
413                return false;
414        }
415        
416        
417        /**
418         * Gets the metadata for the specified type. Use a typed getter, such
419         * as {@link #getRPMetadata}, when available.
420         *
421         * @param type The type. Must not be {@code null}.
422         *
423         * @return The metadata, {@code null} if not specified.
424         */
425        public JSONObject getMetadata(final FederationMetadataType type) {
426                
427                JSONObject o = getJSONObjectClaim(METADATA_CLAIM_NAME);
428                
429                if (o == null) {
430                        return null;
431                }
432                
433                try {
434                        return JSONObjectUtils.getJSONObject(o, type.getValue(), null);
435                } catch (com.nimbusds.oauth2.sdk.ParseException e) {
436                        return null;
437                }
438        }
439        
440        
441        /**
442         * Sets the metadata for the specified type. Use a typed setter, such
443         * as {@link #setRPMetadata}, when available.
444         *
445         * @param type     The type. Must not be {@code null}.
446         * @param metadata The metadata, {@code null} if not specified.
447         */
448        public void setMetadata(final FederationMetadataType type, final JSONObject metadata) {
449                
450                JSONObject o = getJSONObjectClaim(METADATA_CLAIM_NAME);
451                
452                if (o == null) {
453                        if (metadata == null) {
454                                return; // nothing to clear
455                        }
456                        o = new JSONObject();
457                }
458                
459                o.put(type.getValue(), metadata);
460                
461                setClaim(METADATA_CLAIM_NAME, o);
462        }
463        
464        
465        /**
466         * Gets the OpenID relying party metadata if present for this entity.
467         *
468         * @return The RP metadata, {@code null} if not specified or if parsing
469         *         failed.
470         */
471        public OIDCClientMetadata getRPMetadata() {
472                
473                JSONObject o = getMetadata(FederationMetadataType.OPENID_RELYING_PARTY);
474                
475                if (o == null) {
476                        return null;
477                }
478                
479                try {
480                        return OIDCClientMetadata.parse(o);
481                } catch (com.nimbusds.oauth2.sdk.ParseException e) {
482                        return null;
483                }
484        }
485        
486        
487        /**
488         * Sets the OpenID relying party metadata if present for this entity.
489         *
490         * @param rpMetadata The RP metadata, {@code null} if not specified.
491         */
492        public void setRPMetadata(final OIDCClientMetadata rpMetadata) {
493                
494                JSONObject o = rpMetadata != null ? rpMetadata.toJSONObject() : null;
495                setMetadata(FederationMetadataType.OPENID_RELYING_PARTY, o);
496        }
497        
498        
499        /**
500         * Gets the OpenID provider metadata if present for this entity.
501         *
502         * @return The OP metadata, {@code null} if not specified or if parsing
503         *         failed.
504         */
505        public OIDCProviderMetadata getOPMetadata() {
506                
507                JSONObject o = getMetadata(FederationMetadataType.OPENID_PROVIDER);
508                
509                if (o == null) {
510                        return null;
511                }
512                
513                try {
514                        return OIDCProviderMetadata.parse(o);
515                } catch (com.nimbusds.oauth2.sdk.ParseException e) {
516                        return null;
517                }
518        }
519        
520        
521        /**
522         * Gets the OpenID provider metadata if present for this entity.
523         *
524         * @param opMetadata The OP metadata, {@code null} if not specified.
525         */
526        public void setOPMetadata(final OIDCProviderMetadata opMetadata) {
527                
528                JSONObject o = opMetadata != null ? opMetadata.toJSONObject() : null;
529                setMetadata(FederationMetadataType.OPENID_PROVIDER, o);
530        }
531        
532        
533        /**
534         * Gets the OAuth 2.0 client metadata if present for this entity.
535         *
536         * @return The client metadata, {@code null} if not specified or if
537         *         parsing failed.
538         */
539        public ClientMetadata getOAuthClientMetadata() {
540                
541                JSONObject o = getMetadata(FederationMetadataType.OAUTH_CLIENT);
542                
543                if (o == null) {
544                        return null;
545                }
546                
547                try {
548                        return ClientMetadata.parse(o);
549                } catch (com.nimbusds.oauth2.sdk.ParseException e) {
550                        return null;
551                }
552        }
553        
554        
555        /**
556         * Sets the OAuth 2.0 client metadata if present for this entity.
557         *
558         * @param clientMetadata The client metadata, {@code null} if not
559         *                       specified.
560         */
561        public void setOAuthClientMetadata(final ClientMetadata clientMetadata) {
562                
563                JSONObject o = clientMetadata != null ? clientMetadata.toJSONObject() : null;
564                setMetadata(FederationMetadataType.OAUTH_CLIENT, o);
565        }
566        
567        
568        /**
569         * Gets the OAuth 2.0 authorisation server metadata if present for this
570         * entity.
571         *
572         * @return The AS metadata, {@code null} if not specified or if parsing
573         *         failed.
574         */
575        public AuthorizationServerMetadata getASMetadata() {
576                
577                JSONObject o = getMetadata(FederationMetadataType.OAUTH_AUTHORIZATION_SERVER);
578                
579                if (o == null) {
580                        return null;
581                }
582                
583                try {
584                        return AuthorizationServerMetadata.parse(o);
585                } catch (com.nimbusds.oauth2.sdk.ParseException e) {
586                        return null;
587                }
588        }
589        
590        
591        /**
592         * Sets the OAuth 2.0 authorisation server metadata if present for this
593         * entity.
594         *
595         * @param asMetadata The AS metadata, {@code null} if not specified.
596         */
597        public void setASMetadata(final AuthorizationServerMetadata asMetadata) {
598                
599                JSONObject o = asMetadata != null ? asMetadata.toJSONObject() : null;
600                setMetadata(FederationMetadataType.OAUTH_AUTHORIZATION_SERVER, o);
601        }
602        
603        
604        /**
605         * Gets the federation entity metadata if present for this entity.
606         *
607         * @return The federation entity metadata, {@code null} if not
608         *         specified or if parsing failed.
609         */
610        public FederationEntityMetadata getFederationEntityMetadata() {
611                
612                JSONObject o = getMetadata(FederationMetadataType.FEDERATION_ENTITY);
613                
614                if (o == null) {
615                        return null;
616                }
617                
618                try {
619                        return FederationEntityMetadata.parse(o);
620                } catch (com.nimbusds.oauth2.sdk.ParseException e) {
621                        return null;
622                }
623        }
624        
625        
626        /**
627         * Sets the federation entity metadata if present for this entity.
628         *
629         * @param entityMetadata The federation entity metadata, {@code null}
630         *                       if not specified.
631         */
632        public void setFederationEntityMetadata(final FederationEntityMetadata entityMetadata) {
633                
634                JSONObject o = entityMetadata != null ? entityMetadata.toJSONObject() : null;
635                setMetadata(FederationMetadataType.FEDERATION_ENTITY, o);
636        }
637        
638        
639        /**
640         * Gets the complete metadata policy JSON object.
641         *
642         * @return The metadata policy JSON object, {@code null} if not
643         *         specified or if parsing failed.
644         */
645        public JSONObject getMetadataPolicyJSONObject() {
646                
647                return getJSONObjectClaim(METADATA_POLICY_CLAIM_NAME);
648        }
649        
650        
651        /**
652         * Sets the complete metadata policy JSON object.
653         *
654         * @param metadataPolicy The metadata policy JSON object, {@code null}
655         *                       if not specified.
656         */
657        public void setMetadataPolicyJSONObject(final JSONObject metadataPolicy) {
658        
659                setClaim(METADATA_POLICY_CLAIM_NAME, metadataPolicy);
660        }
661        
662        
663        /**
664         * Gets the metadata policy for the specified type.
665         *
666         * @param type The type. Must not be {@code null}.
667         *
668         * @return The metadata policy, {@code null} or if JSON parsing failed.
669         *
670         * @throws PolicyViolationException On a policy violation.
671         */
672        public MetadataPolicy getMetadataPolicy(final FederationMetadataType type)
673                throws PolicyViolationException {
674                
675                JSONObject o = getMetadataPolicyJSONObject();
676                
677                if (o == null) {
678                        return null;
679                }
680                
681                try {
682                        JSONObject policyJSONObject = JSONObjectUtils.getJSONObject(o, type.getValue(), null);
683                        if (policyJSONObject == null) {
684                                return null;
685                        }
686                        return MetadataPolicy.parse(policyJSONObject);
687                } catch (ParseException e) {
688                        return null;
689                }
690        }
691        
692        
693        /**
694         * Sets the metadata policy for the specified type.
695         *
696         * @param type           The type. Must not be {@code null}.
697         * @param metadataPolicy The metadata policy, {@code null} if not
698         *                       specified.
699         */
700        public void setMetadataPolicy(final FederationMetadataType type, final MetadataPolicy metadataPolicy) {
701                
702                JSONObject o = getMetadataPolicyJSONObject();
703                
704                if (o == null) {
705                        if (metadataPolicy == null) {
706                                return; // nothing to clear
707                        }
708                        o = new JSONObject();
709                }
710                
711                if (metadataPolicy != null) {
712                        o.put(type.getValue(), metadataPolicy.toJSONObject());
713                } else {
714                        o.remove(type.getValue());
715                }
716                
717                if (o.isEmpty()) {
718                        o = null;
719                }
720                setMetadataPolicyJSONObject(o);
721        }
722        
723        
724        /**
725         * Gets the used trust anchor in a explicit client registration in
726         * OpenID Connect Federation 1.0. Intended for entity statements issued
727         * by an OpenID provider for a Relying party performing explicit client
728         * registration only.Corresponds to the {@code trust_anchor_id} client
729         * metadata field.
730         *
731         * @return The trust anchor ID, {@code null} if not specified.
732         */
733        public EntityID getTrustAnchorID() {
734                
735                String value = getStringClaim(TRUST_ANCHOR_ID_CLAIM_NAME);
736                
737                try {
738                        return EntityID.parse(value);
739                } catch (ParseException e) {
740                        return null;
741                }
742        }
743        
744        
745        /**
746         * Sets the used trust anchor in a explicit client registration in
747         * OpenID Connect Federation 1.0. Intended for entity statements issued
748         * by an OpenID provider for a Relying party performing explicit client
749         * registration only.Corresponds to the {@code trust_anchor_id} client
750         * metadata field.
751         *
752         * @param trustAnchorID The trust anchor ID, {@code null} if not
753         *                      specified.
754         */
755        public void setTrustAnchorID(final EntityID trustAnchorID) {
756                
757                if (trustAnchorID != null) {
758                        setClaim(TRUST_ANCHOR_ID_CLAIM_NAME, trustAnchorID.getValue());
759                } else {
760                        setClaim(TRUST_ANCHOR_ID_CLAIM_NAME, null);
761                }
762        }
763        
764        
765        /**
766         * Gets the trust chain constraints for subordinate entities.
767         *
768         * @return The trust chain constraints, {@code null} if not specified
769         *          or if parsing failed.
770         */
771        public TrustChainConstraints getConstraints() {
772                
773                JSONObject o = getJSONObjectClaim(CONSTRAINTS_CLAIM_NAME);
774                
775                if (o == null) {
776                        return null;
777                }
778                
779                try {
780                        return TrustChainConstraints.parse(o);
781                } catch (com.nimbusds.oauth2.sdk.ParseException e) {
782                        return null;
783                }
784        }
785        
786        
787        /**
788         * Sets the trust chain constraint for subordinate entities.
789         *
790         * @param constraints The trust chain constraints, {@code null} if not
791         *                    specified.
792         */
793        public void setConstraints(final TrustChainConstraints constraints) {
794        
795                if (constraints != null) {
796                        setClaim(CONSTRAINTS_CLAIM_NAME, constraints.toJSONObject());
797                } else {
798                        setClaim(CONSTRAINTS_CLAIM_NAME, null);
799                }
800        }
801        
802        
803        /**
804         * Gets the names of the critical extension claims.
805         *
806         * @return The names of the critical extension claims, {@code null} if
807         *         not specified or if parsing failed.
808         */
809        public List<String> getCriticalExtensionClaims() {
810                
811                return getStringListClaim(CRITICAL_CLAIM_NAME);
812        }
813        
814        
815        /**
816         * Sets the names of the critical extension claims.
817         *
818         * @param claimNames The names of the critical extension claims,
819         *                   {@code null} if not specified. Must not be an
820         *                   empty list.
821         */
822        public void setCriticalExtensionClaims(final List<String> claimNames) {
823        
824                if (claimNames != null && claimNames.isEmpty()) {
825                        throw new IllegalArgumentException("The critical extension claim names must not be empty");
826                }
827                
828                setClaim(CRITICAL_CLAIM_NAME, claimNames);
829        }
830        
831        
832        /**
833         * Gets the names of the critical policy extensions.
834         *
835         * @return The names of the critical policy extensions or if parsing
836         *         failed.
837         */
838        public List<String> getCriticalPolicyExtensions() {
839                
840                return getStringListClaim(POLICY_LANGUAGE_CRITICAL_CLAIM_NAME);
841        }
842        
843        
844        /**
845         * Sets the names of the critical policy extensions.
846         *
847         * @param extNames The names of the critical policy extensions,
848         *                 {@code null} if not specified. Must not be an empty
849         *                 list.
850         */
851        public void setCriticalPolicyExtensions(final List<String> extNames) {
852        
853                if (extNames != null && extNames.isEmpty()) {
854                        throw new IllegalArgumentException("The critical policy extension names must not be empty");
855                }
856                
857                setClaim(POLICY_LANGUAGE_CRITICAL_CLAIM_NAME, extNames);
858        }
859}