001package com.nimbusds.oauth2.sdk.client;
002
003
004import java.net.URL;
005import java.util.Date;
006
007import net.jcip.annotations.Immutable;
008
009import net.minidev.json.JSONObject;
010
011import com.nimbusds.oauth2.sdk.ParseException;
012import com.nimbusds.oauth2.sdk.auth.Secret;
013import com.nimbusds.oauth2.sdk.id.ClientID;
014import com.nimbusds.oauth2.sdk.token.BearerAccessToken;
015import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
016
017
018/**
019 * Client information. Encapsulates the registration and metadata details of 
020 * an OAuth 2.0 client:
021 * 
022 * <ul>
023 *     <li>The client identifier.
024 *     <li>The client registration URI and access token.
025 *     <li>The client metadata.
026 *     <li>The optional client secret for a confidential client.
027 * </ul>
028 * 
029 * <p>This class is immutable.
030 *
031 * <p>Related specifications:
032 *
033 * <ul>
034 *     <li>OAuth 2.0 Dynamic Client Registration Protocol 
035 *         (draft-ietf-oauth-dyn-reg-14), section 2, 3.2 and 5.1.
036 * </ul>
037 *
038 * @author Vladimir Dzhuvinov
039 */
040@Immutable
041public class ClientInformation {
042
043
044        /**
045         * The registered client ID.
046         */
047        private final ClientID id;
048        
049        
050        /**
051         * The client registration URI.
052         */
053        private final URL registrationURI;
054        
055        
056        /**
057         * The client registration access token.
058         */
059        private final BearerAccessToken accessToken;
060        
061        
062        /**
063         * The client metadata.
064         */
065        private final ClientMetadata metadata;
066
067
068        /**
069         * The optional client secret.
070         */
071        private final Secret secret;
072        
073        
074        /**
075         * The date the client ID was issued at.
076         */
077        private final Date issueDate;
078
079
080        /**
081         * Creates a new client information instance.
082         * 
083         * @param id              The client identifier. Must not be 
084         *                        {@code null}.
085         * @param registrationURI The client registration URI. Must not be
086         *                        {@code null}.
087         * @param accessToken     The client registration access token. Must
088         *                        not be {@code null}.
089         * @param metadata        The client metadata. Must not be 
090         *                        {@code null}.
091         * @param secret          The optional client secret, {@code null} if 
092         *                        not specified.
093         * @param issueDate       The issue date of the client identifier,
094         *                        {@code null} if not specified.
095         */
096        public ClientInformation(final ClientID id,
097                                 final URL registrationURI,
098                                 final BearerAccessToken accessToken,
099                                 final ClientMetadata metadata,
100                                 final Secret secret,
101                                 final Date issueDate) {
102
103                if (id == null)
104                        throw new IllegalArgumentException("The client identifier must not be null");
105                
106                this.id = id;
107                
108                
109                if (registrationURI == null)
110                        throw new IllegalArgumentException("The client registration URI must not be null");
111                
112                this.registrationURI = registrationURI;
113                
114                
115                if (accessToken == null)
116                        throw new IllegalArgumentException("The client registration access token must not be null");
117                
118                this.accessToken = accessToken;
119                
120                if (metadata == null)
121                        throw new IllegalArgumentException("The client metadata must not be null");
122                
123                this.metadata = metadata;
124                
125                this.secret = secret;
126                
127                this.issueDate = issueDate;
128        }
129
130
131        /**
132         * Gets the client ID. Corresponds to the {@code client_id} client
133         * registration parameter.
134         *
135         * @return The client ID, {@code null} if not specified.
136         */
137        public ClientID getID() {
138
139                return id;
140        }
141        
142        
143        /**
144         * Gets the URI of the client registration. Corresponds to the
145         * {@code registration_client_uri} client registration parameter.
146         * 
147         * @return The registration URI, {@code null} if not specified.
148         */
149        public URL getRegistrationURI() {
150                
151                return registrationURI;
152        }
153
154
155        /**
156         * Gets the registration access token. Corresponds to the 
157         * {@code registration_access_token} client registration parameter.
158         *
159         * @return The registration access token, {@code null} if not 
160         *         specified.
161         */
162        public BearerAccessToken getRegistrationAccessToken() {
163
164                return accessToken;
165        }
166        
167        
168        /**
169         * Gets the client metadata.
170         * 
171         * @return The client metadata.
172         */
173        public ClientMetadata getClientMetadata() {
174                
175                return metadata;
176        }
177
178
179        /**
180         * Gets the client secret. Corresponds to the {@code client_secret} and
181         * {@code client_secret_expires_at} client registration parameters.
182         *
183         * @return The client secret, {@code null} if not specified.
184         */
185        public Secret getSecret() {
186
187                return secret;
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 getIssueDate() {
198                
199                return issueDate;
200        }
201
202
203        /**
204         * Returns the JSON object representation of this client information 
205         * instance.
206         *
207         * @return The JSON object.
208         */
209        public JSONObject toJSONObject() {
210
211                JSONObject o = metadata.toJSONObject();
212
213                o.put("client_id", id.getValue());
214                
215                o.put("registration_client_uri", registrationURI.toString());
216                
217                o.put("registration_access_token", accessToken.getValue());
218
219                if (secret != null) {
220                        o.put("client_secret", secret.getValue());
221
222                        if (secret.getExpirationDate() != null)
223                                o.put("client_secret_expires_at", secret.getExpirationDate().getTime() / 1000);
224                }
225                
226                if (issueDate != null) {
227                        
228                        o.put("client_id_issued_at", issueDate.getTime() / 1000);
229                }
230
231                return o;
232        }
233
234
235        /**
236         * Parses a client information instance from the specified JSON object.
237         *
238         * @param jsonObject The JSON object to parse. Must not be 
239         *                   {@code null}.
240         *
241         * @return The client information.
242         *
243         * @throws ParseException If the JSON object couldn't be parsed to a
244         *                        client information instance.
245         */
246        public static ClientInformation parse(final JSONObject jsonObject)
247                throws ParseException {
248
249                ClientID id = new ClientID(JSONObjectUtils.getString(jsonObject, "client_id"));
250                
251                
252                URL registrationURI = JSONObjectUtils.getURL(jsonObject, "registration_client_uri");
253                
254                
255                BearerAccessToken accessToken = new BearerAccessToken(
256                                JSONObjectUtils.getString(jsonObject, "registration_access_token"));
257
258                
259                ClientMetadata metadata = ClientMetadata.parse(jsonObject);
260                
261                
262                Secret secret = null;
263                
264                if (jsonObject.containsKey("client_secret")) {
265
266                        String value = JSONObjectUtils.getString(jsonObject, "client_secret");
267
268                        Date exp = null;
269
270                        if (jsonObject.containsKey("client_secret_expires_at"))
271                                exp = new Date(JSONObjectUtils.getLong(jsonObject, "client_secret_expires_at") * 1000);
272
273                        secret = new Secret(value, exp);
274                }
275                
276                
277                Date issueDate = null;
278                
279                if (jsonObject.containsKey("client_id_issued_at")) {
280                        
281                        issueDate = new Date(JSONObjectUtils.getLong(jsonObject, "client_id_issued_at") * 1000);
282                }
283
284                
285                return new ClientInformation(id, registrationURI, accessToken, metadata, secret, issueDate);
286        }
287}