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.net.URI;
022import java.util.LinkedList;
023import java.util.List;
024
025import net.minidev.json.JSONArray;
026import net.minidev.json.JSONAware;
027import net.minidev.json.JSONObject;
028
029import com.nimbusds.jwt.SignedJWT;
030import com.nimbusds.oauth2.sdk.ParseException;
031import com.nimbusds.oauth2.sdk.util.CollectionUtils;
032import com.nimbusds.oauth2.sdk.util.JSONArrayUtils;
033import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
034
035
036/**
037 * Federation entity metadata.
038 *
039 * <p>Related specifications:
040 *
041 * <ul>
042 *     <li>OpenID Connect Federation 1.0, section 3.6.
043 * </ul>
044 */
045public class FederationEntityMetadata implements JSONAware {
046        
047        
048        /**
049         * The federation API endpoint, required for trust anchors and
050         * intermediate entities.
051         */
052        private final URI federationAPIEndpoint;
053        
054        
055        /**
056         * The optional trust anchor.
057         */
058        private EntityID trustAnchorID;
059        
060        
061        /**
062         * The optional entity name.
063         */
064        private String name;
065        
066        
067        /**
068         * The optional contacts.
069         */
070        private List<String> contacts;
071        
072        
073        /**
074         * The optional policy URI.
075         */
076        private URI policyURI;
077        
078        
079        /**
080         * The optional homepage URI.
081         */
082        private URI homepageURI;
083        
084        
085        /**
086         * The optional trust marks.
087         */
088        private List<SignedJWT> trustMarks;
089        
090        
091        /**
092         * Creates a new federation entity metadata.
093         *
094         * @param federationEndpoint The federation API endpoint, required for
095         *                           trust anchors and intermediate entities,
096         *                           optional for leaf entities.
097         */
098        public FederationEntityMetadata(final URI federationEndpoint) {
099                this.federationAPIEndpoint = federationEndpoint;
100        }
101        
102        
103        /**
104         * Gets the federation API endpoint.
105         *
106         * @return The federation API endpoint, {@code null} if not specified.
107         */
108        public URI getFederationAPIEndpointURI() {
109                return federationAPIEndpoint;
110        }
111        
112        
113        /**
114         * Gets the trust anchor.
115         *
116         * @return The trust anchor, {@code null} if not specified.
117         */
118        public EntityID getTrustAnchorID() {
119                return trustAnchorID;
120        }
121        
122        
123        /**
124         * Sets the trust anchor.
125         *
126         * @param trustAnchorID The trust anchor, {@code null} if not
127         *                      specified.
128         */
129        public void setTrustAnchorID(final EntityID trustAnchorID) {
130                this.trustAnchorID = trustAnchorID;
131        }
132        
133        
134        /**
135         * Gets the entity name.
136         *
137         * @return The entity name, {@code null} if not specified.
138         */
139        public String getName() {
140                return name;
141        }
142        
143        
144        /**
145         * Sets the entity name.
146         *
147         * @param name The entity name, {@code null} if not specified.
148         */
149        public void setName(final String name) {
150                this.name = name;
151        }
152        
153        
154        /**
155         * Gets the entity contacts.
156         *
157         * @return The contacts, such as names, e-mail addresses and phone
158         *         numbers, {@code null} if not specified.
159         */
160        public List<String> getContacts() {
161                return contacts;
162        }
163        
164        
165        /**
166         * Sets the entity contacts.
167         *
168         * @param contacts The contacts, such as names, e-mail addresses and
169         *                 phone numbers, {@code null} if not specified.
170         */
171        public void setContacts(final List<String> contacts) {
172                this.contacts = contacts;
173        }
174        
175        
176        /**
177         * Gets the conditions and policies documentation URI.
178         *
179         * @return The policy URI, {@code null} if not specified.
180         */
181        public URI getPolicyURI() {
182                return policyURI;
183        }
184        
185        
186        /**
187         * Sets the conditions and policies documentation URI.
188         *
189         * @param policyURI The policy URI, {@code null} if not specified.
190         */
191        public void setPolicyURI(final URI policyURI) {
192                this.policyURI = policyURI;
193        }
194        
195        
196        /**
197         * Gets the entity homepage URI.
198         *
199         * @return The entity homepage URI, {@code null} if not specified.
200         */
201        public URI getHomepageURI() {
202                return homepageURI;
203        }
204        
205        
206        /**
207         * Sets the entity homepage URI.
208         *
209         * @param homepageURI The entity homepage URI, {@code null} if not
210         *                    specified.
211         */
212        public void setHomepageURI(final URI homepageURI) {
213                this.homepageURI = homepageURI;
214        }
215        
216        
217        /**
218         * Gets the trust marks.
219         *
220         * @return The trust marks, {@code null} if not specified.
221         */
222        public List<SignedJWT> getTrustMarks() {
223                return trustMarks;
224        }
225        
226        
227        /**
228         * Sets the trust marks.
229         *
230         * @param trustMarks The trust marks, {@code null} if not specified.
231         */
232        public void setTrustMarks(final List<SignedJWT> trustMarks) {
233                this.trustMarks = trustMarks;
234        }
235        
236        
237        /**
238         * Returns a JSON object representation of this federation entity
239         * metadata.
240         *
241         * <p>Example:
242         *
243         * <pre>
244         * {
245         *   "federation_api_endpoint" : "https://example.com/federation_api_endpoint",
246         *   "name"                    : "The example cooperation",
247         *   "homepage_uri"            : "https://www.example.com"
248         * }
249         * </pre>
250         *
251         * @return The JSON object.
252         */
253        public JSONObject toJSONObject() {
254                
255                JSONObject o = new JSONObject();
256                if (getFederationAPIEndpointURI() != null) {
257                        o.put("federation_api_endpoint", getFederationAPIEndpointURI().toString());
258                }
259                if (getTrustAnchorID() != null) {
260                        o.put("trust_anchor_id", getTrustAnchorID().getValue());
261                }
262                if (getName() != null) {
263                        o.put("name", getName());
264                }
265                if (getContacts() != null) {
266                        o.put("contacts", getContacts());
267                }
268                if (getPolicyURI() != null) {
269                        o.put("policy_uri", getPolicyURI().toString());
270                }
271                if (getHomepageURI() != null) {
272                        o.put("homepage_uri", getHomepageURI().toString());
273                }
274                if (CollectionUtils.isNotEmpty(trustMarks)) {
275                        JSONArray jsonArray = new JSONArray();
276                        for (SignedJWT jwt: trustMarks) {
277                                jsonArray.add(jwt.serialize());
278                        }
279                        o.put("trust_marks", jsonArray);
280                }
281                return o;
282        }
283        
284        
285        @Override
286        public String toJSONString() {
287                return toJSONObject().toJSONString();
288        }
289        
290        
291        /**
292         * Parses a federation entity metadata from the specified a JSON object
293         * string.
294         *
295         * <p>Example:
296         *
297         * <pre>
298         * {
299         *   "federation_api_endpoint" : "https://example.com/federation_api_endpoint",
300         *   "name"                    : "The example cooperation",
301         *   "homepage_uri"            : "https://www.example.com"
302         * }
303         * </pre>
304         *
305         * @param jsonObject The JSON object. Must not be {@code null}.
306         *
307         * @return The entity metadata.
308         *
309         * @throws ParseException If parsing failed.
310         */
311        public static FederationEntityMetadata parse(final JSONObject jsonObject)
312                throws ParseException {
313                
314                URI federationAPIEndpoint = JSONObjectUtils.getURI(jsonObject, "federation_api_endpoint", null);
315                
316                FederationEntityMetadata metadata = new FederationEntityMetadata(federationAPIEndpoint);
317                
318                if (jsonObject.get("trust_anchor_id") != null) {
319                        metadata.setTrustAnchorID(new EntityID(JSONObjectUtils.getString(jsonObject, "trust_anchor_id")));
320                }
321                
322                metadata.setName(JSONObjectUtils.getString(jsonObject, "name", null));
323                
324                metadata.setContacts(JSONObjectUtils.getStringList(jsonObject, "contacts", null));
325                
326                metadata.setPolicyURI(JSONObjectUtils.getURI(jsonObject, "policy_uri", null));
327                
328                metadata.setHomepageURI(JSONObjectUtils.getURI(jsonObject, "homepage_uri", null));
329                
330                JSONArray trustMarksArray = JSONObjectUtils.getJSONArray(jsonObject, "trust_marks", null);
331                List<SignedJWT> trustMarks = null;
332                if (CollectionUtils.isNotEmpty(trustMarksArray)) {
333                        trustMarks = new LinkedList<>();
334                        for (String jwtString: JSONArrayUtils.toStringList(trustMarksArray)) {
335                                try {
336                                        trustMarks.add(SignedJWT.parse(jwtString));
337                                } catch (java.text.ParseException e) {
338                                        throw new ParseException("Invalid trust mark JWT: " + e.getMessage());
339                                }
340                        }
341                }
342                metadata.setTrustMarks(trustMarks);
343                
344                return metadata;
345        }
346        
347        
348        /**
349         * Parses a federation entity metadata from the specified JSON object
350         * string.
351         *
352         * <p>Example:
353         *
354         * <pre>
355         * {
356         *   "federation_api_endpoint" : "https://example.com/federation_api_endpoint",
357         *   "name"                    : "The example cooperation",
358         *   "homepage_uri"            : "https://www.example.com"
359         * }
360         * </pre>
361         *
362         * @param json The JSON object string. Must not be {@code null}.
363         *
364         * @return The entity metadata.
365         *
366         * @throws ParseException If parsing failed.
367         */
368        public static FederationEntityMetadata parse(final String json)
369                throws ParseException {
370                
371                return parse(JSONObjectUtils.parse(json));
372        }
373}