Files
ThreadNet-Web/apps/web/src/PasswordReset.ts
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

109 lines
3.9 KiB
TypeScript
Raw Normal View History

2016-01-12 17:20:16 +00:00
/*
2024-09-09 14:57:16 +01:00
Copyright 2024 New Vector Ltd.
Copyright 2019-2022 The Matrix.org Foundation C.I.C.
2016-01-12 17:20:16 +00:00
Copyright 2015, 2016 OpenMarket Ltd
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
2024-09-09 14:57:16 +01:00
Please see LICENSE files in the repository root for full details.
2016-01-12 17:20:16 +00:00
*/
2025-02-05 13:25:06 +00:00
import { createClient, type IRequestTokenResponse, type MatrixClient } from "matrix-js-sdk/src/matrix";
2021-10-22 17:23:32 -05:00
2017-05-25 11:39:08 +01:00
import { _t } from "./languageHandler";
2016-01-12 17:20:16 +00:00
/**
* 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 {
2021-08-19 08:59:27 +02:00
private client: MatrixClient;
private clientSecret: string;
2022-11-22 07:58:37 +01:00
private password = "";
private sessionId = "";
private logoutDevices = false;
private sendAttempt = 0;
2021-08-19 08:59:27 +02:00
2016-01-12 17:20:16 +00:00
/**
* 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({
2016-01-12 17:20:16 +00:00
baseUrl: homeserverUrl,
2017-07-01 14:31:59 +01:00
idBaseUrl: identityUrl,
2016-01-12 17:20:16 +00:00
});
this.clientSecret = this.client.generateClientSecret();
2019-08-16 18:11:24 +01:00
}
2022-11-22 07:58:37 +01:00
/**
* 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) => {
2016-01-12 17:20:16 +00:00
this.sessionId = res.sid;
return res;
},
function (err) {
2017-07-01 14:31:59 +01:00
if (err.errcode === "M_THREEPID_NOT_FOUND") {
err.message = _t("auth|reset_password_email_not_found_title");
} else if (err.httpStatus) {
2016-01-12 17:20:16 +00:00
err.message = err.message + ` (Status ${err.httpStatus})`;
}
throw err;
},
);
}
public setLogoutDevices(logoutDevices: boolean): void {
this.logoutDevices = logoutDevices;
}
2022-11-22 07:58:37 +01:00
public async setNewPassword(password: string): Promise<void> {
this.password = password;
await this.checkEmailLinkClicked();
}
2016-01-12 17:20:16 +00:00
/**
* 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".
*/
2021-08-19 09:47:26 +02:00
public async checkEmailLinkClicked(): Promise<void> {
2019-09-24 14:47:08 +01:00
const creds = {
sid: this.sessionId,
client_secret: this.clientSecret,
};
try {
await this.client.setPassword(
{
2020-05-29 08:23:59 -06:00
// Note: Though this sounds like a login type for identity servers only, it
// has a dual purpose of being used for homeservers too.
2019-09-24 14:47:08 +01:00
type: "m.login.email.identity",
threepid_creds: creds,
},
this.password,
this.logoutDevices,
);
2022-11-22 07:58:37 +01:00
} catch (err: any) {
2016-01-12 17:20:16 +00:00
if (err.httpStatus === 401) {
err.message = _t("settings|general|add_email_failed_verification");
2017-07-01 14:31:59 +01:00
} else if (err.httpStatus === 404) {
err.message = _t("auth|reset_password_email_not_associated");
2017-07-01 14:31:59 +01:00
} else if (err.httpStatus) {
2016-01-12 17:20:16 +00:00
err.message += ` (Status ${err.httpStatus})`;
}
throw err;
2019-09-24 14:47:08 +01:00
}
2016-01-12 17:20:16 +00:00
}
}