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.entities;
019
020
021import java.util.Date;
022import java.util.LinkedList;
023import java.util.List;
024
025import net.minidev.json.JSONArray;
026import net.minidev.json.JSONObject;
027
028import com.nimbusds.oauth2.sdk.ParseException;
029import com.nimbusds.oauth2.sdk.as.AuthorizationServerMetadata;
030import com.nimbusds.oauth2.sdk.client.ClientMetadata;
031import com.nimbusds.oauth2.sdk.util.JSONArrayUtils;
032import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
033import com.nimbusds.openid.connect.sdk.claims.CommonClaimsSet;
034import com.nimbusds.openid.connect.sdk.federation.trust.marks.TrustMarkEntry;
035import com.nimbusds.openid.connect.sdk.federation.trust.marks.TrustMarkIssuerMetadata;
036import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
037import com.nimbusds.openid.connect.sdk.rp.OIDCClientMetadata;
038
039
040/**
041 * Common federation claims set.
042 */
043public abstract class CommonFederationClaimsSet extends CommonClaimsSet {
044        
045        
046        /**
047         * The expiration time claim name.
048         */
049        public static final String EXP_CLAIM_NAME = "exp";
050        
051        
052        /**
053         * The metadata claim name.
054         */
055        public static final String METADATA_CLAIM_NAME = "metadata";
056        
057        
058        /**
059         * The trust marks claim name.
060         */
061        public static final String TRUST_MARKS_CLAIM_NAME = "trust_marks";
062        
063        
064        /**
065         * Creates a new empty common federation claims set.
066         */
067        protected CommonFederationClaimsSet() {
068                super();
069        }
070        
071        
072        /**
073         * Creates a new common federation claims set from the specified JSON
074         * object.
075         *
076         * @param jsonObject The JSON object. Must not be {@code null}.
077         */
078        protected CommonFederationClaimsSet(final JSONObject jsonObject) {
079                super(jsonObject);
080        }
081        
082        
083        /**
084         * Validates this claims set for having all minimum required claims.
085         *
086         * @throws ParseException If the validation failed and a required claim
087         *                        is missing.
088         */
089        protected void validateRequiredClaimsPresence()
090                throws ParseException {
091                
092                if (getIssuer() == null) {
093                        throw new ParseException("Missing iss (issuer) claim");
094                }
095                
096                EntityID.parse(getIssuer()); // ensure URI
097                
098                if (getSubject() == null) {
099                        throw new ParseException("Missing sub (subject) claim");
100                }
101                
102                EntityID.parse(getSubject()); // ensure URI
103                
104                if (getIssueTime() == null) {
105                        throw new ParseException("Missing iat (issued-at) claim");
106                }
107                
108                if (getExpirationTime() == null) {
109                        throw new ParseException("Missing exp (expiration) claim");
110                }
111        }
112        
113        
114        /**
115         * Returns the issuer as entity ID. Corresponds to the {@code iss}
116         * claim.
117         *
118         * @return The issuer as entity ID.
119         */
120        public EntityID getIssuerEntityID() {
121                
122                return new EntityID(getIssuer().getValue());
123        }
124        
125        
126        /**
127         * Returns the subject as entity ID. Corresponds to the {@code iss}
128         * claim.
129         *
130         * @return The subject as entity ID.
131         */
132        public EntityID getSubjectEntityID() {
133                
134                return new EntityID(getSubject().getValue());
135        }
136        
137        
138        /**
139         * Gets the entity statement expiration time. Corresponds to the
140         * {@code exp} claim.
141         *
142         * @return The expiration time, {@code null} if not specified or
143         *         parsing failed.
144         */
145        public Date getExpirationTime() {
146                
147                return getDateClaim(EXP_CLAIM_NAME);
148        }
149        
150        
151        /**
152         * Gets the metadata for the specified entity type. Use a typed getter,
153         * such as {@link #getRPMetadata}, when available. Corresponds to the
154         * {@code metadata} claim.
155         *
156         * @param type The entity type. Must not be {@code null}.
157         *
158         * @return The metadata, {@code null} if not specified or if parsing
159         *         failed.
160         */
161        public JSONObject getMetadata(final EntityType type) {
162                
163                JSONObject o = getJSONObjectClaim(METADATA_CLAIM_NAME);
164                
165                if (o == null) {
166                        return null;
167                }
168                
169                try {
170                        return JSONObjectUtils.getJSONObject(o, type.getValue(), null);
171                } catch (ParseException e) {
172                        return null;
173                }
174        }
175        
176        
177        /**
178         * Gets the OpenID relying party metadata if present for this entity.
179         * Corresponds to the {@code metadata.openid_relying_party} claim.
180         *
181         * @return The RP metadata, {@code null} if not specified or if parsing
182         *         failed.
183         */
184        public OIDCClientMetadata getRPMetadata() {
185                
186                JSONObject o = getMetadata(EntityType.OPENID_RELYING_PARTY);
187                
188                if (o == null) {
189                        return null;
190                }
191                
192                try {
193                        return OIDCClientMetadata.parse(o);
194                } catch (ParseException e) {
195                        return null;
196                }
197        }
198        
199        
200        /**
201         * Gets the OpenID provider metadata if present for this entity.
202         * Corresponds to the {@code metadata.openid_provider} claim.
203         *
204         * @return The OP metadata, {@code null} if not specified or if parsing
205         *         failed.
206         */
207        public OIDCProviderMetadata getOPMetadata() {
208                
209                JSONObject o = getMetadata(EntityType.OPENID_PROVIDER);
210                
211                if (o == null) {
212                        return null;
213                }
214                
215                try {
216                        return OIDCProviderMetadata.parse(o);
217                } catch (ParseException e) {
218                        return null;
219                }
220        }
221        
222        
223        /**
224         * Gets the OAuth 2.0 client metadata if present for this entity.
225         * Corresponds to the {@code metadata.oauth_client} claim.
226         *
227         * @return The client metadata, {@code null} if not specified or if
228         *         parsing failed.
229         */
230        public ClientMetadata getOAuthClientMetadata() {
231                
232                JSONObject o = getMetadata(EntityType.OAUTH_CLIENT);
233                
234                if (o == null) {
235                        return null;
236                }
237                
238                try {
239                        return ClientMetadata.parse(o);
240                } catch (ParseException e) {
241                        return null;
242                }
243        }
244        
245        
246        /**
247         * Gets the OAuth 2.0 authorisation server metadata if present for this
248         * entity. Corresponds to the
249         * {@code metadata.oauth_authorization_server} claim.
250         *
251         * @return The AS metadata, {@code null} if not specified or if parsing
252         *         failed.
253         */
254        public AuthorizationServerMetadata getASMetadata() {
255                
256                JSONObject o = getMetadata(EntityType.OAUTH_AUTHORIZATION_SERVER);
257                
258                if (o == null) {
259                        return null;
260                }
261                
262                try {
263                        return AuthorizationServerMetadata.parse(o);
264                } catch (ParseException e) {
265                        return null;
266                }
267        }
268        
269        
270        /**
271         * Gets the federation entity metadata if present for this entity.
272         * Corresponds to the {@code metadata.federation_entity} claim.
273         *
274         * @return The federation entity metadata, {@code null} if not
275         *         specified or if parsing failed.
276         */
277        public FederationEntityMetadata getFederationEntityMetadata() {
278                
279                JSONObject o = getMetadata(EntityType.FEDERATION_ENTITY);
280                
281                if (o == null) {
282                        return null;
283                }
284                
285                try {
286                        return FederationEntityMetadata.parse(o);
287                } catch (ParseException e) {
288                        return null;
289                }
290        }
291        
292        
293        /**
294         * Gets the trust mark issuer metadata if present for this entity.
295         * Corresponds to the {@code metadata.trust_mark_issuer} claim.
296         *
297         * @return The trust mark issuer metadata, {@code null} if not
298         *         specified or if parsing failed.
299         */
300        @Deprecated
301        public TrustMarkIssuerMetadata getTrustMarkIssuerMetadata() {
302                
303                JSONObject o = getMetadata(EntityType.TRUST_MARK_ISSUER);
304                
305                if (o == null) {
306                        return null;
307                }
308                
309                try {
310                        return TrustMarkIssuerMetadata.parse(o);
311                } catch (ParseException e) {
312                        return null;
313                }
314        }
315        
316        
317        /**
318         * Gets the trust marks. Corresponds to the {@code trust_marks} claim.
319         *
320         * @return The trust marks, {@code null} if not specified or parsing
321         *         failed.
322         */
323        public List<TrustMarkEntry> getTrustMarks() {
324                
325                JSONArray array = getJSONArrayClaim(TRUST_MARKS_CLAIM_NAME);
326                
327                if (array == null) {
328                        return null;
329                }
330                
331                List<JSONObject> jsonObjects;
332                try {
333                        jsonObjects = JSONArrayUtils.toJSONObjectList(array);
334                } catch (ParseException e) {
335                        return null;
336                }
337                
338                List<TrustMarkEntry> marks = new LinkedList<>();
339                
340                for (JSONObject o: jsonObjects) {
341                        try {
342                                marks.add(TrustMarkEntry.parse(o));
343                        } catch (ParseException e) {
344                                return null;
345                        }
346                }
347                
348                return marks;
349        }
350        
351        
352        /**
353         * Sets the trust marks. Corresponds to the {@code trust_marks} claim.
354         *
355         * @param marks The trust marks, {@code null} if not specified.
356         */
357        public void setTrustMarks(final List<TrustMarkEntry> marks) {
358                
359                if (marks != null) {
360                        JSONArray array = new JSONArray();
361                        for (TrustMarkEntry en: marks) {
362                                array.add(en.toJSONObject());
363                        }
364                        setClaim(TRUST_MARKS_CLAIM_NAME, array);
365                } else {
366                        setClaim(TRUST_MARKS_CLAIM_NAME, null);
367                }
368        }
369}