001/*
002 * oauth2-oidc-sdk
003 *
004 * Copyright 2012-2021, 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.api;
019
020
021import java.util.*;
022
023import net.minidev.json.JSONObject;
024
025import com.nimbusds.jwt.JWTClaimsSet;
026import com.nimbusds.oauth2.sdk.ParseException;
027import com.nimbusds.oauth2.sdk.id.Issuer;
028import com.nimbusds.oauth2.sdk.id.Subject;
029import com.nimbusds.oauth2.sdk.util.CollectionUtils;
030import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
031import com.nimbusds.oauth2.sdk.util.MapUtils;
032import com.nimbusds.openid.connect.sdk.federation.entities.CommonFederationClaimsSet;
033import com.nimbusds.openid.connect.sdk.federation.entities.EntityID;
034import com.nimbusds.openid.connect.sdk.federation.trust.TrustChain;
035
036
037/**
038 * Resolve response claims set.
039 *
040 * <p>Related specifications:
041 *
042 * <ul>
043 *     <li>OpenID Connect Federation 1.0, section 7.2.2.
044 * </ul>
045 */
046public class ResolveClaimsSet extends CommonFederationClaimsSet {
047        
048        
049        /**
050         * The trust chain claim name.
051         */
052        public static final String TRUST_CHAIN_CLAIM_NAME = "trust_chain";
053        
054        
055        /**
056         * The names of the standard top-level claims.
057         */
058        private static final Set<String> STD_CLAIM_NAMES;
059        
060        static {
061                Set<String> claimNames = new HashSet<>();
062                claimNames.add(ISS_CLAIM_NAME);
063                claimNames.add(SUB_CLAIM_NAME);
064                claimNames.add(IAT_CLAIM_NAME);
065                claimNames.add(EXP_CLAIM_NAME);
066                claimNames.add(METADATA_CLAIM_NAME);
067                claimNames.add(TRUST_MARKS_CLAIM_NAME);
068                claimNames.add(TRUST_CHAIN_CLAIM_NAME);
069                STD_CLAIM_NAMES = Collections.unmodifiableSet(claimNames);
070        }
071        
072        
073        /**
074         * Gets the names of the standard top-level claims.
075         *
076         * @return The names of the standard top-level claims (read-only set).
077         */
078        public static Set<String> getStandardClaimNames() {
079                
080                return STD_CLAIM_NAMES;
081        }
082        
083        
084        /**
085         * Creates a new resolve response claims set with the minimum required
086         * claims.
087         *
088         * @param iss      The issuer. Must not be {@code null}.
089         * @param sub      The subject. Must not be {@code null}.
090         * @param iat      The issue time. Must not be {@code null}.
091         * @param exp      The expiration time. Must not be {@code null}.
092         * @param metadata The metadata JSON object. Must not be {@code null}.
093         */
094        public ResolveClaimsSet(final Issuer iss,
095                                final Subject sub,
096                                final Date iat,
097                                final Date exp,
098                                final JSONObject metadata) {
099                
100                this(new EntityID(iss.getValue()), new EntityID(sub.getValue()), iat, exp, metadata);
101        }
102        
103        
104        /**
105         * Creates a new resolve response claims set with the minimum required
106         * claims.
107         *
108         * @param iss      The issuer. Must not be {@code null}.
109         * @param sub      The subject. Must not be {@code null}.
110         * @param iat      The issue time. Must not be {@code null}.
111         * @param exp      The expiration time. Must not be {@code null}.
112         * @param metadata The metadata JSON object. Must not be {@code null}.
113         */
114        public ResolveClaimsSet(final EntityID iss,
115                                final EntityID sub,
116                                final Date iat,
117                                final Date exp,
118                                final JSONObject metadata) {
119                
120                setClaim(ISS_CLAIM_NAME, iss.getValue());
121                setClaim(SUB_CLAIM_NAME, sub.getValue());
122                
123                if (iat == null) {
124                        throw new IllegalArgumentException("The iat (issued-at) claim must not be null");
125                }
126                setDateClaim(IAT_CLAIM_NAME, iat);
127                
128                if (exp == null) {
129                        throw new IllegalArgumentException("The exp (expiration) claim must not be null");
130                }
131                setDateClaim(EXP_CLAIM_NAME, exp);
132                
133                if (metadata == null || metadata.isEmpty()) {
134                        throw new IllegalArgumentException("The metadata claim must not be null");
135                }
136                setClaim(METADATA_CLAIM_NAME, metadata);
137        }
138        
139        
140        /**
141         * Creates a new resolve response claims set from the specified JWT
142         * claims set.
143         *
144         * @param jwtClaimsSet The JWT claims set. Must not be {@code null}.
145         *
146         * @throws ParseException If the JWT claims set doesn't represent a
147         *                        valid resolve response claims set.
148         */
149        public ResolveClaimsSet(final JWTClaimsSet jwtClaimsSet)
150                throws ParseException {
151                
152                super(JSONObjectUtils.toJSONObject(jwtClaimsSet));
153                
154                validateRequiredClaimsPresence();
155        }
156        
157        
158        /**
159         * Validates this claims set for having all minimum required claims for
160         * a resolve response.
161         *
162         * @throws ParseException If the validation failed and a required claim
163         *                        is missing.
164         */
165        public void validateRequiredClaimsPresence()
166                throws ParseException {
167                
168                super.validateRequiredClaimsPresence();
169                
170                if (MapUtils.isEmpty(getJSONObjectClaim(METADATA_CLAIM_NAME))) {
171                        throw new ParseException("Missing metadata claim");
172                }
173        }
174        
175        
176        /**
177         * Gets the trust chain. Corresponds to the {@code trust_chain} claim.
178         *
179         * @return The trust chain, {@code null} if not specified or parsing
180         *         failed.
181         */
182        public TrustChain getTrustChain() {
183                
184                List<String> chainJWTs = getStringListClaim(TRUST_CHAIN_CLAIM_NAME);
185                
186                if (CollectionUtils.isEmpty(chainJWTs)) {
187                        return null;
188                }
189                
190                try {
191                        return TrustChain.parseSerialized(chainJWTs);
192                } catch (ParseException e) {
193                        return null;
194                }
195        }
196        
197        
198        /**
199         * Sets the trust chain. Corresponds to the {@code trust_chain} claim.
200         *
201         * @param trustChain The trust chain, {@code null} if not specified.
202         */
203        public void setTrustChain(final TrustChain trustChain) {
204                
205                if (trustChain != null) {
206                        setClaim(TRUST_CHAIN_CLAIM_NAME, trustChain.toSerializedJWTs());
207                } else {
208                        setClaim(TRUST_CHAIN_CLAIM_NAME, null);
209                }
210        }
211}