Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2013-2024 Ping Identity Corporation
* All Rights Reserved.
*/
/*
* Copyright 2013-2024 Ping Identity Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright (C) 2013-2024 Ping Identity Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License (GPLv2 only)
* or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
package com.unboundid.ldap.sdk.unboundidds.extensions;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import com.unboundid.asn1.ASN1Element;
import com.unboundid.asn1.ASN1OctetString;
import com.unboundid.asn1.ASN1Sequence;
import com.unboundid.ldap.sdk.Control;
import com.unboundid.ldap.sdk.ExtendedRequest;
import com.unboundid.ldap.sdk.ExtendedResult;
import com.unboundid.ldap.sdk.LDAPConnection;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.ResultCode;
import com.unboundid.util.Debug;
import com.unboundid.util.NotMutable;
import com.unboundid.util.NotNull;
import com.unboundid.util.Nullable;
import com.unboundid.util.ObjectPair;
import com.unboundid.util.StaticUtils;
import com.unboundid.util.ThreadSafety;
import com.unboundid.util.ThreadSafetyLevel;
import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
/**
* This class provides an implementation of an extended request that may be used
* to request that the Directory Server deliver a one-time password to an end
* user that they may use to authenticate via an
* {@link com.unboundid.ldap.sdk.unboundidds.UnboundIDDeliveredOTPBindRequest}.
*
*
* NOTE: This class, and other classes within the
* {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
* supported for use against Ping Identity, UnboundID, and
* Nokia/Alcatel-Lucent 8661 server products. These classes provide support
* for proprietary functionality or for external specifications that are not
* considered stable or mature enough to be guaranteed to work in an
* interoperable way with other types of LDAP servers.
*
*
* Notes on the recommended use of this extended request:
*
*
Whenever possible, the user's static password should be provided.
* However, the server will allow the static password to be omitted if the
* authentication ID included in the request matches the authorization
* identity of the extended operation (either because that user is already
* authenticated on the connection, or because the request includes a
* proxied authorization or intermediate client control specifying that
* identity). In that case, the operation will be able to act as a
* "step-up" mechanism, providing further proof of the identity of an
* already-authenticated client rather than performing the complete
* authentication process.
*
The request offers two mechanisms for indicating which delivery
* mechanism(s) should be considered: an option to specify just the
* delivery mechanism names, and an option to specify the names along with
* recipient IDs. At most one of these elements must be present in the
* request. If neither is present, the server will attempt to determine
* which delivery mechanisms and recipient IDs should be used. If the
* set of preferred delivery mechanisms includes multiple items, the
* server will attempt them in the order provided until it is able to
* successfully deliver the message. The server will not attempt to
* use any other delivery mechanisms that may be configured if the request
* includes a list of preferred delivery mechanisms.
*
Although the message elements (message subject, and full and compact
* text before and after the OTP) are optional, it is recommended that
* they be supplied by the client. The server will provide a generic
* message if no message elements are included in the request.
*
*
* The OID for this extended request is 1.3.6.1.4.1.30221.2.6.24. It must have
* a value, and that value should have the following encoding:
*
*
* @see com.unboundid.ldap.sdk.unboundidds.UnboundIDDeliveredOTPBindRequest
* @see DeliverOneTimePasswordExtendedResult
*/
@NotMutable()
@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
public final class DeliverOneTimePasswordExtendedRequest
extends ExtendedRequest
{
/**
* The OID (1.3.6.1.4.1.30221.2.6.24) for the deliver one-time password
* extended request.
*/
@NotNull public static final String DELIVER_OTP_REQUEST_OID =
"1.3.6.1.4.1.30221.2.6.24";
/**
* The BER type for the authentication ID element.
*/
private static final byte TYPE_AUTHN_ID = (byte) 0x80;
/**
* The BER type for the static password element.
*/
private static final byte TYPE_PASSWORD = (byte) 0x81;
/**
* The BER type for the preferred delivery mechanism names element.
*/
private static final byte TYPE_PREFERRED_DELIVERY_MECHANISM_NAMES =
(byte) 0xA2;
/**
* The BER type for the preferred delivery mechanism names and IDs element.
*/
private static final byte TYPE_PREFERRED_DELIVERY_MECHANISM_NAMES_AND_IDS =
(byte) 0xA3;
/**
* The BER type for the "message subject" element of the value sequence.
*/
private static final byte MESSAGE_SUBJECT_BER_TYPE = (byte) 0x84;
/**
* The BER type for the "full text before OTP" element of the value
* sequence.
*/
private static final byte FULL_TEXT_BEFORE_OTP_BER_TYPE = (byte) 0x85;
/**
* The BER type for the "full text after OTP" element of the value
* sequence.
*/
private static final byte FULL_TEXT_AFTER_OTP_BER_TYPE = (byte) 0x86;
/**
* The BER type for the "compact text before OTP" element of the value
* sequence.
*/
private static final byte COMPACT_TEXT_BEFORE_OTP_BER_TYPE = (byte) 0x87;
/**
* The BER type for the "compact text after OTP" element of the value
* sequence.
*/
private static final byte COMPACT_TEXT_AFTER_OTP_BER_TYPE = (byte) 0x88;
/**
* The serial version UID for this serializable class.
*/
private static final long serialVersionUID = 1259250969726758847L;
// The static password to include in the request.
@Nullable private final ASN1OctetString staticPassword;
// The list of preferred delivery mechanisms to include in the request.
@NotNull private final List>
preferredDeliveryMechanisms;
// The authentication ID to include in the request.
@NotNull private final String authenticationID;
// The text to include after the OTP in a compact message.
@Nullable private final String compactTextAfterOTP;
// The text to include before the OTP in a compact message.
@Nullable private final String compactTextBeforeOTP;
// The text to include after the OTP in a message without size constraints.
@Nullable private final String fullTextAfterOTP;
// The text to include before the OTP in a message without size constraints.
@Nullable private final String fullTextBeforeOTP;
// The text to use as the message subject.
@Nullable private final String messageSubject;
/**
* Creates a new deliver one-time password extended request with the provided
* information.
*
* @param authenticationID The authentication ID for the user to
* whom the one-time password should be
* delivered. It must not be
* {@code null}.
* @param staticPassword The static password for the user to
* whom the one-time password should be
* delivered. It may be {@code null} if
* this request is intended to be used
* to step-up an existing authentication
* rather than perform a new
* authentication (in which case the
* provided authentication ID must match
* the operation's authorization ID).
* @param preferredDeliveryMechanisms The names of the preferred delivery
* mechanisms for the one-time password.
* It may be {@code null} or empty if the
* server should select an appropriate
* delivery mechanism. If it is
* non-{@code null} and non-empty, then
* only the listed mechanisms will be
* considered for use, even if the server
* supports alternate mechanisms not
* included in this list.
*/
public DeliverOneTimePasswordExtendedRequest(
@NotNull final String authenticationID,
@Nullable final String staticPassword,
@Nullable final String... preferredDeliveryMechanisms)
{
this(authenticationID, staticPassword,
StaticUtils.toList(preferredDeliveryMechanisms));
}
/**
* Creates a new deliver one-time password extended request with the provided
* information.
*
* @param authenticationID The authentication ID for the user to
* whom the one-time password should be
* delivered. It must not be
* {@code null}.
* @param staticPassword The static password for the user to
* whom the one-time password should be
* delivered. It may be {@code null} if
* this request is intended to be used
* to step-up an existing authentication
* rather than perform a new
* authentication (in which case the
* provided authentication ID must match
* the operation's authorization ID).
* @param preferredDeliveryMechanisms The names of the preferred delivery
* mechanisms for the one-time password.
* It may be {@code null} or empty if the
* server should select an appropriate
* delivery mechanism. If it is
* non-{@code null} and non-empty, then
* only the listed mechanisms will be
* considered for use, even if the server
* supports alternate mechanisms not
* included in this list.
*/
public DeliverOneTimePasswordExtendedRequest(
@NotNull final String authenticationID,
@Nullable final byte[] staticPassword,
@Nullable final String... preferredDeliveryMechanisms)
{
this(authenticationID, staticPassword,
StaticUtils.toList(preferredDeliveryMechanisms));
}
/**
* Creates a new deliver one-time password extended request with the provided
* information.
*
* @param authenticationID The authentication ID for the user to
* whom the one-time password should be
* delivered. It must not be
* {@code null}.
* @param staticPassword The static password for the user to
* whom the one-time password should be
* delivered. It may be {@code null} if
* this request is intended to be used
* to step-up an existing authentication
* rather than perform a new
* authentication (in which case the
* provided authentication ID must match
* the operation's authorization ID).
* @param preferredDeliveryMechanisms The names of the preferred delivery
* mechanisms for the one-time password.
* It may be {@code null} or empty if the
* server should select an appropriate
* delivery mechanism. If it is
* non-{@code null} and non-empty, then
* only the listed mechanisms will be
* considered for use, even if the server
* supports alternate mechanisms not
* included in this list.
* @param controls The set of controls to include in the
* request. It may be {@code null} or
* empty if no controls should be
* included.
*/
public DeliverOneTimePasswordExtendedRequest(
@NotNull final String authenticationID,
@Nullable final String staticPassword,
@Nullable final List preferredDeliveryMechanisms,
@Nullable final Control... controls)
{
this(authenticationID,
(staticPassword == null
? null
: new ASN1OctetString(TYPE_PASSWORD, staticPassword)),
preferredDeliveryMechanisms, controls);
}
/**
* Creates a new deliver one-time password extended request with the provided
* information.
*
* @param authenticationID The authentication ID for the user to
* whom the one-time password should be
* delivered. It must not be
* {@code null}.
* @param staticPassword The static password for the user to
* whom the one-time password should be
* delivered. It may be {@code null} if
* this request is intended to be used
* to step-up an existing authentication
* rather than perform a new
* authentication (in which case the
* provided authentication ID must match
* the operation's authorization ID).
* @param preferredDeliveryMechanisms The names of the preferred delivery
* mechanisms for the one-time password.
* It may be {@code null} or empty if the
* server should select an appropriate
* delivery mechanism. If it is
* non-{@code null} and non-empty, then
* only the listed mechanisms will be
* considered for use, even if the server
* supports alternate mechanisms not
* included in this list.
* @param controls The set of controls to include in the
* request. It may be {@code null} or
* empty if no controls should be
* included.
*/
public DeliverOneTimePasswordExtendedRequest(
@NotNull final String authenticationID,
@Nullable final byte[] staticPassword,
@Nullable final List preferredDeliveryMechanisms,
@Nullable final Control... controls)
{
this(authenticationID,
(staticPassword == null
? null
: new ASN1OctetString(TYPE_PASSWORD, staticPassword)),
preferredDeliveryMechanisms, controls);
}
/**
* Creates a new deliver one-time password extended request with the provided
* information.
*
* @param authenticationID The authentication ID for the user to
* whom the one-time password should be
* delivered. It must not be
* {@code null}.
* @param staticPassword The static password for the user to
* whom the one-time password should be
* delivered. It may be {@code null} if
* this request is intended to be used
* to step-up an existing authentication
* rather than perform a new
* authentication (in which case the
* provided authentication ID must match
* the operation's authorization ID).
* @param preferredDeliveryMechanisms The names of the preferred delivery
* mechanisms for the one-time password.
* It may be {@code null} or empty if the
* server should select an appropriate
* delivery mechanism. If it is
* non-{@code null} and non-empty, then
* only the listed mechanisms will be
* considered for use, even if the server
* supports alternate mechanisms not
* included in this list.
* @param controls The set of controls to include in the
* request. It may be {@code null} or
* empty if no controls should be
* included.
*/
private DeliverOneTimePasswordExtendedRequest(
@NotNull final String authenticationID,
@Nullable final ASN1OctetString staticPassword,
@Nullable final List preferredDeliveryMechanisms,
@Nullable final Control... controls)
{
super(DELIVER_OTP_REQUEST_OID,
encodeValue(authenticationID, staticPassword,
preferredDeliveryMechanisms),
controls);
this.authenticationID = authenticationID;
this.staticPassword = staticPassword;
if ((preferredDeliveryMechanisms == null) ||
preferredDeliveryMechanisms.isEmpty())
{
this.preferredDeliveryMechanisms = Collections.emptyList();
}
else
{
final ArrayList> l =
new ArrayList<>(preferredDeliveryMechanisms.size());
for (final String s : preferredDeliveryMechanisms)
{
l.add(new ObjectPair(s, null));
}
this.preferredDeliveryMechanisms = Collections.unmodifiableList(l);
}
messageSubject = null;
fullTextBeforeOTP = null;
fullTextAfterOTP = null;
compactTextBeforeOTP = null;
compactTextAfterOTP = null;
}
/**
* Creates a new deliver one-time password extended request with the provided
* information.
*
* @param authenticationID The authentication ID for the user to
* whom the one-time password should be
* delivered. It must not be
* {@code null}.
* @param staticPassword The static password for the user to
* whom the one-time password should be
* delivered. It may be {@code null} if
* this request is intended to be used
* to step-up an existing authentication
* rather than perform a new
* authentication (in which case the
* provided authentication ID must match
* the operation's authorization ID).
* @param messageSubject The text (if any) that should be used
* as the message subject if the delivery
* mechanism accepts a subject. This may
* be {@code null} if no subject is
* required or a subject should be
* automatically generated.
* @param fullTextBeforeOTP The text (if any) that should appear
* before the generated one-time password
* in the message delivered to the user
* via a delivery mechanism that does not
* impose significant constraints on
* message size. This may be
* {@code null} if no text is required
* before the one-time password.
* @param fullTextAfterOTP The text (if any) that should appear
* after the one-time password in the
* message delivered to the user via a
* delivery mechanism that does not
* impose significant constraints on
* message size. This may be
* {@code null} if no text is required
* after the one-time password.
* @param compactTextBeforeOTP The text (if any) that should appear
* before the generated one-time password
* in the message delivered to the user
* via a delivery mechanism that imposes
* significant constraints on message
* size. This may be {@code null} if no
* text is required before the one-time
* password.
* @param compactTextAfterOTP The text (if any) that should appear
* after the generated one-time password
* in the message delivered to the user
* via a delivery mechanism that imposes
* significant constraints on message
* size. This may be {@code null} if no
* text is required after the one-time
* password.
* @param preferredDeliveryMechanisms An optional ordered list of preferred
* delivery mechanisms that should be
* used to deliver the one-time password
* to the user. It may be {@code null}
* or empty to allow the server to select
* an appropriate delivery mechanism. If
* it is non-{@code null} and non-empty,
* then only the listed mechanisms will
* be considered for use, even if the
* server supports alternate mechanisms
* not included in this list. Each
* {@code ObjectPair} item must have
* a non-{@code null} value for the first
* element, which is the name of the
* target delivery mechanism. It may
* optionally have a non-{@code null}
* value for the second element, which is
* a recipient ID to use for that
* mechanism (e.g., the target mobile
* phone number for SMS delivery, an
* email address for email delivery,
* etc.). If no recipient ID is provided
* for a mechanism, then the server will
* attempt to select a value for the
* user.
* @param controls The set of controls to include in the
* request. It may be {@code null} or
* empty if no controls should be
* included.
*/
public DeliverOneTimePasswordExtendedRequest(
@NotNull final String authenticationID,
@Nullable final String staticPassword,
@Nullable final String messageSubject,
@Nullable final String fullTextBeforeOTP,
@Nullable final String fullTextAfterOTP,
@Nullable final String compactTextBeforeOTP,
@Nullable final String compactTextAfterOTP,
@Nullable final List>
preferredDeliveryMechanisms,
@Nullable final Control... controls)
{
this(authenticationID,
(staticPassword == null
? null
: new ASN1OctetString(TYPE_PASSWORD, staticPassword)),
messageSubject, fullTextBeforeOTP, fullTextAfterOTP,
compactTextBeforeOTP, compactTextAfterOTP, preferredDeliveryMechanisms,
controls);
}
/**
* Creates a new deliver one-time password extended request with the provided
* information.
*
* @param authenticationID The authentication ID for the user to
* whom the one-time password should be
* delivered. It must not be
* {@code null}.
* @param staticPassword The static password for the user to
* whom the one-time password should be
* delivered. It may be {@code null} if
* this request is intended to be used
* to step-up an existing authentication
* rather than perform a new
* authentication (in which case the
* provided authentication ID must match
* the operation's authorization ID).
* @param messageSubject The text (if any) that should be used
* as the message subject if the delivery
* mechanism accepts a subject. This may
* be {@code null} if no subject is
* required or a subject should be
* automatically generated.
* @param fullTextBeforeOTP The text (if any) that should appear
* before the generated one-time password
* in the message delivered to the user
* via a delivery mechanism that does not
* impose significant constraints on
* message size. This may be
* {@code null} if no text is required
* before the one-time password.
* @param fullTextAfterOTP The text (if any) that should appear
* after the one-time password in the
* message delivered to the user via a
* delivery mechanism that does not
* impose significant constraints on
* message size. This may be
* {@code null} if no text is required
* after the one-time password.
* @param compactTextBeforeOTP The text (if any) that should appear
* before the generated one-time password
* in the message delivered to the user
* via a delivery mechanism that imposes
* significant constraints on message
* size. This may be {@code null} if no
* text is required before the one-time
* password.
* @param compactTextAfterOTP The text (if any) that should appear
* after the generated one-time password
* in the message delivered to the user
* via a delivery mechanism that imposes
* significant constraints on message
* size. This may be {@code null} if no
* text is required after the one-time
* password.
* @param preferredDeliveryMechanisms An optional ordered list of preferred
* delivery mechanisms that should be
* used to deliver the one-time password
* to the user. It may be {@code null}
* or empty to allow the server to select
* an appropriate delivery mechanism. If
* it is non-{@code null} and non-empty,
* then only the listed mechanisms will
* be considered for use, even if the
* server supports alternate mechanisms
* not included in this list. Each
* {@code ObjectPair} item must have
* a non-{@code null} value for the first
* element, which is the name of the
* target delivery mechanism. It may
* optionally have a non-{@code null}
* value for the second element, which is
* a recipient ID to use for that
* mechanism (e.g., the target mobile
* phone number for SMS delivery, an
* email address for email delivery,
* etc.). If no recipient ID is provided
* for a mechanism, then the server will
* attempt to select a value for the
* user.
* @param controls The set of controls to include in the
* request. It may be {@code null} or
* empty if no controls should be
* included.
*/
public DeliverOneTimePasswordExtendedRequest(
@NotNull final String authenticationID,
@Nullable final byte[] staticPassword,
@Nullable final String messageSubject,
@Nullable final String fullTextBeforeOTP,
@Nullable final String fullTextAfterOTP,
@Nullable final String compactTextBeforeOTP,
@Nullable final String compactTextAfterOTP,
@Nullable final List>
preferredDeliveryMechanisms,
@Nullable final Control... controls)
{
this(authenticationID,
(staticPassword == null
? null
: new ASN1OctetString(TYPE_PASSWORD, staticPassword)),
messageSubject, fullTextBeforeOTP, fullTextAfterOTP,
compactTextBeforeOTP, compactTextAfterOTP, preferredDeliveryMechanisms,
controls);
}
/**
* Creates a new deliver one-time password extended request with the provided
* information.
*
* @param authenticationID The authentication ID for the user to
* whom the one-time password should be
* delivered. It must not be
* {@code null}.
* @param staticPassword The static password for the user to
* whom the one-time password should be
* delivered. It may be {@code null} if
* this request is intended to be used
* to step-up an existing authentication
* rather than perform a new
* authentication (in which case the
* provided authentication ID must match
* the operation's authorization ID).
* @param messageSubject The text (if any) that should be used
* as the message subject if the delivery
* mechanism accepts a subject. This may
* be {@code null} if no subject is
* required or a subject should be
* automatically generated.
* @param fullTextBeforeOTP The text (if any) that should appear
* before the generated one-time password
* in the message delivered to the user
* via a delivery mechanism that does not
* impose significant constraints on
* message size. This may be
* {@code null} if no text is required
* before the one-time password.
* @param fullTextAfterOTP The text (if any) that should appear
* after the one-time password in the
* message delivered to the user via a
* delivery mechanism that does not
* impose significant constraints on
* message size. This may be
* {@code null} if no text is required
* after the one-time password.
* @param compactTextBeforeOTP The text (if any) that should appear
* before the generated one-time password
* in the message delivered to the user
* via a delivery mechanism that imposes
* significant constraints on message
* size. This may be {@code null} if no
* text is required before the one-time
* password.
* @param compactTextAfterOTP The text (if any) that should appear
* after the generated one-time password
* in the message delivered to the user
* via a delivery mechanism that imposes
* significant constraints on message
* size. This may be {@code null} if no
* text is required after the one-time
* password.
* @param preferredDeliveryMechanisms An optional ordered list of preferred
* delivery mechanisms that should be
* used to deliver the one-time password
* to the user. It may be {@code null}
* or empty to allow the server to select
* an appropriate delivery mechanism. If
* it is non-{@code null} and non-empty,
* then only the listed mechanisms will
* be considered for use, even if the
* server supports alternate mechanisms
* not included in this list. Each
* {@code ObjectPair} item must have
* a non-{@code null} value for the first
* element, which is the name of the
* target delivery mechanism. It may
* optionally have a non-{@code null}
* value for the second element, which is
* a recipient ID to use for that
* mechanism (e.g., the target mobile
* phone number for SMS delivery, an
* email address for email delivery,
* etc.). If no recipient ID is provided
* for a mechanism, then the server will
* attempt to select a value for the
* user.
* @param controls The set of controls to include in the
* request. It may be {@code null} or
* empty if no controls should be
* included.
*/
private DeliverOneTimePasswordExtendedRequest(
@NotNull final String authenticationID,
@Nullable final ASN1OctetString staticPassword,
@Nullable final String messageSubject,
@Nullable final String fullTextBeforeOTP,
@Nullable final String fullTextAfterOTP,
@Nullable final String compactTextBeforeOTP,
@Nullable final String compactTextAfterOTP,
@Nullable final List>
preferredDeliveryMechanisms,
@Nullable final Control... controls)
{
super(DELIVER_OTP_REQUEST_OID,
encodeValue(authenticationID, staticPassword, messageSubject,
fullTextBeforeOTP, fullTextAfterOTP, compactTextBeforeOTP,
compactTextAfterOTP, preferredDeliveryMechanisms),
controls);
this.authenticationID = authenticationID;
this.staticPassword = staticPassword;
this.messageSubject = messageSubject;
this.fullTextBeforeOTP = fullTextBeforeOTP;
this.fullTextAfterOTP = fullTextAfterOTP;
this.compactTextBeforeOTP = compactTextBeforeOTP;
this.compactTextAfterOTP = compactTextAfterOTP;
if ((preferredDeliveryMechanisms == null) ||
preferredDeliveryMechanisms.isEmpty())
{
this.preferredDeliveryMechanisms = Collections.emptyList();
}
else
{
this.preferredDeliveryMechanisms =
Collections.unmodifiableList(preferredDeliveryMechanisms);
}
}
/**
* Creates a new deliver one-time password extended request from the
* information contained in the provided generic extended request.
*
* @param request The generic extended request to be decoded as a deliver
* one-time password extended request.
*
* @throws LDAPException If a problem is encountered while attempting to
* decode the provided generic extended request as a
* deliver one-time password extended request.
*/
public DeliverOneTimePasswordExtendedRequest(
@NotNull final ExtendedRequest request)
throws LDAPException
{
super(request);
// The request must have a value.
final ASN1OctetString value = request.getValue();
if (value == null)
{
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_DELIVER_OTP_REQ_NO_VALUE.get());
}
// Parse the value.
ASN1OctetString password = null;
String authnID = null;
String subject = null;
String fullBefore = null;
String fullAfter = null;
String compactBefore = null;
String compactAfter = null;
final ArrayList> pdmList = new ArrayList<>(10);
try
{
for (final ASN1Element e :
ASN1Sequence.decodeAsSequence(value.getValue()).elements())
{
switch (e.getType())
{
case TYPE_AUTHN_ID:
authnID = ASN1OctetString.decodeAsOctetString(e).stringValue();
break;
case TYPE_PASSWORD:
password = ASN1OctetString.decodeAsOctetString(e);
break;
case TYPE_PREFERRED_DELIVERY_MECHANISM_NAMES:
final ASN1Element[] mechNameElements =
ASN1Sequence.decodeAsSequence(e).elements();
for (final ASN1Element mechElement : mechNameElements)
{
pdmList.add(new ObjectPair(
ASN1OctetString.decodeAsOctetString(mechElement).
stringValue(),
null));
}
break;
case TYPE_PREFERRED_DELIVERY_MECHANISM_NAMES_AND_IDS:
final ASN1Element[] pdmElements =
ASN1Sequence.decodeAsSequence(e).elements();
for (final ASN1Element pdmElement : pdmElements)
{
final ASN1Element[] mechElements =
ASN1Sequence.decodeAsSequence(pdmElement).elements();
final String mech = ASN1OctetString.decodeAsOctetString(
mechElements[0]).stringValue();
final String recipientID;
if (mechElements.length > 1)
{
recipientID = ASN1OctetString.decodeAsOctetString(
mechElements[1]).stringValue();
}
else
{
recipientID = null;
}
pdmList.add(new ObjectPair<>(mech, recipientID));
}
break;
case MESSAGE_SUBJECT_BER_TYPE:
subject =
ASN1OctetString.decodeAsOctetString(e).stringValue();
break;
case FULL_TEXT_BEFORE_OTP_BER_TYPE:
fullBefore =
ASN1OctetString.decodeAsOctetString(e).stringValue();
break;
case FULL_TEXT_AFTER_OTP_BER_TYPE:
fullAfter =
ASN1OctetString.decodeAsOctetString(e).stringValue();
break;
case COMPACT_TEXT_BEFORE_OTP_BER_TYPE:
compactBefore =
ASN1OctetString.decodeAsOctetString(e).stringValue();
break;
case COMPACT_TEXT_AFTER_OTP_BER_TYPE:
compactAfter =
ASN1OctetString.decodeAsOctetString(e).stringValue();
break;
default:
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_DELIVER_OTP_REQ_UNEXPECTED_ELEMENT_TYPE.get(
StaticUtils.toHex(e.getType())));
}
}
}
catch (final LDAPException le)
{
Debug.debugException(le);
throw le;
}
catch (final Exception e)
{
Debug.debugException(e);
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_DELIVER_OTP_REQ_ERROR_PARSING_VALUE.get(
StaticUtils.getExceptionMessage(e)),
e);
}
if (authnID == null)
{
throw new LDAPException(ResultCode.DECODING_ERROR,
ERR_DELIVER_OTP_REQ_NO_AUTHN_ID.get());
}
else
{
authenticationID = authnID;
}
staticPassword = password;
messageSubject = subject;
fullTextBeforeOTP = fullBefore;
fullTextAfterOTP = fullAfter;
compactTextBeforeOTP = compactBefore;
compactTextAfterOTP = compactAfter;
if ((pdmList == null) || pdmList.isEmpty())
{
preferredDeliveryMechanisms = Collections.emptyList();
}
else
{
preferredDeliveryMechanisms = Collections.unmodifiableList(pdmList);
}
}
/**
* Encodes the provided information into an ASN.1 octet string suitable for
* use as the value of this extended request.
*
* @param authenticationID The authentication ID for the user to
* whom the one-time password should be
* delivered. It must not be
* {@code null}.
* @param staticPassword The static password for the user to
* whom the one-time password should be
* delivered.
* @param preferredDeliveryMechanisms The names of the preferred delivery
* mechanisms for the one-time password.
* It may be {@code null} or empty if the
* server should select an appropriate
* delivery mechanism. If it is
* non-{@code null} and non-empty, then
* only the listed mechanisms will be
* considered for use, even if the server
* supports alternate mechanisms not
* included in this list.
*
* @return An ASN.1 octet string suitable for use as the value of this
* extended request.
*/
@NotNull()
private static ASN1OctetString encodeValue(
@NotNull final String authenticationID,
@Nullable final ASN1OctetString staticPassword,
@Nullable final List preferredDeliveryMechanisms)
{
final ArrayList elements = new ArrayList<>(3);
elements.add(new ASN1OctetString(TYPE_AUTHN_ID, authenticationID));
if (staticPassword != null)
{
elements.add(staticPassword);
}
if ((preferredDeliveryMechanisms != null) &&
(! preferredDeliveryMechanisms.isEmpty()))
{
final ArrayList dmElements =
new ArrayList<>(preferredDeliveryMechanisms.size());
for (final String s : preferredDeliveryMechanisms)
{
dmElements.add(new ASN1OctetString(s));
}
elements.add(new ASN1Sequence(TYPE_PREFERRED_DELIVERY_MECHANISM_NAMES,
dmElements));
}
return new ASN1OctetString(new ASN1Sequence(elements).encode());
}
/**
* Encodes the provided information into an ASN.1 octet string suitable for
* use as the value of this extended request.
*
* @param authenticationID The authentication ID for the user to
* whom the one-time password should be
* delivered. It must not be
* {@code null}.
* @param staticPassword The static password for the user to
* whom the one-time password should be
* delivered. It may be {@code null} if
* this request is intended to be used
* to step-up an existing authentication
* rather than perform a new
* authentication (in which case the
* provided authentication ID must match
* the operation's authorization ID).
* @param messageSubject The text (if any) that should be used
* as the message subject if the delivery
* mechanism accepts a subject. This may
* be {@code null} if no subject is
* required or a subject should be
* automatically generated.
* @param fullTextBeforeOTP The text (if any) that should appear
* before the generated one-time password
* in the message delivered to the user
* via a delivery mechanism that does not
* impose significant constraints on
* message size. This may be
* {@code null} if no text is required
* before the one-time password.
* @param fullTextAfterOTP The text (if any) that should appear
* after the one-time password in the
* message delivered to the user via a
* delivery mechanism that does not
* impose significant constraints on
* message size. This may be
* {@code null} if no text is required
* after the one-time password.
* @param compactTextBeforeOTP The text (if any) that should appear
* before the generated one-time password
* in the message delivered to the user
* via a delivery mechanism that imposes
* significant constraints on message
* size. This may be {@code null} if no
* text is required before the one-time
* password.
* @param compactTextAfterOTP The text (if any) that should appear
* after the generated one-time password
* in the message delivered to the user
* via a delivery mechanism that imposes
* significant constraints on message
* size. This may be {@code null} if no
* text is required after the one-time
* password.
* @param preferredDeliveryMechanisms An optional ordered list of preferred
* delivery mechanisms that should be
* used to deliver the one-time password
* to the user. It may be {@code null}
* or empty to allow the server to select
* an appropriate delivery mechanism. If
* it is non-{@code null} and non-empty,
* then only the listed mechanisms will
* be considered for use, even if the
* server supports alternate mechanisms
* not included in this list. Each
* {@code ObjectPair} item must have
* a non-{@code null} value for the first
* element, which is the name of the
* target delivery mechanism. It may
* optionally have a non-{@code null}
* value for the second element, which is
* a recipient ID to use for that
* mechanism (e.g., the target mobile
* phone number for SMS delivery, an
* email address for email delivery,
* etc.). If no recipient ID is provided
* for a mechanism, then the server will
* attempt to select a value for the
* user.
*
* @return An ASN.1 octet string suitable for use as the value of this
* extended request.
*/
@NotNull()
private static ASN1OctetString encodeValue(
@NotNull final String authenticationID,
@Nullable final ASN1OctetString staticPassword,
@Nullable final String messageSubject,
@Nullable final String fullTextBeforeOTP,
@Nullable final String fullTextAfterOTP,
@Nullable final String compactTextBeforeOTP,
@Nullable final String compactTextAfterOTP,
@Nullable final List>
preferredDeliveryMechanisms)
{
final ArrayList elements = new ArrayList<>(8);
elements.add(new ASN1OctetString(TYPE_AUTHN_ID, authenticationID));
if (staticPassword != null)
{
elements.add(staticPassword);
}
if (messageSubject != null)
{
elements.add(new ASN1OctetString(MESSAGE_SUBJECT_BER_TYPE,
messageSubject));
}
if (fullTextBeforeOTP != null)
{
elements.add(new ASN1OctetString(FULL_TEXT_BEFORE_OTP_BER_TYPE,
fullTextBeforeOTP));
}
if (fullTextAfterOTP != null)
{
elements.add(new ASN1OctetString(FULL_TEXT_AFTER_OTP_BER_TYPE,
fullTextAfterOTP));
}
if (compactTextBeforeOTP != null)
{
elements.add(new ASN1OctetString(COMPACT_TEXT_BEFORE_OTP_BER_TYPE,
compactTextBeforeOTP));
}
if (compactTextAfterOTP != null)
{
elements.add(new ASN1OctetString(COMPACT_TEXT_AFTER_OTP_BER_TYPE,
compactTextAfterOTP));
}
if ((preferredDeliveryMechanisms != null) &&
(! preferredDeliveryMechanisms.isEmpty()))
{
final ArrayList pdmElements =
new ArrayList<>(preferredDeliveryMechanisms.size());
for (final ObjectPair p : preferredDeliveryMechanisms)
{
if (p.getSecond() == null)
{
pdmElements.add(new ASN1Sequence(
new ASN1OctetString(p.getFirst())));
}
else
{
pdmElements.add(new ASN1Sequence(
new ASN1OctetString(p.getFirst()),
new ASN1OctetString(p.getSecond())));
}
}
elements.add(new ASN1Sequence(
TYPE_PREFERRED_DELIVERY_MECHANISM_NAMES_AND_IDS, pdmElements));
}
return new ASN1OctetString(new ASN1Sequence(elements).encode());
}
/**
* Retrieves the authentication ID for the user to whom the one-time password
* should be delivered.
*
* @return The authentication ID for the user to whom the one-time password
* should be delivered.
*/
@NotNull()
public String getAuthenticationID()
{
return authenticationID;
}
/**
* Retrieves the static password for the user to whom the one-time password
* should be delivered. The returned password may be {@code null} if no
*
*
* @return The static password for the user to whom the one-time password
* should be delivered, or {@code null} if no static password should
* be included in the request.
*/
@Nullable()
public ASN1OctetString getStaticPassword()
{
return staticPassword;
}
/**
* Retrieves an ordered list of the names of the preferred delivery mechanisms
* for the one-time password, if provided.
*
* @return An ordered list of the names of the preferred delivery mechanisms
* for the one-time password, or {@code null} if this was not
* provided.
*/
@Nullable()
public List getPreferredDeliveryMechanisms()
{
if (preferredDeliveryMechanisms.isEmpty())
{
return null;
}
else
{
final LinkedHashSet s = new LinkedHashSet<>(
StaticUtils.computeMapCapacity(preferredDeliveryMechanisms.size()));
for (final ObjectPair p : preferredDeliveryMechanisms)
{
s.add(p.getFirst());
}
return Collections.unmodifiableList(new ArrayList<>(s));
}
}
/**
* Retrieves an ordered list of the preferred delivery mechanisms that should
* be used to provide the one-time password to the user, optionally paired
* with a mechanism-specific recipient ID (e.g., a mobile phone number for SMS
* delivery, or an email address for email delivery) that can be used in the
* delivery. If this list is non-empty, then the server will use the first
* mechanism in the list that the server supports and is available for the
* target user, and the server will only consider mechanisms in the provided
* list even if the server supports alternate mechanisms that are not
* included. If this list is empty, then the server will attempt to select an
* appropriate delivery mechanism for the user.
*
* @return An ordered list of the preferred delivery mechanisms for the
* one-time password, or an empty list if none were provided.
*/
@NotNull()
public List>
getPreferredDeliveryMechanismNamesAndIDs()
{
return preferredDeliveryMechanisms;
}
/**
* Retrieves the text (if any) that should be used as the message subject for
* delivery mechanisms that can make use of a subject.
*
* @return The text that should be used as the message subject for delivery
* mechanisms that can make use of a subject, or {@code null} if no
* subject should be used, or if the delivery mechanism should
* attempt to automatically determine a subject.
*/
@Nullable()
public String getMessageSubject()
{
return messageSubject;
}
/**
* Retrieves the text (if any) that should appear before the one-time password
* in the message delivered to the user via a mechanism that does not impose
* significant constraints on message size.
*
* @return The text that should appear before the one-time password in the
* message delivered to the user via a mechanism that does not impose
* significant constraints on message size, or {@code null} if there
* should not be any text before the one-time password.
*/
@Nullable()
public String getFullTextBeforeOTP()
{
return fullTextBeforeOTP;
}
/**
* Retrieves the text (if any) that should appear after the one-time password
* in the message delivered to the user via a mechanism that does not impose
* significant constraints on message size.
*
* @return The text that should appear after the one-time password in the
* message delivered to the user via a mechanism that does not impose
* significant constraints on message size, or {@code null} if there
* should not be any text after the one-time password.
*/
@Nullable()
public String getFullTextAfterOTP()
{
return fullTextAfterOTP;
}
/**
* Retrieves the text (if any) that should appear before the one-time password
* in the message delivered to the user via a mechanism that imposes
* significant constraints on message size.
*
* @return The text that should appear before the one-time password in the
* message delivered to the user via a mechanism that imposes
* significant constraints on message size, or {@code null} if there
* should not be any text before the one-time password.
*/
@Nullable()
public String getCompactTextBeforeOTP()
{
return compactTextBeforeOTP;
}
/**
* Retrieves the text (if any) that should appear after the one-time password
* in the message delivered to the user via a mechanism that imposes
* significant constraints on message size.
*
* @return The text that should appear after the one-time password in the
* message delivered to the user via a mechanism that imposes
* significant constraints on message size, or {@code null} if there
* should not be any text after the one-time password.
*/
@Nullable()
public String getCompactTextAfterOTP()
{
return compactTextAfterOTP;
}
/**
* {@inheritDoc}
*/
@Override()
@NotNull()
public DeliverOneTimePasswordExtendedResult process(
@NotNull final LDAPConnection connection, final int depth)
throws LDAPException
{
final ExtendedResult extendedResponse = super.process(connection, depth);
return new DeliverOneTimePasswordExtendedResult(extendedResponse);
}
/**
* {@inheritDoc}.
*/
@Override()
@NotNull()
public DeliverOneTimePasswordExtendedRequest duplicate()
{
return duplicate(getControls());
}
/**
* {@inheritDoc}.
*/
@Override()
@NotNull()
public DeliverOneTimePasswordExtendedRequest duplicate(
@Nullable final Control[] controls)
{
final DeliverOneTimePasswordExtendedRequest r =
new DeliverOneTimePasswordExtendedRequest(authenticationID,
staticPassword, messageSubject, fullTextBeforeOTP,
fullTextAfterOTP, compactTextBeforeOTP, compactTextAfterOTP,
preferredDeliveryMechanisms, controls);
r.setResponseTimeoutMillis(getResponseTimeoutMillis(null));
r.setIntermediateResponseListener(getIntermediateResponseListener());
r.setReferralDepth(getReferralDepth());
r.setReferralConnector(getReferralConnectorInternal());
return r;
}
/**
* {@inheritDoc}
*/
@Override()
@NotNull()
public String getExtendedRequestName()
{
return INFO_DELIVER_OTP_REQ_NAME.get();
}
/**
* {@inheritDoc}
*/
@Override()
public void toString(@NotNull final StringBuilder buffer)
{
buffer.append("DeliverOneTimePasswordExtendedRequest(authenticationID=");
buffer.append(authenticationID);
if (messageSubject != null)
{
buffer.append(", messageSubject='");
buffer.append(messageSubject);
buffer.append('\'');
}
if (fullTextBeforeOTP != null)
{
buffer.append(", fullTextBeforeOTP='");
buffer.append(fullTextBeforeOTP);
buffer.append('\'');
}
if (fullTextAfterOTP != null)
{
buffer.append(", fullTextAfterOTP='");
buffer.append(fullTextAfterOTP);
buffer.append('\'');
}
if (compactTextBeforeOTP != null)
{
buffer.append(", compactTextBeforeOTP='");
buffer.append(compactTextBeforeOTP);
buffer.append('\'');
}
if (compactTextAfterOTP != null)
{
buffer.append(", compactTextAfterOTP='");
buffer.append(compactTextAfterOTP);
buffer.append('\'');
}
if (preferredDeliveryMechanisms != null)
{
buffer.append(", preferredDeliveryMechanisms={");
final Iterator> iterator =
preferredDeliveryMechanisms.iterator();
while (iterator.hasNext())
{
final ObjectPair p = iterator.next();
buffer.append('\'');
buffer.append(p.getFirst());
if (p.getSecond() != null)
{
buffer.append('(');
buffer.append(p.getSecond());
buffer.append(')');
}
buffer.append('\'');
if (iterator.hasNext())
{
buffer.append(',');
}
}
}
final Control[] controls = getControls();
if (controls.length > 0)
{
buffer.append(", controls={");
for (int i=0; i < controls.length; i++)
{
if (i > 0)
{
buffer.append(", ");
}
buffer.append(controls[i]);
}
buffer.append('}');
}
buffer.append(')');
}
}