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 * This class provides a data structure for working with OAuth2 access tokens.
042 */
043@NotExtensible()
044@Mutable()
045@ThreadSafety(level= ThreadSafetyLevel.COMPLETELY_THREADSAFE)
046public final class AccessToken extends Token
047{
048  // The user ID associated with this token.
049  private final String userId;
050
051  // The set of scope IDs for which the application has requested or authorized.
052  private final Set<String> scopeIds;
053
054  // The refresh token associated with this access token.
055  private volatile RefreshToken refreshToken;
056
057  /**
058   * Construct a new access token instance.
059   *
060   * @param userId The user ID of the resource owner this access token is
061   *                 associated with or the application ID if resource owner
062   *                 authentication was not performed.
063   * @param applicationId The application ID with which this token is
064   *                      associated. Must not be null.
065   * @param generateTimestamp The time that this token was generated. Must not
066   *                          be null.
067   * @param maxValiditySeconds The maximum length of time in seconds that this
068   *                           token will be considered valid. Must not be null
069   *                           and must not be negative.
070   * @param scopeIds The set of scopes for which the client has been authorized.
071   *                 Must not be null.
072   */
073  public AccessToken(final String userId, final String applicationId,
074                     final Date generateTimestamp,
075                     final long maxValiditySeconds, final Set<String> scopeIds)
076  {
077    super(applicationId, scopeIds, generateTimestamp, maxValiditySeconds);
078    this.userId = userId;
079    this.scopeIds = Collections.unmodifiableSet(scopeIds);
080  }
081
082  /**
083   * Retrieves the user ID of the resource owner this access token is
084   * associated with. Some grant types don't require resource owner involvement
085   * (ie. client_credentials), the userId may be equal to the application ID in
086   * such cases.
087   *
088   * @return The user ID of the resource owner this access token is associated
089   *         with or equal to the application ID if resource owner
090   *         authentication was not performed.
091   */
092  public String getUserId()
093  {
094    return userId;
095  }
096
097  /**
098   * Retrieves the refresh token associated with this access token.
099   *
100   * @return The refresh token associated with this access token or {@code null}
101   *         if there is no associated refresh token.
102   */
103  public RefreshToken getRefreshToken()
104  {
105    return refreshToken;
106  }
107
108  /**
109   * Sets the refresh token associated with this access token.
110   *
111   * @param refreshToken The refresh token associated with this access token.
112   */
113  public void setRefreshToken(final RefreshToken refreshToken)
114  {
115    Validator.ensureNotNull(refreshToken);
116    this.refreshToken = refreshToken;
117  }
118
119  /**
120   * Retrieves a hash code for this access token.
121   *
122   * @return  A hash code for this access token.
123   */
124  @Override
125  public int hashCode()
126  {
127    final int prime = 31;
128    int result = super.hashCode();
129    result = prime * result + (userId != null ? userId.hashCode() : 0);
130    result = prime * result + (scopeIds != null ? scopeIds.hashCode() : 0);
131    return result;
132  }
133
134  /**
135   * Indicates whether the provided object is equal to this access token.
136   *
137   * @param  o  The object for which to make the determination.
138   *
139   * @return  {@code true} if the provided object is equal to this authorization
140   *          code, or {@code false} if not.
141   */
142  @Override
143  public boolean equals(final Object o)
144  {
145    if (this == o)
146    {
147      return true;
148    }
149    if (o == null || getClass() != o.getClass())
150    {
151      return false;
152    }
153
154    AccessToken that = (AccessToken) o;
155
156    if (scopeIds != null ?
157        !scopeIds.equals(that.scopeIds) :
158        that.scopeIds != null)
159    {
160      return false;
161    }
162    if (userId != null ?
163        !userId.equals(that.userId) :
164        that.userId != null)
165    {
166      return false;
167    }
168    if (refreshToken != null ?
169        !refreshToken.equals(that.refreshToken) :
170        that.refreshToken != null)
171    {
172      return false;
173    }
174
175    return super.equals(o);
176  }
177
178  /**
179   * Appends a string representation of this access token to the provided
180   * buffer.
181   *
182   * @param  buffer  The buffer to which the string representation should be
183   *                 appended.
184   */
185  protected void toString(final StringBuilder buffer)
186  {
187    buffer.append("AccessToken(userId='");
188    buffer.append(userId);
189    buffer.append("', appID=");
190    buffer.append(getApplicationId());
191    buffer.append(", generateTimestamp=");
192    buffer.append(getGenerateTimestamp());
193    buffer.append("', maxValiditySeconds=");
194    buffer.append(getMaxValiditySeconds());
195    buffer.append(", value=");
196    buffer.append(getValue());
197
198    if (! scopeIds.isEmpty())
199    {
200      buffer.append(", scopes={");
201
202      final Iterator<String> iterator = scopeIds.iterator();
203      while (iterator.hasNext())
204      {
205        buffer.append(iterator.next());
206        if (iterator.hasNext())
207        {
208          buffer.append(", ");
209        }
210      }
211
212      buffer.append('}');
213    }
214
215    buffer.append("')");
216  }
217}