Documentation Index
Fetch the complete documentation index at: https://mintlify.com/matrix-org/matrix-js-sdk/llms.txt
Use this file to discover all available pages before exploring further.
The matrix-js-sdk supports several authentication methods: password-based login, SSO and OIDC, direct access token usage, and token-based login. This guide walks through each method and common patterns for session management.
Server discovery
Before logging in, use AutoDiscovery.findClientConfig() to resolve a homeserver URL from a user-supplied domain. This performs a .well-known/matrix/client lookup and validates the result.
import { AutoDiscovery } from "matrix-js-sdk";
const config = await AutoDiscovery.findClientConfig("matrix.org");
const hsConfig = config["m.homeserver"];
if (hsConfig.state === AutoDiscovery.SUCCESS) {
console.log("Homeserver URL:", hsConfig.base_url);
} else if (hsConfig.state === AutoDiscovery.FAIL_ERROR) {
// Terminal failure — do not proceed
console.error("Discovery failed:", hsConfig.error);
} else {
// FAIL_PROMPT or PROMPT — warn the user but may still proceed
console.warn("Discovery incomplete:", hsConfig.error);
}
The state field is one of AutoDiscovery.SUCCESS, AutoDiscovery.FAIL_PROMPT, AutoDiscovery.FAIL_ERROR, or AutoDiscovery.PROMPT.
Checking available login flows
Before prompting the user, check which login flows the homeserver advertises:
import { createClient } from "matrix-js-sdk";
const tempClient = createClient({ baseUrl: "https://matrix.org" });
const { flows } = await tempClient.loginFlows();
// flows is an array of LoginFlow objects, each with a `type` string:
// "m.login.password", "m.login.sso", "m.login.token", etc.
for (const flow of flows) {
console.log("Supported flow:", flow.type);
}
Password login
The recommended approach is to call loginRequest() on a temporary unauthenticated client, then construct a new fully-configured MatrixClient using the returned credentials.
import { createClient } from "matrix-js-sdk";
const tempClient = createClient({ baseUrl: "https://matrix.org" });
const response = await tempClient.loginRequest({
type: "m.login.password",
identifier: {
type: "m.id.user",
user: "@alice:matrix.org",
},
password: "correct horse battery staple",
initial_device_display_name: "My App",
// Opt in to refresh tokens:
refresh_token: true,
});
// Construct a new client with the returned credentials
const client = createClient({
baseUrl: "https://matrix.org",
accessToken: response.access_token,
userId: response.user_id,
deviceId: response.device_id,
refreshToken: response.refresh_token,
});
loginWithPassword() and login() are deprecated because they mutate the existing client instance with only some of the returned credentials, which can produce inconsistent state. Use loginRequest() instead and create a new MatrixClient from the full response.
Login with a phone number
const response = await tempClient.loginRequest({
type: "m.login.password",
identifier: {
type: "m.id.phone",
country: "GB",
phone: "07700900000",
},
password: "correct horse battery staple",
});
Login with an email address
const response = await tempClient.loginRequest({
type: "m.login.password",
identifier: {
type: "m.id.thirdparty",
medium: "email",
address: "alice@example.com",
},
password: "correct horse battery staple",
});
Using an existing access token
If you have previously stored credentials (for example in local storage after a prior login), pass them directly to createClient():
import { createClient } from "matrix-js-sdk";
const client = createClient({
baseUrl: "https://matrix.org",
accessToken: storedAccessToken,
userId: storedUserId,
deviceId: storedDeviceId,
// If you also stored a refresh token:
refreshToken: storedRefreshToken,
tokenRefreshFunction: async (refreshToken) => {
const response = await client.refreshToken(refreshToken);
return {
accessToken: response.access_token,
refreshToken: response.refresh_token,
expiry: new Date(Date.now() + response.expires_in_ms),
};
},
});
The tokenRefreshFunction is invoked automatically by the HTTP layer whenever it detects an expired token and a refreshToken is present.
Token-based login
Some flows (such as SSO) issue a short-lived m.login.token. Exchange it with loginRequest():
const response = await tempClient.loginRequest({
type: "m.login.token",
token: ssoLoginToken,
});
SSO login
For traditional homeserver-proxied SSO (not native OIDC), build the redirect URL using getSsoLoginUrl() and direct the user’s browser to it:
const ssoUrl = tempClient.getSsoLoginUrl(
"https://my-app.example.com/callback", // redirectUrl
"sso", // loginType ("sso" or "cas")
"google", // optional IdP id
SSOAction.LOGIN, // optional: LOGIN or REGISTER
);
// Redirect the user to ssoUrl.
// After authentication, the homeserver redirects back to your callback
// with a `loginToken` query parameter. Exchange it:
const callbackToken = new URLSearchParams(window.location.search).get("loginToken");
const response = await tempClient.loginRequest({
type: "m.login.token",
token: callbackToken!,
});
For native OIDC flows, see OIDC authentication.
Token refresh
Homeservers may issue short-lived access tokens alongside a refresh_token. Pass a tokenRefreshFunction when constructing the client and the SDK will call it automatically:
import { createClient, type TokenRefreshFunction } from "matrix-js-sdk";
const tokenRefreshFunction: TokenRefreshFunction = async (refreshToken) => {
const res = await client.refreshToken(refreshToken);
// Persist the new tokens in your storage layer here
return {
accessToken: res.access_token,
refreshToken: res.refresh_token,
expiry: new Date(Date.now() + res.expires_in_ms),
};
};
const client = createClient({
baseUrl: "https://matrix.org",
accessToken,
refreshToken,
userId,
deviceId,
tokenRefreshFunction,
});
For OIDC sessions, use OidcTokenRefresher instead — see OIDC authentication.
Logout
Log out the current session
// Stop the client first to avoid race conditions with in-flight requests
await client.logout(true /* stopClient */);
Passing true stops the client and aborts pending requests before calling POST /logout. After logout, discard the MatrixClient instance and clear any stored credentials.
Deactivate an account
Account deactivation requires User-Interactive Authentication (UIA). See Interactive authentication (UIA) for details on constructing the auth dict.
await client.deactivateAccount(
{ type: "m.login.password", identifier: { type: "m.id.user", user: userId }, password, session },
true, // erase — request erasure of account data
);
Error handling
Authentication failures throw a MatrixError. The errcode field identifies the specific error:
import { MatrixError } from "matrix-js-sdk";
try {
const response = await tempClient.loginRequest({
type: "m.login.password",
identifier: { type: "m.id.user", user: "@alice:matrix.org" },
password: "wrong-password",
});
} catch (err) {
if (err instanceof MatrixError) {
switch (err.errcode) {
case "M_FORBIDDEN":
console.error("Invalid credentials");
break;
case "M_USER_DEACTIVATED":
console.error("Account has been deactivated");
break;
case "M_LIMIT_EXCEEDED":
console.error("Too many attempts. Retry after:", err.data.retry_after_ms, "ms");
break;
default:
console.error("Login failed:", err.message);
}
}
}
When the homeserver returns M_UNKNOWN_TOKEN during normal API usage, the SDK emits a Session.logged_out event. Subscribe to this event to handle forced logouts and prompt the user to re-authenticate.