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 * docs/licenses/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 * docs/licenses/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 2016-2019 Ping Identity Corporation
026 */
027
028
029package com.unboundid.directory.sdk.common.types;
030
031import com.unboundid.util.NotExtensible;
032
033import java.util.Collections;
034import java.util.Map;
035import java.util.Set;
036import java.util.concurrent.TimeUnit;
037
038/**
039 * Object returned from a request to an AccessTokenValidator to validate a
040 * token. The fields of this object are derived from the IETF OAuth 2.0 Token
041 * Introspection specification (RFC7662).
042 * <p>
043 * The decision as to whether an access token is accepted or not varies by
044 * product. For the Directory Server, Directory Proxy Server,
045 * Data Sync Server, or Data Metrics Server, different REST APIs
046 * may enforce different authorization rules, depending on their configuration;
047 * please refer to the relevant documentation. In general, a token's
048 * {@code active} property must be true.
049 * <p>
050 * For the Data Governance Server, authorization decisions are made by the policy
051 * engine. All properties of the TokenValidationResult may be accessed by
052 * policies; however, the default policy may only examine a subset of those
053 * properties (e.g. especially the {@code active} property).
054 */
055@NotExtensible()
056public final class TokenValidationResult {
057
058
059  private final String accessToken;
060
061  private final Boolean active;
062
063  private final Set<String> scope;
064
065  private final String clientId;
066
067  private final String username;
068
069  private final String tokenType;
070
071  private final Long expirationTime;
072
073  private final Long issuedAt;
074
075  private final Long notUsedBefore;
076
077  private final String tokenSubject;
078
079  private final Set<String> audience;
080
081  private final String tokenIdentifier;
082
083  /**
084   * This field contains any extension values implemented by the
085   * Token Validator.
086   */
087  private final Map<String,Object> additionalProperties;
088
089  /**
090   * Private constructor for builder.
091   * @param builder Builder source for properties.
092   */
093  private TokenValidationResult(final Builder builder)
094  {
095    this.accessToken = builder.accessToken;
096    this.active = builder.active;
097    this.scope = builder.scope;
098    this.clientId = builder.clientId;
099    this.username = builder.username;
100    this.tokenType = builder.tokenType;
101    this.expirationTime = builder.expirationTime;
102    this.issuedAt = builder.issuedAt;
103    this.notUsedBefore = builder.notUsedBefore;
104    this.tokenSubject = builder.tokenSubject;
105    this.audience = builder.audience;
106    this.tokenIdentifier = builder.tokenIdentifier;
107    this.additionalProperties = (builder.additionalProperties == null) ?
108        Collections.<String,Object>emptyMap() :
109        builder.additionalProperties;
110  }
111
112  /**
113   * Get the actual access token as issued by the authorization server.
114   * @return the access token. May be null.
115   */
116  public String getAccessToken() {
117    return accessToken;
118  }
119
120  /**
121   * Get whether the token is active. Per RFC 7662, a value of true for this
122   * property indicates that the given token was issued by the Token
123   * Validator's associated authorization server, has not been revoked by the
124   * resource owner, and is within its given time window of validity
125   * (e.g. after its issuance time and before its expiration time).
126   * @return the active state.
127   */
128  public Boolean getActive() {
129    return active;
130  }
131
132  /**
133   * Get the scopes granted to this token.
134   * @return set of scope names.
135   */
136  public Set<String> getScope() {
137    return scope;
138  }
139
140  /**
141   * Get the OAuth2 client Id of the client that requested the token.
142   * @return client Id string.
143   */
144  public String getClientId() {
145    return clientId;
146  }
147
148  /**
149   * Get a human-readable user name for the resource owner that authorized
150   * the token.
151   * @return user name string.
152   */
153  public String getUsername() {
154    return username;
155  }
156
157  /**
158   * Get the token type.  The type of the token is defined in section 5.1 of
159   * OAuth 2.0 [RFC6749].
160   * @return token type string.
161   */
162  public String getTokenType() {
163    return tokenType;
164  }
165
166  /**
167   * Get the token expiration time in seconds since January 1 1970 UTC.
168   * @return expiration time in seconds.
169   */
170  public Long getExpirationTime() {
171    return expirationTime;
172  }
173
174  /**
175   * Get the token issue time in seconds since January 1 1970 UTC.
176   * @return token issue time in seconds.
177   */
178  public Long getIssuedAt() {
179    return issuedAt;
180  }
181
182  /**
183   * Get the not used before time in seconds since January 1 1070 UTC.
184   * @return not used before time in seconds.
185   */
186  public Long getNotUsedBefore() {
187    return notUsedBefore;
188  }
189
190  /**
191   * Get the token subject as defined in JWT [RFC7519].  This value should
192   * contain the subject ID as known to the external authorization server rather
193   * than the local server.
194   * @return token subject string.
195   */
196  public String getTokenSubject() {
197    return tokenSubject;
198  }
199
200  /**
201   * Get the token's intended audience(s).  The audience is a Service-specific
202   * identifier representing the intended audience(s) for this token, as
203   * defined in JWT [RFC7519].
204   * @return token audience.
205   */
206  public Set<String> getAudience() {
207    return audience;
208  }
209
210  /**
211   * Get the unique identifier for this token. as defined in section 4.1.7 of
212   * JWT [RFC7519].
213   * @return token unique identifier string.
214   */
215  public String getTokenIdentifier() {
216    return tokenIdentifier;
217  }
218
219  /**
220   * Get any extension properties associated with the token.
221   * @return Map of property names to values.
222   */
223  public Map<String, Object> getAdditionalProperties() {
224    return additionalProperties;
225  }
226
227  /**
228   * A Builder for TokenValidationResult.
229   */
230  public static class Builder
231  {
232    private String accessToken;
233    private Boolean active;
234    private Set<String> scope;
235    private String clientId;
236    private String username;
237    private String tokenType;
238    private Long expirationTime;
239    private Long issuedAt;
240    private Long notUsedBefore;
241    private String tokenSubject;
242    private Set<String> audience;
243    private String tokenIdentifier;
244    private Map<String,Object> additionalProperties;
245
246
247    /**
248     * Creates a new builder object.
249     * @param active      true if the token is active, false if not.  Per RFC
250     *                    7662, a value of true for this property indicates
251     *                    that the given token was issued by the Token
252     *                    Validator's associated authorization server, has not
253     *                    been revoked by the resource owner, and is within its
254     *                    given time window of validity (e.g. after its issuance
255     *                    time and before its expiration time).
256     */
257    public Builder(final boolean active)
258    {
259      this(null, active);
260    }
261
262    /**
263     * Creates a new builder object.
264     * @param accessToken the actual access token, as received from the
265     *                    authorization server.  May be null.
266     * @param active      true if the token is active, false if not.  Per RFC
267     *                    7662, a value of true for this property indicates
268     *                    that the given token was issued by the Token
269     *                    Validator's associated authorization server, has not
270     *                    been revoked by the resource owner, and is within its
271     *                    given time window of validity (e.g. after its issuance
272     *                    time and before its expiration time).
273     */
274    public Builder(final String accessToken, final boolean active)
275    {
276      this.accessToken = accessToken;
277      this.active = active;
278      setScope(Collections.<String>emptySet());
279    }
280
281    /**
282     * Set the active field of the token validation result.
283     *
284     * @param active true if the token is active, false if not.  Per RFC 7662,
285     *               a value of true for this property indicates that the given
286     *               token was issued by the Token Validator's associated
287     *               authorization server, has not been revoked by the resource
288     *               owner, and is within its given time window of validity
289     *               (e.g. after its issuance time and before its expiration
290     *               time).
291     * @return this.
292     */
293    public Builder setActive(final boolean active)
294    {
295      this.active = active;
296      return this;
297    }
298
299    /**
300     * Set the optional scope field of the token validation result.
301     *
302     * @param scope A list of strings representing the scopes associated with
303     *              this token.
304     * @return this.
305     */
306    public Builder setScope(final Set<String> scope)
307    {
308      this.scope = (scope == null) ? Collections.<String>emptySet() : scope;
309      return this;
310    }
311
312    /**
313     * Set the optional clientId field of the token validation result.
314     *
315     * @param clientId Client identifier for the OAuth 2.0 client that
316     *                 requested this token.
317     * @return this.
318     */
319    public Builder setClientId(final String clientId)
320    {
321      this.clientId = clientId;
322      return this;
323    }
324
325    /**
326     * Set the optional username field of the token validation result.
327     *
328     * @param username Human-readable identifier for the resource owner who
329     *                 authorized this token.
330     * @return this.
331     */
332    public Builder setUsername(final String username)
333    {
334      this.username = username;
335      return this;
336    }
337
338    /**
339     * Set the optional tokenType field of the token validation result.
340     *
341     * @param tokenType Type of the token as defined in section 5.1 of OAuth
342     *                  2.0 [RFC6749].
343     * @return this.
344     */
345    public Builder setTokenType(final String tokenType)
346    {
347      this.tokenType = tokenType;
348      return this;
349    }
350
351    /**
352     * Set the optional expirationTime field of the token validation result.
353     *
354     * @param expirationTime Integer timestamp, measured in the number of
355     *                       time units since January 1 1970 UTC, indicating
356     *                       when this token will expire.
357     * @param timeUnit the time units of the specified expiration time.
358     * @return this.
359     */
360    public Builder setExpirationTime(
361        final long expirationTime,
362        final TimeUnit timeUnit)
363    {
364      this.expirationTime = timeUnit.toSeconds(expirationTime);
365      return this;
366    }
367
368    /**
369     * Set the optional issuedAt field of the token validation result.
370     *
371     * @param issuedAt Integer timestamp, measured in the number of time
372     *                 units since January 1 1970 UTC, indicating when this
373     *                 token was originally issued.
374     * @param timeUnit the time units of the specified issuedAt time.
375     * @return this.
376     */
377    public Builder setIssuedAt(
378        final long issuedAt,
379        final TimeUnit timeUnit)
380    {
381      this.issuedAt = timeUnit.toSeconds(issuedAt);
382      return this;
383    }
384
385    /**
386     * Set the optional notUsedBefore field of the token validation result.
387     *
388     * @param notUsedBefore Integer timestamp, measured in the number of
389     *                      time units since January 1 1970 UTC, indicating
390     *                      when this token is not to be used before.
391     * @param timeUnit the time units of the specified notUsedBefore time.
392     * @return this.
393     */
394    public Builder setNotUsedBefore(
395        final long notUsedBefore,
396        final TimeUnit timeUnit)
397    {
398      this.notUsedBefore = timeUnit.toSeconds(notUsedBefore);
399      return this;
400    }
401
402    /**
403     * Set the optional subjectToken field of the token validation result.
404     *
405     * @param tokenSubject Subject of the token, as defined in JWT [RFC7519].
406     *                     This value should contain the subject ID as known to
407     *                     the external authorization server rather than the
408     *                     local server.
409     * @return this.
410     */
411    public Builder setTokenSubject(final String tokenSubject)
412    {
413      this.tokenSubject = tokenSubject;
414      return this;
415    }
416
417    /**
418     * Set the optional audience field of the token validation result.
419     *
420     * @param audience Service-specific identifiers representing the
421     *                 intended audience(s) for this token, as defined in
422     *                 JWT [RFC7519].
423     * @return this.
424     */
425    public Builder setAudience(final Set<String> audience)
426    {
427      this.audience = audience;
428      return this;
429    }
430
431    /**
432     * Set the optional tokenIdentifier field of the token validation result.
433     *
434     * @param tokenIdentifier Unique string identifier for the token, as
435     *                        defined in section 4.1.7 of JWT [RFC7519].
436     * @return this.
437     */
438    public Builder setTokenIdentifier(final String tokenIdentifier)
439    {
440      this.tokenIdentifier = tokenIdentifier;
441      return this;
442    }
443
444    /**
445     * Set the optional additionalProperties field of the token validation
446     * result.
447     * @param properties Map of property names to values, containing any
448     *                   extension values implemented by the
449     *                   AccessTokenValidator.
450     * @return this.
451     */
452    public Builder setAdditionalProperties(
453        final Map<String,Object> properties) {
454
455      this.additionalProperties = properties;
456      return this;
457    }
458
459    /**
460     * Builds a new TokenValidationResult from the parameters
461     * previously supplied to the builder.
462     *
463     * @return a new TokenValidationResult.
464     */
465    public TokenValidationResult build()
466    {
467      return new TokenValidationResult(this);
468    }
469  }
470
471}