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