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