001package com.nimbusds.oauth2.sdk.client;
002
003
004import java.net.URI;
005import java.util.Collections;
006import java.util.Date;
007import java.util.HashSet;
008import java.util.Set;
009
010import net.jcip.annotations.Immutable;
011
012import net.minidev.json.JSONObject;
013
014import com.nimbusds.oauth2.sdk.ParseException;
015import com.nimbusds.oauth2.sdk.auth.Secret;
016import com.nimbusds.oauth2.sdk.id.ClientID;
017import com.nimbusds.oauth2.sdk.token.BearerAccessToken;
018import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
019
020
021/**
022 * Client information. Encapsulates the registration and metadata details of 
023 * an OAuth 2.0 client:
024 * 
025 * <ul>
026 *     <li>The client identifier.
027 *     <li>The client metadata.
028 *     <li>The optional client secret for a confidential client.
029 *     <li>The optional registration URI and access token if dynamic client
030 *         registration is permitted.
031 * </ul>
032 *
033 * <p>Related specifications:
034 *
035 * <ul>
036 *     <li>OAuth 2.0 Dynamic Client Registration Protocol
037 *         (draft-ietf-oauth-dyn-reg-18), section 4.1.
038 *     <li>OAuth 2.0 Dynamic Client Registration Management Protocol
039 *         (draft-ietf-oauth-dyn-reg-management-02), section 3.1.
040 * </ul>
041 */
042@Immutable
043public class ClientInformation {
044
045
046        /**
047         * The registered parameter names.
048         */
049        private static final Set<String> REGISTERED_PARAMETER_NAMES;
050
051
052        /**
053         * Initialises the registered parameter name set.
054         */
055        static {
056                Set<String> p = new HashSet<>(ClientMetadata.getRegisteredParameterNames());
057
058                p.add("client_id");
059                p.add("client_id_issued_at");
060                p.add("client_secret");
061                p.add("client_secret_expires_at");
062                p.add("registration_access_token");
063                p.add("registration_client_uri");
064
065                REGISTERED_PARAMETER_NAMES = Collections.unmodifiableSet(p);
066        }
067
068
069        /**
070         * The registered client ID.
071         */
072        private final ClientID id;
073
074
075        /**
076         * The date the client ID was issued at.
077         */
078        private final Date issueDate;
079
080
081        /**
082         * The client metadata.
083         */
084        private final ClientMetadata metadata;
085
086
087        /**
088         * The optional client secret.
089         */
090        private final Secret secret;
091
092
093        /**
094         * The client registration URI.
095         */
096        private final URI registrationURI;
097
098
099        /**
100         * The client registration access token.
101         */
102        private final BearerAccessToken accessToken;
103
104
105        /**
106         * Creates a new client information instance.
107         *
108         * @param id              The client identifier. Must not be
109         *                        {@code null}.
110         * @param issueDate       The issue date of the client identifier,
111         *                        {@code null} if not specified.
112         * @param metadata        The client metadata. Must not be
113         *                        {@code null}.
114         * @param secret          The optional client secret, {@code null} if
115         *                        not specified.
116         */
117        public ClientInformation(final ClientID id,
118                                 final Date issueDate,
119                                 final ClientMetadata metadata,
120                                 final Secret secret) {
121
122                this(id, issueDate, metadata, secret, null, null);
123        }
124
125
126        /**
127         * Creates a new client information instance permitting dynamic client
128         * registration management.
129         * 
130         * @param id              The client identifier. Must not be 
131         *                        {@code null}.
132         * @param issueDate       The issue date of the client identifier,
133         *                        {@code null} if not specified.
134         * @param metadata        The client metadata. Must not be
135         *                        {@code null}.
136         * @param secret          The optional client secret, {@code null} if
137         *                        not specified.
138         * @param registrationURI The client registration URI, {@code null} if
139         *                        not specified.
140         * @param accessToken     The client registration access token,
141         *                        {@code null} if not specified.
142         */
143        public ClientInformation(final ClientID id,
144                                 final Date issueDate,
145                                 final ClientMetadata metadata,
146                                 final Secret secret,
147                                 final URI registrationURI,
148                                 final BearerAccessToken accessToken) {
149
150                if (id == null)
151                        throw new IllegalArgumentException("The client identifier must not be null");
152                
153                this.id = id;
154
155                this.issueDate = issueDate;
156
157                if (metadata == null)
158                        throw new IllegalArgumentException("The client metadata must not be null");
159
160                this.metadata = metadata;
161
162                this.secret = secret;
163
164                this.registrationURI = registrationURI;
165
166                this.accessToken = accessToken;
167        }
168
169
170        /**
171         * Gets the registered client metadata parameter names.
172         *
173         * @return The registered parameter names, as an unmodifiable set.
174         */
175        public static Set<String> getRegisteredParameterNames() {
176
177                return REGISTERED_PARAMETER_NAMES;
178        }
179
180
181        /**
182         * Gets the client ID. Corresponds to the {@code client_id} client
183         * registration parameter.
184         *
185         * @return The client ID.
186         */
187        public ClientID getID() {
188
189                return id;
190        }
191
192
193        /**
194         * Gets the issue date of the client identifier. Corresponds to the
195         * {@code client_id_issued_at} client registration parameter.
196         *
197         * @return The issue date, {@code null} if not specified.
198         */
199        public Date getIDIssueDate() {
200
201                return issueDate;
202        }
203        
204        
205        /**
206         * Gets the client metadata.
207         * 
208         * @return The client metadata.
209         */
210        public ClientMetadata getMetadata() {
211                
212                return metadata;
213        }
214
215
216        /**
217         * Gets the client secret. Corresponds to the {@code client_secret} and
218         * {@code client_secret_expires_at} client registration parameters.
219         *
220         * @return The client secret, {@code null} if not specified.
221         */
222        public Secret getSecret() {
223
224                return secret;
225        }
226
227
228        /**
229         * Gets the URI of the client registration. Corresponds to the
230         * {@code registration_client_uri} client registration parameter.
231         *
232         * @return The registration URI, {@code null} if not specified.
233         */
234        public URI getRegistrationURI() {
235
236                return registrationURI;
237        }
238
239
240        /**
241         * Gets the registration access token. Corresponds to the
242         * {@code registration_access_token} client registration parameter.
243         *
244         * @return The registration access token, {@code null} if not
245         *         specified.
246         */
247        public BearerAccessToken getRegistrationAccessToken() {
248
249                return accessToken;
250        }
251
252
253        /**
254         * Returns the JSON object representation of this client information 
255         * instance.
256         *
257         * @return The JSON object.
258         */
259        public JSONObject toJSONObject() {
260
261                JSONObject o = metadata.toJSONObject();
262
263                o.put("client_id", id.getValue());
264
265                if (issueDate != null) {
266
267                        o.put("client_id_issued_at", issueDate.getTime() / 1000);
268                }
269
270                if (secret != null) {
271                        o.put("client_secret", secret.getValue());
272
273                        if (secret.getExpirationDate() != null) {
274                                o.put("client_secret_expires_at", secret.getExpirationDate().getTime() / 1000);
275                        } else {
276                                o.put("client_secret_expires_at", 0l);
277                        }
278                }
279
280                if (registrationURI != null) {
281
282                        o.put("registration_client_uri", registrationURI.toString());
283                }
284
285                if (accessToken != null) {
286
287                        o.put("registration_access_token", accessToken.getValue());
288                }
289
290                return o;
291        }
292
293
294        /**
295         * Parses a client information instance from the specified JSON object.
296         *
297         * @param jsonObject The JSON object to parse. Must not be 
298         *                   {@code null}.
299         *
300         * @return The client information.
301         *
302         * @throws ParseException If the JSON object couldn't be parsed to a
303         *                        client information instance.
304         */
305        public static ClientInformation parse(final JSONObject jsonObject)
306                throws ParseException {
307
308                ClientID id = new ClientID(JSONObjectUtils.getString(jsonObject, "client_id"));
309
310                Date issueDate = null;
311
312                if (jsonObject.containsKey("client_id_issued_at")) {
313
314                        issueDate = new Date(JSONObjectUtils.getLong(jsonObject, "client_id_issued_at") * 1000);
315                }
316
317                ClientMetadata metadata = ClientMetadata.parse(jsonObject);
318
319                Secret secret = null;
320
321                if (jsonObject.containsKey("client_secret")) {
322
323                        String value = JSONObjectUtils.getString(jsonObject, "client_secret");
324
325                        Date exp = null;
326
327                        if (jsonObject.containsKey("client_secret_expires_at")) {
328
329                                final long t = JSONObjectUtils.getLong(jsonObject, "client_secret_expires_at");
330
331                                if (t > 0) {
332                                        exp = new Date(t * 1000);
333                                }
334                        }
335
336                        secret = new Secret(value, exp);
337                }
338
339                URI registrationURI = null;
340
341                if (jsonObject.containsKey("registration_client_uri")) {
342
343                        registrationURI = JSONObjectUtils.getURI(jsonObject, "registration_client_uri");
344                }
345                
346                BearerAccessToken accessToken = null;
347
348                if (jsonObject.containsKey("registration_access_token")) {
349
350                        accessToken = new BearerAccessToken(
351                                JSONObjectUtils.getString(jsonObject, "registration_access_token"));
352                }
353                
354                return new ClientInformation(id, issueDate, metadata, secret, registrationURI, accessToken);
355        }
356}