001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/ds/resource/legal-notices/cddl.txt
011 * or http://www.opensource.org/licenses/cddl1.php.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/ds/resource/legal-notices/cddl.txt.  If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 *      Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 *      Copyright 2010-2016 UnboundID Corp.
026 */
027package com.unboundid.directory.sdk.broker.types;
028
029import com.unboundid.util.Mutable;
030import com.unboundid.util.NotExtensible;
031import com.unboundid.util.ThreadSafety;
032import com.unboundid.util.ThreadSafetyLevel;
033import com.unboundid.util.Validator;
034
035import java.util.Collections;
036import java.util.Date;
037import java.util.Iterator;
038import java.util.Set;
039
040
041/**
042 * This class provides a data structure for working with OAuth2 temporary
043 * authorization codes.
044 */
045@NotExtensible()
046@Mutable()
047@ThreadSafety(level= ThreadSafetyLevel.COMPLETELY_THREADSAFE)
048public final class AuthorizationCode
049{
050  // The ID of the user that performed the authorization.
051  private final String userId;
052
053  // The application ID that has been authorized.
054  private final String applicationId;
055
056  // The redirect URI the client specified.
057  private final String redirectUri;
058
059  // The time that this authorization code was generated.
060  private final Date generateTimestamp;
061
062  // The maximum length of time in seconds that this authorization code will be
063  // considered valid.
064  private final long maxValiditySeconds;
065
066  // The set of scope IDs for which the application has been authorized.
067  private final Set<String> scopeIds;
068
069  // The optional state parameter from the client.
070  private final String state;
071
072  // The time that the user authenticated with the server, in milliseconds
073  // since midnight January 1, 1970 GMT
074  private final long authTime;
075
076  // A value of this authorization code that will be exposed to clients.
077  private volatile String value;
078
079  /**
080   * Construct a new authorization code instance.
081   *
082   * @param userId The user ID of the resource owner this authorization code
083   *                 is associated with. Must not be null.
084   * @param applicationId The application ID with which this token is
085   *                      associated. Must not be null.
086   * @param redirectUri the endpoint to redirect the resource owner's user-agent
087   *                    back to the application. Must not be null.
088   * @param generateTimestamp The time that this token was generated.
089   *                          Must not be null.
090   * @param maxValiditySeconds The maximum length of time in seconds that this
091   *                           token will be considered valid. Must not be null.
092   * @param scopeIds The set of scopes for which the client has been authorized.
093   *                  Must not be null.
094   * @param state The opaque value used by the client to maintain state between
095   *              the request and callback.
096   * @param authTime The time at which the resource owner was authenticated with
097   *                 the Identity Broker, in milliseconds since 1/1/70 12:00 AM.
098   */
099  public AuthorizationCode(final String userId, final String applicationId,
100                           final String redirectUri,
101                           final Date generateTimestamp,
102                           final long maxValiditySeconds,
103                           final Set<String> scopeIds,
104                           final String state,
105                           final long authTime)
106  {
107    Validator.ensureNotNull(userId, applicationId, redirectUri);
108    Validator.ensureNotNull(generateTimestamp, maxValiditySeconds, scopeIds);
109    this.applicationId = applicationId;
110    this.userId = userId;
111    this.redirectUri = redirectUri;
112    this.generateTimestamp = generateTimestamp;
113    this.maxValiditySeconds = maxValiditySeconds;
114    this.scopeIds = Collections.unmodifiableSet(scopeIds);
115    this.state = state;
116    this.authTime = authTime;
117  }
118
119  /**
120   * Retrieves the user ID of the resource owner this authorization code is
121   * associated with.
122   *
123   * @return The user ID of the resource owner this authorization code is
124   *         associated with.
125   */
126  public String getUserId()
127  {
128    return userId;
129  }
130
131  /**
132   * Retrieves the application ID with which this authorization code is
133   * associated.
134   *
135   * @return  The application ID with which this authorization code is
136   *          associated.
137   */
138  public String getApplicationId()
139  {
140    return applicationId;
141  }
142
143  /**
144   * Retrieves the set of scope IDs for which the client has been authorized.
145   *
146   * @return  The set of scope IDs for which the client has been authorized.
147   */
148  public Set<String> getScopeIds()
149  {
150    return scopeIds;
151  }
152
153  /**
154   * Retrieves the time that this authorization code was generated.
155   *
156   * @return  The time that this authorization code was generated.
157   */
158  public Date getGenerateTimestamp()
159  {
160    return generateTimestamp;
161  }
162
163  /**
164   * Retrieves the maximum length of time in seconds that this code will be
165   * considered valid.
166   *
167   * @return  The maximum length of time in seconds that this code will be
168   *          considered valid.
169   */
170  public long getMaxValiditySeconds()
171  {
172    return maxValiditySeconds;
173  }
174
175  /**
176   * Retrieves the opaque value used by the client to maintain state between
177   * the request and callback.
178   *
179   * @return  The opaque value used by the client to maintain state between
180   *          the request and callback or {@code null} if it was not used.
181   */
182  public String getState()
183  {
184    return state;
185  }
186
187  /**
188   * Returns the endpoint to redirect the resource owner's user-agent back to
189   * the application.
190   *
191   * @return  The endpoint to redirect the resource owner's user-agent back to
192   *          the application.
193   */
194  public String getRedirectUri()
195  {
196    return redirectUri;
197  }
198
199
200  /**
201   * Retrieves the time that the user authenticated with the server.
202   *
203   * @return Authentication time in milliseconds since midnight 1/1/1970 GMT.
204   */
205  public long getAuthTime() {
206    return authTime;
207  }
208
209  /**
210   * Retrieves the string value of this authorization code that should be
211   * returned to the client.
212   *
213   * @return  The string value of this authorization code that should be
214   *          returned to the client.
215   */
216  public String getValue()
217  {
218    return value;
219  }
220
221  /**
222   * Sets the string value of this authorization code that should be returned
223   * to the client.
224   *
225   * @param value The string value of this authorization code that should be
226   *              returned to the client.
227   */
228  public void setValue(final String value)
229  {
230    this.value = value;
231  }
232
233  /**
234   * Indicates whether this authorization code is expired.
235   *
236   * @return  {@code true} if this authorization code is expired, or
237   *          {@code false} if not.
238   */
239  public boolean isExpired()
240  {
241    final long generateTS = generateTimestamp.getTime();
242    final long expirationTime = (generateTS + (1000L * maxValiditySeconds));
243    final long currentTime = System.currentTimeMillis();
244    return currentTime > expirationTime;
245  }
246
247
248
249  /**
250   * Retrieves a hash code for this authorization code.
251   *
252   * @return  A hash code for this authorization code.
253   */
254  @Override
255  public int hashCode()
256  {
257    final int prime = 31;
258    int result = 1;
259    result = prime * result + (userId != null ? userId.hashCode() : 0);
260    result = prime * result + (applicationId != null ?
261        applicationId.hashCode() : 0);
262    result = prime * result + (state != null ? state.hashCode() : 0);
263    result = prime * result + (redirectUri != null ?
264        redirectUri.hashCode() : 0);
265    result = prime * result + (generateTimestamp != null ?
266        generateTimestamp.hashCode() : 0);
267    result = prime * result + (int) (maxValiditySeconds ^
268        (maxValiditySeconds >>> 32));
269    result = prime * result + (scopeIds != null ? scopeIds.hashCode() : 0);
270    return result;
271  }
272
273  /**
274   * Indicates whether the provided object is equal to this authorization code.
275   *
276   * @param  o  The object for which to make the determination.
277   *
278   * @return  {@code true} if the provided object is equal to this authorization
279   *          code, or {@code false} if not.
280   */
281  @Override
282  public boolean equals(final Object o)
283  {
284    if (this == o)
285    {
286      return true;
287    }
288    if (o == null || getClass() != o.getClass())
289    {
290      return false;
291    }
292
293    AuthorizationCode that = (AuthorizationCode) o;
294
295    if (maxValiditySeconds != that.maxValiditySeconds)
296    {
297      return false;
298    }
299    if (applicationId != null ? !applicationId.equals(that.applicationId) :
300        that.applicationId != null)
301    {
302      return false;
303    }
304    if (scopeIds != null ? !scopeIds.equals(that.scopeIds) :
305        that.scopeIds != null)
306    {
307      return false;
308    }
309    if (generateTimestamp != null ?
310        !generateTimestamp.equals(that.generateTimestamp) :
311        that.generateTimestamp != null)
312    {
313      return false;
314    }
315    if (userId != null ? !userId.equals(that.userId) :
316        that.userId != null)
317    {
318      return false;
319    }
320    if (redirectUri != null ? !redirectUri.equals(that.redirectUri) :
321        that.redirectUri != null)
322    {
323      return false;
324    }
325    if (state != null ? !state.equals(that.state) : that.state != null)
326    {
327      return false;
328    }
329    if (value != null ? !value.equals(that.value) : that.value != null)
330    {
331      return false;
332    }
333
334    return true;
335  }
336
337
338
339
340  /**
341   * Retrieves a string representation of this authorization code.
342   *
343   * @return  A string representation of this authorization code.
344   */
345  @Override()
346  public String toString()
347  {
348    final StringBuilder buffer = new StringBuilder();
349    toString(buffer);
350    return buffer.toString();
351  }
352
353
354
355  /**
356   * Appends a string representation of this authorization code to the provided
357   * buffer.
358   *
359   * @param  buffer  The buffer to which the string representation should be
360   *                 appended.
361   */
362  void toString(final StringBuilder buffer)
363  {
364    buffer.append("AuthorizationCode(userId='");
365    buffer.append(userId);
366    buffer.append("', appID=");
367    buffer.append(applicationId);
368    buffer.append(", generateTimestamp=");
369    buffer.append(generateTimestamp);
370    buffer.append("', maxValiditySeconds=");
371    buffer.append(maxValiditySeconds);
372    buffer.append(", value=");
373    buffer.append(value);
374
375    if (state != null)
376    {
377      buffer.append("', state='");
378      buffer.append(state);
379    }
380    if (! scopeIds.isEmpty())
381    {
382      buffer.append(", authorizedScopes={");
383
384      final Iterator<String> iterator = scopeIds.iterator();
385      while (iterator.hasNext())
386      {
387        buffer.append(iterator.next());
388        if (iterator.hasNext())
389        {
390          buffer.append(", ");
391        }
392      }
393
394      buffer.append('}');
395    }
396    buffer.append("', redirectUri='");
397    buffer.append(redirectUri);
398
399    buffer.append("')");
400  }
401}