Interface Sasl2Task


public interface Sasl2Task
One execution of a SASL2 task, as defined by the <continue/> flow of XEP-0388. An instance is created by a Sasl2TaskProvider when the peer selects the task by sending <next task='...'/>, and is discarded when the negotiation ends. Instances are therefore stateful and must not be shared between sessions.

Protocol

  1. begin(Element) is invoked with the <next/> element that selected this task. That element may carry a payload, allowing a task to complete in a single round trip.
  2. Whenever Sasl2TaskResult.taskData(Element...) is returned, a <task-data/> element is sent to the peer and the peer's reply is delivered to onTaskData(Element). This repeats for as long as the implementation wishes.
  3. When Sasl2TaskResult.completed() is returned, the task is done. The server then either offers another <continue/> (if any further task is eligible) or completes the SASL2 negotiation with <success/>.
  4. Throwing a SaslFailureException at any point aborts the entire SASL2 negotiation: the peer receives a <failure/> and the session remains unauthenticated. No FAST token is issued, no resource is bound, and no inline stream resumption takes place.

Threading

Methods are invoked on the thread that processes inbound data for the peer's connection, and never concurrently for the same instance. They must not block: a database round trip is acceptable, a call out to a third-party service is not. Asynchronous evaluation of a task step is not currently supported.

Security

A task runs after the SASL exchange has succeeded but before the session is authenticated. Openfire holds back the authentication token, resource binding, FAST token issuance and inline stream resumption until every task has completed, so a task can be used as a genuine additional authentication factor. It cannot, however, be used to protect against an attacker that already holds valid credentials and can abandon the connection: the password was verified before the task ran, so a failed task tells the attacker that the password was correct.
See Also:
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final org.slf4j.Logger
     
  • Method Summary

    Modifier and Type
    Method
    Description
    begin(org.dom4j.Element next)
    Performs the first step of the task, in response to the peer selecting it.
    The name of this task, as it was advertised in the <continue/> element and selected by the peer.
    default void
    Invoked when the negotiation ends before this task completed: the peer aborted, another part of the negotiation failed, or the connection was closed.
    onTaskData(org.dom4j.Element taskData)
    Processes a <task-data/> element received from the peer.
  • Field Details

    • Log

      static final org.slf4j.Logger Log
  • Method Details

    • getName

      @Nonnull String getName()
      The name of this task, as it was advertised in the <continue/> element and selected by the peer.
      Returns:
      a task name (never null or empty).
    • begin

      @Nonnull Sasl2TaskResult begin(@Nonnull org.dom4j.Element next) throws SaslFailureException
      Performs the first step of the task, in response to the peer selecting it.
      Parameters:
      next - the <next/> element that selected this task. Never null. Its task attribute holds this task's name; any child elements are a task-defined payload.
      Returns:
      the outcome of this step (never null).
      Throws:
      SaslFailureException - to abort the SASL2 negotiation.
    • onTaskData

      @Nonnull default Sasl2TaskResult onTaskData(@Nonnull org.dom4j.Element taskData) throws SaslFailureException
      Processes a <task-data/> element received from the peer. Only invoked after a previous step returned Sasl2TaskResult.taskData(Element...). The default implementation aborts the negotiation, which is the correct behaviour for a task that never asks the peer for data.
      Parameters:
      taskData - the <task-data/> element received from the peer (never null). Its children are a task-defined payload.
      Returns:
      the outcome of this step (never null).
      Throws:
      SaslFailureException - to abort the SASL2 negotiation.
    • onAborted

      default void onAborted()
      Invoked when the negotiation ends before this task completed: the peer aborted, another part of the negotiation failed, or the connection was closed. Implementations should release any resources that they hold (a pending challenge, a reserved one-time code) and must not attempt to write to the session. The default implementation does nothing. Note: this may be called even when the negotiation ended because this very task's begin(Element) or onTaskData(Element) threw a SaslFailureException. Implementations must tolerate being asked to release resources they may have already released or never acquired (cleanup should be idempotent).