Files
element-web/src/PasswordReset.ts
Michael Telatynski c05c429803 Absorb the matrix-react-sdk repository (#28192)
Co-authored-by: github-merge-queue <118344674+github-merge-queue@users.noreply.github.com>
Co-authored-by: github-merge-queue <github-merge-queue@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Florian Duros <florian.duros@ormaz.fr>
Co-authored-by: Kim Brose <kim.brose@nordeck.net>
Co-authored-by: Florian Duros <florianduros@element.io>
Co-authored-by: R Midhun Suresh <hi@midhun.dev>
Co-authored-by: dbkr <986903+dbkr@users.noreply.github.com>
Co-authored-by: ElementRobot <releases@riot.im>
Co-authored-by: dbkr <dbkr@users.noreply.github.com>
Co-authored-by: David Baker <dbkr@users.noreply.github.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>
Co-authored-by: David Langley <davidl@element.io>
Co-authored-by: Michael Weimann <michaelw@matrix.org>
Co-authored-by: Timshel <Timshel@users.noreply.github.com>
Co-authored-by: Sahil Silare <32628578+sahil9001@users.noreply.github.com>
Co-authored-by: Will Hunt <will@half-shot.uk>
Co-authored-by: Hubert Chathi <hubert@uhoreg.ca>
Co-authored-by: Andrew Ferrazzutti <andrewf@element.io>
Co-authored-by: Robin <robin@robin.town>
Co-authored-by: Tulir Asokan <tulir@maunium.net>
2024-10-16 13:31:55 +01:00

109 lines
3.9 KiB
TypeScript

/*
Copyright 2024 New Vector Ltd.
Copyright 2019-2022 The Matrix.org Foundation C.I.C.
Copyright 2015, 2016 OpenMarket Ltd
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
import { createClient, IRequestTokenResponse, MatrixClient } from "matrix-js-sdk/src/matrix";
import { _t } from "./languageHandler";
/**
* Allows a user to reset their password on a homeserver.
*
* This involves getting an email token from the identity server to "prove" that
* the client owns the given email address, which is then passed to the password
* API on the homeserver in question with the new password.
*/
export default class PasswordReset {
private client: MatrixClient;
private clientSecret: string;
private password = "";
private sessionId = "";
private logoutDevices = false;
private sendAttempt = 0;
/**
* Configure the endpoints for password resetting.
* @param {string} homeserverUrl The URL to the HS which has the account to reset.
* @param {string} identityUrl The URL to the IS which has linked the email -> mxid mapping.
*/
public constructor(homeserverUrl: string, identityUrl: string) {
this.client = createClient({
baseUrl: homeserverUrl,
idBaseUrl: identityUrl,
});
this.clientSecret = this.client.generateClientSecret();
}
/**
* Request a password reset token.
* This will trigger a side-effect of sending an email to the provided email address.
*/
public requestResetToken(emailAddress: string): Promise<IRequestTokenResponse> {
this.sendAttempt++;
return this.client.requestPasswordEmailToken(emailAddress, this.clientSecret, this.sendAttempt).then(
(res) => {
this.sessionId = res.sid;
return res;
},
function (err) {
if (err.errcode === "M_THREEPID_NOT_FOUND") {
err.message = _t("auth|reset_password_email_not_found_title");
} else if (err.httpStatus) {
err.message = err.message + ` (Status ${err.httpStatus})`;
}
throw err;
},
);
}
public setLogoutDevices(logoutDevices: boolean): void {
this.logoutDevices = logoutDevices;
}
public async setNewPassword(password: string): Promise<void> {
this.password = password;
await this.checkEmailLinkClicked();
}
/**
* Checks if the email link has been clicked by attempting to change the password
* for the mxid linked to the email.
* @return {Promise} Resolves if the password was reset. Rejects with an object
* with a "message" property which contains a human-readable message detailing why
* the reset failed, e.g. "There is no mapped matrix user ID for the given email address".
*/
public async checkEmailLinkClicked(): Promise<void> {
const creds = {
sid: this.sessionId,
client_secret: this.clientSecret,
};
try {
await this.client.setPassword(
{
// Note: Though this sounds like a login type for identity servers only, it
// has a dual purpose of being used for homeservers too.
type: "m.login.email.identity",
threepid_creds: creds,
},
this.password,
this.logoutDevices,
);
} catch (err: any) {
if (err.httpStatus === 401) {
err.message = _t("settings|general|add_email_failed_verification");
} else if (err.httpStatus === 404) {
err.message = _t("auth|reset_password_email_not_associated");
} else if (err.httpStatus) {
err.message += ` (Status ${err.httpStatus})`;
}
throw err;
}
}
}