Using the Mechanisms

Once the application has created a mechanism, it uses the mechanism to obtain SASL tokens to exchange with the peer. The client typically indicates to the server via the application protocol which mechanism to use. Some protocols allows the client to accompany the request with an optional initial response for mechanisms that have an initial response. This feature can be used to reduce the number of message exchanges that are required for authentication. Here is an example of how a client might use SaslClient for authentication.

    // Get optional initial response
        byte[] response = (sc.hasInitialResponse() ? sc.evaluateChallenge(new byte[]) : null);
        String mechanism = sc.getName();
    // Send selected mechanism name and optional initial response to server
        send(mechanism, response);
    // Read response
        msg = receive();
        while (!sc.isComplete() && (msg.status == CONTINUE || msg.status == SUCCESS)) {
            // Evaluate server challenge
            response = sc.evaluateChallenge(msg.contents);
         if (msg.status == SUCCESS) {
            // done; server doesn't expect any more SASL data
            if (response != null) {
                throw new IOException(“Protocol error: attempting to send response after completion”);
          }
            break;
        } else {
            send(mechanism, response);
            msg = receive();
         }
    }

The client application iterates through each step of the authentication by using the mechanism (sc) to evaluate the challenge gotten from the server and to get a response to send back to the server. It continues this cycle until either the mechanism or application-level protocol indicates that the authentication has completed, or if the mechanism cannot evaluate a challenge. If the mechanism cannot evaluate the challenge, it throws an exception to indicate the error and terminates the authentication. Disagreement between the mechanism and protocol about the completion state must be treated as an error because it might indicate a compromise of the authentication exchange.

Here is an example of how a server might use SaslServer.

    // Read request that contains mechanism name and optional initial response
    msg.receive();
    // Obtain a SaslServer to perform authentication
    SaslServer ss = Sasl.createSaslServer(msg.mechanism, protocol, myName, props, callbackHandler);
    // Perform authentication steps until done
    while (!ss.isComplete()) {

        try {
        // Process response
            byte[] challenge = sc.evaluateResponse(msg.contents);
            if (ss.isComplete()) {
                send(mechanism, challenge, SUCCESS);
            } else {
                send(mechanism, challenge, CONTINUE);
                msg.receive();
           }
        } catch (SaslException e) {
            send(ERROR);
            sc.dispose();
            break;
       }
    }

The server application iterates through each step of the authentication by giving the clients response to the mechanism (ss) to process. If the response is incorrect, the mechanism indicates the error by throwing a SaslException so that the server can report the error and terminate the authentication. If the response is correct, the mechanism returns challenge data to be sent to the client and indicates whether the authentication is complete. Note that challenge data can accompany a success indication. This might be used, for example, to tell the client to finalize some negotiated state.