001/*
002 * Copyright 2023-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2023-2024 Ping Identity Corporation
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *    http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020/*
021 * Copyright (C) 2023-2024 Ping Identity Corporation
022 *
023 * This program is free software; you can redistribute it and/or modify
024 * it under the terms of the GNU General Public License (GPLv2 only)
025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
026 * as published by the Free Software Foundation.
027 *
028 * This program is distributed in the hope that it will be useful,
029 * but WITHOUT ANY WARRANTY; without even the implied warranty of
030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
031 * GNU General Public License for more details.
032 *
033 * You should have received a copy of the GNU General Public License
034 * along with this program; if not, see <http://www.gnu.org/licenses>.
035 */
036package com.unboundid.ldap.sdk.unboundidds.controls;
037
038
039
040import com.unboundid.ldap.sdk.Control;
041import com.unboundid.ldap.sdk.JSONControlDecodeHelper;
042import com.unboundid.ldap.sdk.LDAPException;
043import com.unboundid.ldap.sdk.ResultCode;
044import com.unboundid.util.NotMutable;
045import com.unboundid.util.NotNull;
046import com.unboundid.util.ThreadSafety;
047import com.unboundid.util.ThreadSafetyLevel;
048import com.unboundid.util.json.JSONField;
049import com.unboundid.util.json.JSONObject;
050
051import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*;
052
053
054
055/**
056 * This class provides a request control that can be included in a bind request
057 * to indicate that if the bind succeeds, the server should generate an access
058 * token that can be used in the
059 * {@link com.unboundid.ldap.sdk.OAUTHBEARERBindRequest} to authenticate as the
060 * user for subsequent authentication attempts.  This can be useful for cases in
061 * which the initial authentication attempt is made with credentials that cannot
062 * be replayed, like a those involving a one-time password (e.g.,
063 * {@link com.unboundid.ldap.sdk.unboundidds.UnboundIDTOTPBindRequest},
064 * {@link com.unboundid.ldap.sdk.unboundidds.UnboundIDDeliveredOTPBindRequest},
065 * or
066 * {@link com.unboundid.ldap.sdk.unboundidds.UnboundIDYubiKeyOTPBindRequest}).
067 * <BR>
068 * <BLOCKQUOTE>
069 *   <B>NOTE:</B>  This class, and other classes within the
070 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
071 *   supported for use against Ping Identity, UnboundID, and
072 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
073 *   for proprietary functionality or for external specifications that are not
074 *   considered stable or mature enough to be guaranteed to work in an
075 *   interoperable way with other types of LDAP servers.
076 * </BLOCKQUOTE>
077 * <BR>
078 * The OID for this control is 1.3.6.1.4.1.30221.2.5.67, the criticality may be
079 * either {@code true} or {@code false}, and it does not have a value.
080 * <BR><BR>
081 * <H2>Example</H2>
082 * The following example demonstrates the process of requesting an access token
083 * when performing one bind, and then using that access token to authenticate
084 * with subsequent bind operations:
085 * <PRE>
086 *   // Authenticate with the UNBOUNDID-TOTP SASL mechanism, which uses a
087 *   // time-based one-time password.  Since it's a one-time password, it
088 *   // can't be reused.  If we want to re-authenticate as the same user,
089 *   // we can request that the server return an access token that we can
090 *   // use instead.
091 *   GenerateAccessTokenRequestControl requestControl =
092 *        new GenerateAccessTokenRequestControl();
093 *   SingleUseTOTPBindRequest totpBindRequest =
094 *        new SingleUseTOTPBindRequest(authenticationID, authorizationID,
095 *             totpPassword, staticPassword, requestControl);
096 *
097 *   BindResult totpBindResult = connection.bind(totpBindRequest);
098 *
099 *   // Get the access token from the bind result.
100 *   String accessToken = null;
101 *   GenerateAccessTokenResponseControl responseControl =
102 *        GenerateAccessTokenResponseControl.get(totpBindResult);
103 *   if (responseControl != null)
104 *   {
105 *     accessToken = responseControl.getAccessToken();
106 *   }
107 *
108 *   // The next time you need to authenticate, you can use the access
109 *   // token with an OAUTHBEARER SASL mechanism using the access token.
110 *   if (accessToken != null)
111 *   {
112 *     OAUTHBEARERBindRequest tokenBindRequest =
113 *          new OAUTHBEARERBindRequest(accessToken);
114 *     BindResult tokenBindResult = connection.bind(tokenBindRequest);
115 *   }
116 * </PRE>
117 *
118 * @see  GenerateAccessTokenResponseControl
119 */
120@NotMutable()
121@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
122public final class GenerateAccessTokenRequestControl
123       extends Control
124{
125  /**
126   * The OID (1.3.6.1.4.1.30221.2.5.67) for the generate access token request
127   * control.
128   */
129  @NotNull public static final  String GENERATE_ACCESS_TOKEN_REQUEST_OID =
130       "1.3.6.1.4.1.30221.2.5.67";
131
132
133
134  /**
135   * The serial version UID for this serializable class.
136   */
137  private static final long serialVersionUID = -7583146521476190879L;
138
139
140
141  /**
142   * Creates a new generate access token request control.  It will be marked
143   * critical.
144   */
145  public GenerateAccessTokenRequestControl()
146  {
147    this(true);
148  }
149
150
151
152  /**
153   * Creates a new generate access token request control with the specified
154   * criticality.
155   *
156   * @param  isCritical  Indicates whether this control should be marked
157   *                     critical.
158   */
159  public GenerateAccessTokenRequestControl(final boolean isCritical)
160  {
161    super(GENERATE_ACCESS_TOKEN_REQUEST_OID, isCritical,  null);
162  }
163
164
165
166  /**
167   * Creates a new generate access token request control which is decoded from
168   * the provided generic control.
169   *
170   * @param  control  The generic control to be decoded as a generate access
171   *                  token request control.
172   *
173   * @throws  LDAPException  If the provided control cannot be decoded as a
174   *                         generate access token request control.
175   */
176  public GenerateAccessTokenRequestControl(@NotNull final Control control)
177         throws LDAPException
178  {
179    super(control);
180
181    if (control.hasValue())
182    {
183      throw new LDAPException(ResultCode.DECODING_ERROR,
184           ERR_GENERATE_ACCESS_TOKEN_REQUEST_HAS_VALUE.get());
185    }
186  }
187
188
189
190  /**
191   * {@inheritDoc}
192   */
193  @Override()
194  @NotNull()
195  public String getControlName()
196  {
197    return INFO_CONTROL_NAME_GENERATE_ACCESS_TOKEN_REQUEST.get();
198  }
199
200
201
202  /**
203   * Retrieves a representation of this generate access token request control as
204   * a JSON object.  The JSON object uses the following fields (note that since
205   * this control does not have a value, neither the {@code value-base64} nor
206   * {@code value-json} fields may be present):
207   * <UL>
208   *   <LI>
209   *     {@code oid} -- A mandatory string field whose value is the object
210   *     identifier for this control.  For the generate access token request
211   *     control, the OID is "1.3.6.1.4.1.30221.2.5.67".
212   *   </LI>
213   *   <LI>
214   *     {@code control-name} -- An optional string field whose value is a
215   *     human-readable name for this control.  This field is only intended for
216   *     descriptive purposes, and when decoding a control, the {@code oid}
217   *     field should be used to identify the type of control.
218   *   </LI>
219   *   <LI>
220   *     {@code criticality} -- A mandatory Boolean field used to indicate
221   *     whether this control is considered critical.
222   *   </LI>
223   * </UL>
224   *
225   * @return  A JSON object that contains a representation of this control.
226   */
227  @Override()
228  @NotNull()
229  public JSONObject toJSONControl()
230  {
231    return new JSONObject(
232         new JSONField(JSONControlDecodeHelper.JSON_FIELD_OID,
233              GENERATE_ACCESS_TOKEN_REQUEST_OID),
234         new JSONField(JSONControlDecodeHelper.JSON_FIELD_CONTROL_NAME,
235              INFO_CONTROL_NAME_GENERATE_ACCESS_TOKEN_REQUEST.get()),
236         new JSONField(JSONControlDecodeHelper.JSON_FIELD_CRITICALITY,
237              isCritical()));
238  }
239
240
241
242  /**
243   * Attempts to decode the provided object as a JSON representation of a
244   * generate access token request control.
245   *
246   * @param  controlObject  The JSON object to be decoded.  It must not be
247   *                        {@code null}.
248   * @param  strict         Indicates whether to use strict mode when decoding
249   *                        the provided JSON object.  If this is {@code true},
250   *                        then this method will throw an exception if the
251   *                        provided JSON object contains any unrecognized
252   *                        fields.  If this is {@code false}, then unrecognized
253   *                        fields will be ignored.
254   *
255   * @return  The generate access token request control that was decoded from
256   *          the provided JSON object.
257   *
258   * @throws  LDAPException  If the provided JSON object cannot be parsed as a
259   *                         valid generate access token request control.
260   */
261  @NotNull()
262  public static GenerateAccessTokenRequestControl decodeJSONControl(
263              @NotNull final JSONObject controlObject,
264              final boolean strict)
265         throws LDAPException
266  {
267    final JSONControlDecodeHelper jsonControl = new JSONControlDecodeHelper(
268         controlObject, strict, false, false);
269
270    return new GenerateAccessTokenRequestControl(jsonControl.getCriticality());
271  }
272
273
274
275  /**
276   * {@inheritDoc}
277   */
278  @Override()
279  public void toString(@NotNull final StringBuilder buffer)
280  {
281    buffer.append("GenerateAccessTokenRequestControl(isCritical=");
282    buffer.append(isCritical());
283    buffer.append(')');
284  }
285}