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-2013 UnboundID Corp.
026     */
027    package com.unboundid.directory.sdk.broker.types;
028    
029    import com.unboundid.util.Mutable;
030    import com.unboundid.util.NotExtensible;
031    import com.unboundid.util.ThreadSafety;
032    import com.unboundid.util.ThreadSafetyLevel;
033    import com.unboundid.util.Validator;
034    
035    import java.util.Collections;
036    import java.util.Date;
037    import java.util.Iterator;
038    import 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)
048    public final class AuthorizationCode
049    {
050      // The user that performed the authorization.
051      private final String username;
052    
053      // The granted authorities of the user that performed the authorization.
054      private final Set<String> authorities;
055    
056      // The application ID that has been authorized.
057      private final String applicationId;
058    
059      // The redirect URI the client specified.
060      private final String redirectUri;
061    
062      // The time that this authorization code was generated.
063      private final Date generateTimestamp;
064    
065      // The maximum length of time in seconds that this authorization code will be
066      // considered valid.
067      private final long maxValiditySeconds;
068    
069      // The set of scope IDs for which the application has been authorized.
070      private final Set<String> scopeIds;
071    
072      // The optional state parameter from the client.
073      private final String state;
074    
075      // Whether the client requested offline access.
076      private final boolean offlineAccess;
077    
078      // A value of this authorization code that will be exposed to clients.
079      private volatile String value;
080    
081      /**
082       * Construct a new authorization code instance.
083       *
084       * @param username The username of the resource owner this authorization code
085       *                 is associated with. Must not be null.
086       * @param authorities The authorities of the resource owner. Must not be null.
087       * @param applicationId The application ID with which this token is
088       *                      associated. Must not be null.
089       * @param redirectUri the endpoint to redirect the resource owner's user-agent
090       *                    back to the application. Must not be null.
091       * @param generateTimestamp The time that this token was generated.
092       *                          Must not be null.
093       * @param maxValiditySeconds The maximum length of time in seconds that this
094       *                           token will be considered valid. Must not be null.
095       * @param scopeIds The set of scopes for which the client has been authorized.
096       *                  Must not be null.
097       * @param state The opaque value used by the client to maintain state between
098       *              the request and callback.
099       * @param offlineAccess Whether the client requested offline access.
100       */
101      public AuthorizationCode(final String username, final Set<String> authorities,
102                               final String applicationId, final String redirectUri,
103                               final Date generateTimestamp,
104                               final long maxValiditySeconds,
105                               final Set<String> scopeIds,
106                               final String state,
107                               final boolean offlineAccess)
108      {
109        Validator.ensureNotNull(username, authorities, applicationId, redirectUri);
110        Validator.ensureNotNull(generateTimestamp, maxValiditySeconds, scopeIds);
111        this.applicationId = applicationId;
112        this.username = username;
113        this.authorities = Collections.unmodifiableSet(authorities);
114        this.redirectUri = redirectUri;
115        this.generateTimestamp = generateTimestamp;
116        this.maxValiditySeconds = maxValiditySeconds;
117        this.scopeIds = Collections.unmodifiableSet(scopeIds);
118        this.state = state;
119        this.offlineAccess = offlineAccess;
120      }
121    
122      /**
123       * Retrieves the username of the resource owner this authorization code is
124       * associated with.
125       *
126       * @return The username of the resource owner this authorization code is
127       *         associated with.
128       */
129      public String getUsername()
130      {
131        return username;
132      }
133    
134      /**
135       * Retrieves the authorities of the resource owner.
136       *
137       * @return The authorities of the resource owner.
138       */
139      public Set<String> getAuthorities()
140      {
141        return authorities;
142      }
143    
144      /**
145       * Retrieves the application ID with which this authorization code is
146       * associated.
147       *
148       * @return  The application ID with which this authorization code is
149       *          associated.
150       */
151      public String getApplicationId()
152      {
153        return applicationId;
154      }
155    
156      /**
157       * Retrieves the set of scope IDs for which the client has been authorized.
158       *
159       * @return  The set of scope IDs for which the client has been authorized.
160       */
161      public Set<String> getScopeIds()
162      {
163        return scopeIds;
164      }
165    
166      /**
167       * Retrieves the time that this authorization code was generated.
168       *
169       * @return  The time that this authorization code was generated.
170       */
171      public Date getGenerateTimestamp()
172      {
173        return generateTimestamp;
174      }
175    
176      /**
177       * Retrieves the maximum length of time in seconds that this code will be
178       * considered valid.
179       *
180       * @return  The maximum length of time in seconds that this code will be
181       *          considered valid.
182       */
183      public long getMaxValiditySeconds()
184      {
185        return maxValiditySeconds;
186      }
187    
188      /**
189       * Whether the client requested for offline access.
190       *
191       * @return  {@code true} if the client requested off offline access or
192       *          {@code false} otherwise.
193       */
194      public boolean isOfflineAccess()
195      {
196        return offlineAccess;
197      }
198    
199      /**
200       * Retrieves the opaque value used by the client to maintain state between
201       * the request and callback.
202       *
203       * @return  The opaque value used by the client to maintain state between
204       *          the request and callback or {@code null} if it was not used.
205       */
206      public String getState()
207      {
208        return state;
209      }
210    
211      /**
212       * Returns the endpoint to redirect the resource owner's user-agent back to
213       * the application.
214       *
215       * @return  The endpoint to redirect the resource owner's user-agent back to
216       *          the application.
217       */
218      public String getRedirectUri()
219      {
220        return redirectUri;
221      }
222    
223      /**
224       * Retrieves the string value of this authorization code that should be
225       * returned to the client.
226       *
227       * @return  The string value of this authorization code that should be
228       *          returned to the client.
229       */
230      public String getValue()
231      {
232        return value;
233      }
234    
235      /**
236       * Sets the string value of this authorization code that should be returned
237       * to the client.
238       *
239       * @param value The string value of this authorization code that should be
240       *              returned to the client.
241       */
242      public void setValue(final String value)
243      {
244        this.value = value;
245      }
246    
247      /**
248       * Indicates whether this authorization code is expired.
249       *
250       * @return  {@code true} if this authorization code is expired, or
251       *          {@code false} if not.
252       */
253      public boolean isExpired()
254      {
255        final long generateTS = generateTimestamp.getTime();
256        final long expirationTime = (generateTS + (1000L * maxValiditySeconds));
257        final long currentTime = System.currentTimeMillis();
258        return ((currentTime < generateTS) || (currentTime > expirationTime));
259      }
260    
261    
262    
263      /**
264       * Retrieves a hash code for this authorization code.
265       *
266       * @return  A hash code for this authorization code.
267       */
268      @Override
269      public int hashCode()
270      {
271        final int prime = 31;
272        int result = 1;
273        result = prime * result + (username != null ? username.hashCode() : 0);
274        result = prime * result + (authorities != null ?
275            authorities.hashCode() : 0);
276        result = prime * result + (applicationId != null ?
277            applicationId.hashCode() : 0);
278        result = prime * result + (state != null ? state.hashCode() : 0);
279        result = prime * result + (redirectUri != null ?
280            redirectUri.hashCode() : 0);
281        result = prime * result + (generateTimestamp != null ?
282            generateTimestamp.hashCode() : 0);
283        result = prime * result + (offlineAccess ? 1 : 0);
284        result = prime * result + (int) (maxValiditySeconds ^
285            (maxValiditySeconds >>> 32));
286        result = prime * result + (scopeIds != null ? scopeIds.hashCode() : 0);
287        return result;
288      }
289    
290      /**
291       * Indicates whether the provided object is equal to this authorization code.
292       *
293       * @param  o  The object for which to make the determination.
294       *
295       * @return  {@code true} if the provided object is equal to this authorization
296       *          code, or {@code false} if not.
297       */
298      @Override
299      public boolean equals(final Object o)
300      {
301        if (this == o)
302        {
303          return true;
304        }
305        if (o == null || getClass() != o.getClass())
306        {
307          return false;
308        }
309    
310        AuthorizationCode that = (AuthorizationCode) o;
311    
312        if (offlineAccess != that.offlineAccess)
313        {
314          return false;
315        }
316        if (maxValiditySeconds != that.maxValiditySeconds)
317        {
318          return false;
319        }
320        if (applicationId != null ? !applicationId.equals(that.applicationId) :
321            that.applicationId != null)
322        {
323          return false;
324        }
325        if (scopeIds != null ? !scopeIds.equals(that.scopeIds) :
326            that.scopeIds != null)
327        {
328          return false;
329        }
330        if (generateTimestamp != null ?
331            !generateTimestamp.equals(that.generateTimestamp) :
332            that.generateTimestamp != null)
333        {
334          return false;
335        }
336        if (username != null ? !username.equals(that.username) :
337            that.username != null)
338        {
339          return false;
340        }
341        if (authorities != null ? !authorities.equals(that.authorities) :
342            that.authorities != null)
343        {
344          return false;
345        }
346        if (redirectUri != null ? !redirectUri.equals(that.redirectUri) :
347            that.redirectUri != null)
348        {
349          return false;
350        }
351        if (state != null ? !state.equals(that.state) : that.state != null)
352        {
353          return false;
354        }
355        if (value != null ? !value.equals(that.value) : that.value != null)
356        {
357          return false;
358        }
359    
360        return true;
361      }
362    
363    
364    
365    
366      /**
367       * Retrieves a string representation of this authorization code.
368       *
369       * @return  A string representation of this authorization code.
370       */
371      @Override()
372      public String toString()
373      {
374        final StringBuilder buffer = new StringBuilder();
375        toString(buffer);
376        return buffer.toString();
377      }
378    
379    
380    
381      /**
382       * Appends a string representation of this authorization code to the provided
383       * buffer.
384       *
385       * @param  buffer  The buffer to which the string representation should be
386       *                 appended.
387       */
388      void toString(final StringBuilder buffer)
389      {
390        buffer.append("AuthorizationCode(username='");
391        buffer.append(username);
392        if (! authorities.isEmpty())
393        {
394          buffer.append(", authorities={");
395    
396          final Iterator<String> iterator = authorities.iterator();
397          while (iterator.hasNext())
398          {
399            buffer.append(iterator.next());
400            if (iterator.hasNext())
401            {
402              buffer.append(", ");
403            }
404          }
405    
406          buffer.append('}');
407        }
408        buffer.append("', appID=");
409        buffer.append(applicationId);
410        buffer.append(", generateTimestamp=");
411        buffer.append(generateTimestamp);
412        buffer.append("', maxValiditySeconds=");
413        buffer.append(maxValiditySeconds);
414        buffer.append("', offlineAccess=");
415        buffer.append(offlineAccess);
416        buffer.append(", value=");
417        buffer.append(value);
418    
419        if (state != null)
420        {
421          buffer.append("', state='");
422          buffer.append(state);
423        }
424        if (! scopeIds.isEmpty())
425        {
426          buffer.append(", authorizedScopes={");
427    
428          final Iterator<String> iterator = scopeIds.iterator();
429          while (iterator.hasNext())
430          {
431            buffer.append(iterator.next());
432            if (iterator.hasNext())
433            {
434              buffer.append(", ");
435            }
436          }
437    
438          buffer.append('}');
439        }
440        buffer.append("', redirectUri='");
441        buffer.append(redirectUri);
442    
443        buffer.append("')");
444      }
445    }