Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/strophe/strophejs/llms.txt

Use this file to discover all available pages before exploring further.

When conn.connect() is called, Strophe.js performs SASL (Simple Authentication and Security Layer) negotiation automatically. The server advertises its supported mechanisms in the <stream:features> element; Strophe.js compares that list against the mechanisms it has registered and selects the one with the highest priority that passes its test() check. Your application code does not need to drive this negotiation — but you can control which mechanisms are available and add custom ones when needed.

Default Mechanisms and Priorities

Strophe.js registers the following mechanisms by default, in descending priority order. When multiple mechanisms are mutually supported, the one with the highest priority wins:
The strongest SCRAM variant available by default. Uses SHA-512 as the hash function. Client and server mutually authenticate: the server proves it knows the password-derived key without ever seeing the password in plaintext.Exported as Strophe.SASLSHA512. Requires the server to advertise SCRAM-SHA-512.
SCRAM using SHA-384. Selected when the server supports it but not SHA-512.Exported as Strophe.SASLSHA384.
SCRAM using SHA-256. Widely supported and a good practical minimum for new deployments.Exported as Strophe.SASLSHA256.
The original SCRAM mechanism from RFC 5802. Still supported by most servers. Prefer a SHA-256 or stronger variant when available.Exported as Strophe.SASLSHA1.
Sends credentials as a plaintext base64-encoded string. Should only be used over a TLS-protected transport (wss:// or https://). Requires connection.authcid to be non-null (i.e. a JID with a node part must be supplied).Exported as Strophe.SASLPlain.
RFC 7628 OAuth 2.0 Bearer token authentication. Pass the access token as the password argument to conn.connect(). Strophe.js packages it in the correct n,,\u0001auth=Bearer <token> format.Exported as Strophe.SASLOAuthBearer.
A non-standard OAuth2 variant used by some servers (notably older Google Talk / Jabber infrastructure). Prefer OAUTHBEARER for standards-compliant deployments.Exported as Strophe.SASLXOAuth2.
RFC 4616 anonymous authentication. No JID node is required: pass only a domain as the JID (e.g. example.com). The server assigns a temporary JID for the session. connection.authcid must be null, which happens when no node part is in the supplied JID.Exported as Strophe.SASLAnonymous.
Used with client-certificate TLS authentication. The client’s identity is asserted by the TLS layer; SASL EXTERNAL simply tells the server to accept that identity. If authcid equals authzid, Strophe.js sends an empty response (indicating “use the identity from the certificate”). Otherwise it sends authzid to request authorization as a different JID.Exported as Strophe.SASLExternal.

Authentication Status Flow

The connection callback will receive these status values during a normal authentication sequence:
1

CONNECTING (1)

Transport connection is being established.
2

AUTHENTICATING (3)

SASL negotiation is underway. Strophe.js has selected a mechanism and is exchanging challenge/response messages with the server.
3

CONNECTED (5) or AUTHFAIL (4)

On success, resource binding completes and CONNECTED is fired. On failure — wrong password, unsupported mechanism, or server rejection — AUTHFAIL is fired and the connection is closed.
import { Strophe } from 'strophejs';

function onConnect(status: number, condition: string | null) {
  if (status === Strophe.Status.AUTHENTICATING) {
    console.log('Negotiating SASL…');
  } else if (status === Strophe.Status.AUTHFAIL) {
    console.error('Authentication failed:', condition);
  } else if (status === Strophe.Status.CONNECTED) {
    console.log('Authenticated and connected as', conn.jid);
  }
}

Restricting Available Mechanisms

Pass a mechanisms array to the ConnectionOptions to limit which SASL mechanisms Strophe.js will offer during negotiation. Only the constructors you list will be registered — all others are ignored:
import { Strophe } from 'strophejs';

// Allow only SCRAM-SHA-256 and SCRAM-SHA-512
const conn = new Strophe.Connection('wss://xmpp.example.com/xmpp-websocket', {
  mechanisms: [Strophe.SASLSHA512, Strophe.SASLSHA256],
});

conn.connect('alice@example.com', 's3cr3t', onConnect);
If the server does not advertise any of the allowed mechanisms, conn.connect() will fail with AUTHFAIL and the error condition 'no-auth-mech'.

Disabling a Specific Mechanism

To prevent a mechanism from being used without replacing the entire list, override its test() method to return false. Strophe.js calls test() before selecting a mechanism, so returning false effectively disables it:
import { Strophe } from 'strophejs';

// Disable PLAIN authentication globally
Strophe.SASLPlain.prototype.test = () => false;
Overriding prototype.test affects all future Connection instances created in the same JavaScript environment. If you need per-connection control, pass a custom mechanisms array in ConnectionOptions instead.

ANONYMOUS Authentication

For guest sessions that do not require a user account, use SASL ANONYMOUS. Pass only the server domain (no node part) as the JID to connect(). Strophe.js detects that authcid is null and the SASLAnonymous.test() method returns true:
const conn = new Strophe.Connection('wss://xmpp.example.com/xmpp-websocket');

conn.connect(
  'example.com', // domain only — no node part
  '',            // password is not used
  (status) => {
    if (status === Strophe.Status.CONNECTED) {
      // conn.jid is now a server-assigned temporary JID
      console.log('Anonymous session JID:', conn.jid);
    }
  }
);

EXTERNAL (Certificate) Authentication

SASL EXTERNAL is used when the client’s identity is established by the TLS layer (e.g. a client certificate). Pass the JID and any optional authcid value to influence whether an authorization identity is sent:
const conn = new Strophe.Connection('wss://xmpp.example.com/xmpp-websocket', {
  mechanisms: [Strophe.SASLExternal],
});

// If authcid matches the JID's node, authzid is NOT sent (identity is in the cert)
conn.connect(
  'alice@example.com',
  '',                    // no password
  onConnect,
  undefined,
  undefined,
  undefined,
  'alice'                // authcid — set equal to jid node to suppress authzid
);

Explicit Resource Binding

By default, Strophe.js calls conn.bind() automatically as soon as the server advertises the urn:ietf:params:xml:ns:xmpp-bind stream feature after authentication. If you need to perform other stream-level setup first (for example, activating XEP-0198 Stream Management), set explicitResourceBinding: true in ConnectionOptions. The connection callback will then receive Strophe.Status.BINDREQUIRED (11) instead of proceeding to binding automatically:
const conn = new Strophe.Connection('wss://xmpp.example.com/xmpp-websocket', {
  explicitResourceBinding: true,
});

function onConnect(status: number) {
  if (status === Strophe.Status.BINDREQUIRED) {
    // Set up stream management or other features here, then bind:
    conn.bind();
  } else if (status === Strophe.Status.CONNECTED) {
    console.log('Bound JID:', conn.jid);
  }
}

conn.connect('alice@example.com/mobile', 's3cr3t', onConnect);

Writing a Custom SASL Mechanism

Subclass SASLMechanism to implement a proprietary or non-standard mechanism. Override test() to indicate when the mechanism can run and onChallenge() to produce the client’s response string:
import { Strophe } from 'strophejs';

class SASLMyCustomMechanism extends Strophe.SASLMechanism {
  constructor() {
    super(
      'X-MY-MECHANISM', // mechanism name as advertised by the server
      true,             // isClientFirst: client sends data first
      25                // priority: between ANONYMOUS (20) and X-OAUTH2 (30)
    );
  }

  test(connection: InstanceType<typeof Strophe.Connection>): boolean {
    // Only use this mechanism when a special token is present
    return connection.pass !== null;
  }

  onChallenge(
    connection: InstanceType<typeof Strophe.Connection>,
    challenge?: string
  ): string {
    // On the first call (isClientFirst), challenge is null.
    // Return the client's initial response string.
    return `token=${connection.pass}`;
  }
}

// Register the mechanism on a new connection
const conn = new Strophe.Connection('wss://xmpp.example.com/xmpp-websocket', {
  mechanisms: [
    SASLMyCustomMechanism,
    Strophe.SASLSHA512,
    Strophe.SASLSHA256,
  ],
});

conn.connect('alice@example.com', 'my-access-token', onConnect);

SASLMechanism Lifecycle Methods

constructor(name, isClientFirst, priority)
constructor
Sets the mechanism name (must match the server-advertised string), whether the client sends data first before receiving a challenge, and the priority used for selection.
test(connection)
(connection) => boolean
Called before selection. Return false to prevent this mechanism from being used on this connection.
onStart(connection)
(connection) => void
Called once when the mechanism is selected and negotiation begins. Stores the connection reference internally.
clientChallenge(connection)
(connection) => string | Promise<string | false>
Called when isClientFirst is true to get the client’s initial message. Defaults to delegating to onChallenge().
onChallenge(connection, challenge?)
(connection, challenge?) => string | Promise<string | false>
Called each time the server sends a challenge. Return the client’s response string. May be async (return a Promise). Throw or return false to signal failure.
onSuccess()
() => void
Called when the server signals authentication success. Clears the internal connection reference.
onFailure()
() => void
Called when the server signals authentication failure. Clears the internal connection reference.

SCRAM Key Caching

After a successful SCRAM authentication, Strophe.js stores the derived client and server keys in connection.scram_keys. On subsequent connections you can pass these pre-derived keys as the password object to skip the expensive key derivation step:
// After first successful login, persist scram_keys
const keys = conn.scram_keys;

// On reconnect, pass the cached keys instead of the raw password
conn.connect('alice@example.com', keys, onConnect);
The keys object has the shape { name: string, ck: string, sk: string, iter: number, salt: string } where name is the hash algorithm name, ck is the base64-encoded client key, sk is the base64-encoded server key, iter is the iteration count, and salt is the base64-encoded salt.

Build docs developers (and LLMs) love