Writing SASL handlers

Sometimes the simple get_password() or test_password() methods of authentication plugins are not enough and you need to implement a custom SASL handler.

The basic flow when a client authenticates is

  1. :mechanisms() is called in order to present the client with the supported mechanisms.
  2. :select(mech) is called when the client initiates the authentication attempt.
  3. :process(message) is called for each message the client sends.


The mechanisms method of the SASL object returns a set of supported mechanisms.

function sasl:mechanisms()
    return {
        ["PLAIN"] = true;
        -- other mechanisms


Called when the user starts authentication.

function sasl:select(mechanism)
    if self:mechanisms()[mechanism] then
        self.selected = mechanism;
        return true;
        return false;


SASL is a back-and-forth messaging protocol. Each message the client sends is passed to the process method, which is expected to return a status code and optional response.

function sasl:process(message)
    if message == "I am Bob" then
        self.username = "bob"
        return "success"
    elseif message == "I am Eve" then
        return "failure", "not-authorized", "I don't think so"
    elseif message == "Who am I?" then
        return "challenge", "Try to remember";
        return "failure", "error-code", "Something bad happened";

The first return value is one of "success", "challenge" or "failure". Simple mechanisms might just validate the message and return success or failure, but more complicated mechanisms may return challenges for the client to complete.

Additional data may be passed as a second return value for success or challenge messages, eg for multi-step mechanisms or for mutual authentication. On failure, a SASL error code should be passed as second return value and an optional textual message as third. Make sure to not distinguish between eg "wrong password" and "no such user" in order to prevent directory harvesting attacks.