summaryrefslogtreecommitdiff
path: root/includes/external/matrix/node_modules/matrix-js-sdk/lib/interactive-auth.js
diff options
context:
space:
mode:
authorRaindropsSys <raindrops@equestria.dev>2023-11-17 23:25:29 +0100
committerRaindropsSys <raindrops@equestria.dev>2023-11-17 23:25:29 +0100
commit953ddd82e48dd206cef5ac94456549aed13b3ad5 (patch)
tree8f003106ee2e7f422e5a22d2ee04d0db302e66c0 /includes/external/matrix/node_modules/matrix-js-sdk/lib/interactive-auth.js
parent62a9199846b0c07c03218703b33e8385764f42d9 (diff)
downloadpluralconnect-953ddd82e48dd206cef5ac94456549aed13b3ad5.tar.gz
pluralconnect-953ddd82e48dd206cef5ac94456549aed13b3ad5.tar.bz2
pluralconnect-953ddd82e48dd206cef5ac94456549aed13b3ad5.zip
Updated 30 files and deleted 2976 files (automated)
Diffstat (limited to 'includes/external/matrix/node_modules/matrix-js-sdk/lib/interactive-auth.js')
-rw-r--r--includes/external/matrix/node_modules/matrix-js-sdk/lib/interactive-auth.js488
1 files changed, 0 insertions, 488 deletions
diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/lib/interactive-auth.js b/includes/external/matrix/node_modules/matrix-js-sdk/lib/interactive-auth.js
deleted file mode 100644
index 7acf359..0000000
--- a/includes/external/matrix/node_modules/matrix-js-sdk/lib/interactive-auth.js
+++ /dev/null
@@ -1,488 +0,0 @@
-"use strict";
-
-var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
-Object.defineProperty(exports, "__esModule", {
- value: true
-});
-exports.InteractiveAuth = exports.AuthType = void 0;
-var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
-var _logger = require("./logger");
-var _utils = require("./utils");
-/*
-Copyright 2016 OpenMarket Ltd
-Copyright 2017 Vector Creations Ltd
-Copyright 2019 The Matrix.org Foundation C.I.C.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-const EMAIL_STAGE_TYPE = "m.login.email.identity";
-const MSISDN_STAGE_TYPE = "m.login.msisdn";
-let AuthType;
-exports.AuthType = AuthType;
-(function (AuthType) {
- AuthType["Password"] = "m.login.password";
- AuthType["Recaptcha"] = "m.login.recaptcha";
- AuthType["Terms"] = "m.login.terms";
- AuthType["Email"] = "m.login.email.identity";
- AuthType["Msisdn"] = "m.login.msisdn";
- AuthType["Sso"] = "m.login.sso";
- AuthType["SsoUnstable"] = "org.matrix.login.sso";
- AuthType["Dummy"] = "m.login.dummy";
- AuthType["RegistrationToken"] = "m.login.registration_token";
- AuthType["UnstableRegistrationToken"] = "org.matrix.msc3231.login.registration_token";
-})(AuthType || (exports.AuthType = AuthType = {}));
-class NoAuthFlowFoundError extends Error {
- // eslint-disable-next-line @typescript-eslint/naming-convention, camelcase
- constructor(m, required_stages, flows) {
- super(m);
- this.required_stages = required_stages;
- this.flows = flows;
- (0, _defineProperty2.default)(this, "name", "NoAuthFlowFoundError");
- }
-}
-/**
- * Abstracts the logic used to drive the interactive auth process.
- *
- * <p>Components implementing an interactive auth flow should instantiate one of
- * these, passing in the necessary callbacks to the constructor. They should
- * then call attemptAuth, which will return a promise which will resolve or
- * reject when the interactive-auth process completes.
- *
- * <p>Meanwhile, calls will be made to the startAuthStage and doRequest
- * callbacks, and information gathered from the user can be submitted with
- * submitAuthDict.
- *
- * @param opts - options object
- */
-class InteractiveAuth {
- // if we are currently trying to submit an auth dict (which includes polling)
- // the promise the will resolve/reject when it completes
-
- constructor(opts) {
- (0, _defineProperty2.default)(this, "matrixClient", void 0);
- (0, _defineProperty2.default)(this, "inputs", void 0);
- (0, _defineProperty2.default)(this, "clientSecret", void 0);
- (0, _defineProperty2.default)(this, "requestCallback", void 0);
- (0, _defineProperty2.default)(this, "busyChangedCallback", void 0);
- (0, _defineProperty2.default)(this, "stateUpdatedCallback", void 0);
- (0, _defineProperty2.default)(this, "requestEmailTokenCallback", void 0);
- (0, _defineProperty2.default)(this, "data", void 0);
- (0, _defineProperty2.default)(this, "emailSid", void 0);
- (0, _defineProperty2.default)(this, "requestingEmailToken", false);
- (0, _defineProperty2.default)(this, "attemptAuthDeferred", null);
- (0, _defineProperty2.default)(this, "chosenFlow", null);
- (0, _defineProperty2.default)(this, "currentStage", null);
- (0, _defineProperty2.default)(this, "emailAttempt", 1);
- (0, _defineProperty2.default)(this, "submitPromise", null);
- (0, _defineProperty2.default)(this, "requestEmailToken", async () => {
- if (!this.requestingEmailToken) {
- _logger.logger.trace("Requesting email token. Attempt: " + this.emailAttempt);
- // If we've picked a flow with email auth, we send the email
- // now because we want the request to fail as soon as possible
- // if the email address is not valid (ie. already taken or not
- // registered, depending on what the operation is).
- this.requestingEmailToken = true;
- try {
- const requestTokenResult = await this.requestEmailTokenCallback(this.inputs.emailAddress, this.clientSecret, this.emailAttempt++, this.data.session);
- this.emailSid = requestTokenResult.sid;
- _logger.logger.trace("Email token request succeeded");
- } finally {
- this.requestingEmailToken = false;
- }
- } else {
- _logger.logger.warn("Could not request email token: Already requesting");
- }
- });
- this.matrixClient = opts.matrixClient;
- this.data = opts.authData || {};
- this.requestCallback = opts.doRequest;
- this.busyChangedCallback = opts.busyChanged;
- // startAuthStage included for backwards compat
- this.stateUpdatedCallback = opts.stateUpdated || opts.startAuthStage;
- this.requestEmailTokenCallback = opts.requestEmailToken;
- this.inputs = opts.inputs || {};
- if (opts.sessionId) this.data.session = opts.sessionId;
- this.clientSecret = opts.clientSecret || this.matrixClient.generateClientSecret();
- this.emailSid = opts.emailSid;
- }
-
- /**
- * begin the authentication process.
- *
- * @returns which resolves to the response on success,
- * or rejects with the error on failure. Rejects with NoAuthFlowFoundError if
- * no suitable authentication flow can be found
- */
- attemptAuth() {
- var _this$data;
- // This promise will be quite long-lived and will resolve when the
- // request is authenticated and completes successfully.
- this.attemptAuthDeferred = (0, _utils.defer)();
- // pluck the promise out now, as doRequest may clear before we return
- const promise = this.attemptAuthDeferred.promise;
-
- // if we have no flows, try a request to acquire the flows
- if (!((_this$data = this.data) !== null && _this$data !== void 0 && _this$data.flows)) {
- var _this$busyChangedCall;
- (_this$busyChangedCall = this.busyChangedCallback) === null || _this$busyChangedCall === void 0 ? void 0 : _this$busyChangedCall.call(this, true);
- // use the existing sessionId, if one is present.
- const auth = this.data.session ? {
- session: this.data.session
- } : null;
- this.doRequest(auth).finally(() => {
- var _this$busyChangedCall2;
- (_this$busyChangedCall2 = this.busyChangedCallback) === null || _this$busyChangedCall2 === void 0 ? void 0 : _this$busyChangedCall2.call(this, false);
- });
- } else {
- this.startNextAuthStage();
- }
- return promise;
- }
-
- /**
- * Poll to check if the auth session or current stage has been
- * completed out-of-band. If so, the attemptAuth promise will
- * be resolved.
- */
- async poll() {
- if (!this.data.session) return;
- // likewise don't poll if there is no auth session in progress
- if (!this.attemptAuthDeferred) return;
- // if we currently have a request in flight, there's no point making
- // another just to check what the status is
- if (this.submitPromise) return;
- let authDict = {};
- if (this.currentStage == EMAIL_STAGE_TYPE) {
- // The email can be validated out-of-band, but we need to provide the
- // creds so the HS can go & check it.
- if (this.emailSid) {
- const creds = {
- sid: this.emailSid,
- client_secret: this.clientSecret
- };
- if (await this.matrixClient.doesServerRequireIdServerParam()) {
- const idServerParsedUrl = new URL(this.matrixClient.getIdentityServerUrl());
- creds.id_server = idServerParsedUrl.host;
- }
- authDict = {
- type: EMAIL_STAGE_TYPE,
- // TODO: Remove `threepid_creds` once servers support proper UIA
- // See https://github.com/matrix-org/synapse/issues/5665
- // See https://github.com/matrix-org/matrix-doc/issues/2220
- threepid_creds: creds,
- threepidCreds: creds
- };
- }
- }
- this.submitAuthDict(authDict, true);
- }
-
- /**
- * get the auth session ID
- *
- * @returns session id
- */
- getSessionId() {
- var _this$data2;
- return (_this$data2 = this.data) === null || _this$data2 === void 0 ? void 0 : _this$data2.session;
- }
-
- /**
- * get the client secret used for validation sessions
- * with the identity server.
- *
- * @returns client secret
- */
- getClientSecret() {
- return this.clientSecret;
- }
-
- /**
- * get the server params for a given stage
- *
- * @param loginType - login type for the stage
- * @returns any parameters from the server for this stage
- */
- getStageParams(loginType) {
- var _this$data$params;
- return (_this$data$params = this.data.params) === null || _this$data$params === void 0 ? void 0 : _this$data$params[loginType];
- }
- getChosenFlow() {
- return this.chosenFlow;
- }
-
- /**
- * submit a new auth dict and fire off the request. This will either
- * make attemptAuth resolve/reject, or cause the startAuthStage callback
- * to be called for a new stage.
- *
- * @param authData - new auth dict to send to the server. Should
- * include a `type` property denoting the login type, as well as any
- * other params for that stage.
- * @param background - If true, this request failing will not result
- * in the attemptAuth promise being rejected. This can be set to true
- * for requests that just poll to see if auth has been completed elsewhere.
- */
- async submitAuthDict(authData, background = false) {
- if (!this.attemptAuthDeferred) {
- throw new Error("submitAuthDict() called before attemptAuth()");
- }
- if (!background) {
- var _this$busyChangedCall3;
- (_this$busyChangedCall3 = this.busyChangedCallback) === null || _this$busyChangedCall3 === void 0 ? void 0 : _this$busyChangedCall3.call(this, true);
- }
-
- // if we're currently trying a request, wait for it to finish
- // as otherwise we can get multiple 200 responses which can mean
- // things like multiple logins for register requests.
- // (but discard any exceptions as we only care when its done,
- // not whether it worked or not)
- while (this.submitPromise) {
- try {
- await this.submitPromise;
- } catch (e) {}
- }
-
- // use the sessionid from the last request, if one is present.
- let auth;
- if (this.data.session) {
- auth = {
- session: this.data.session
- };
- Object.assign(auth, authData);
- } else {
- auth = authData;
- }
- try {
- // NB. the 'background' flag is deprecated by the busyChanged
- // callback and is here for backwards compat
- this.submitPromise = this.doRequest(auth, background);
- await this.submitPromise;
- } finally {
- this.submitPromise = null;
- if (!background) {
- var _this$busyChangedCall4;
- (_this$busyChangedCall4 = this.busyChangedCallback) === null || _this$busyChangedCall4 === void 0 ? void 0 : _this$busyChangedCall4.call(this, false);
- }
- }
- }
-
- /**
- * Gets the sid for the email validation session
- * Specific to m.login.email.identity
- *
- * @returns The sid of the email auth session
- */
- getEmailSid() {
- return this.emailSid;
- }
-
- /**
- * Sets the sid for the email validation session
- * This must be set in order to successfully poll for completion
- * of the email validation.
- * Specific to m.login.email.identity
- *
- * @param sid - The sid for the email validation session
- */
- setEmailSid(sid) {
- this.emailSid = sid;
- }
-
- /**
- * Requests a new email token and sets the email sid for the validation session
- */
-
- /**
- * Fire off a request, and either resolve the promise, or call
- * startAuthStage.
- *
- * @internal
- * @param auth - new auth dict, including session id
- * @param background - If true, this request is a background poll, so it
- * failing will not result in the attemptAuth promise being rejected.
- * This can be set to true for requests that just poll to see if auth has
- * been completed elsewhere.
- */
- async doRequest(auth, background = false) {
- try {
- const result = await this.requestCallback(auth, background);
- this.attemptAuthDeferred.resolve(result);
- this.attemptAuthDeferred = null;
- } catch (error) {
- var _data$flows, _data, _this$chosenFlow;
- // sometimes UI auth errors don't come with flows
- const errorFlows = (_data$flows = (_data = error.data) === null || _data === void 0 ? void 0 : _data.flows) !== null && _data$flows !== void 0 ? _data$flows : null;
- const haveFlows = this.data.flows || Boolean(errorFlows);
- if (error.httpStatus !== 401 || !error.data || !haveFlows) {
- // doesn't look like an interactive-auth failure.
- if (!background) {
- var _this$attemptAuthDefe;
- (_this$attemptAuthDefe = this.attemptAuthDeferred) === null || _this$attemptAuthDefe === void 0 ? void 0 : _this$attemptAuthDefe.reject(error);
- } else {
- // We ignore all failures here (even non-UI auth related ones)
- // since we don't want to suddenly fail if the internet connection
- // had a blip whilst we were polling
- _logger.logger.log("Background poll request failed doing UI auth: ignoring", error);
- }
- }
- if (!error.data) {
- error.data = {};
- }
- // if the error didn't come with flows, completed flows or session ID,
- // copy over the ones we have. Synapse sometimes sends responses without
- // any UI auth data (eg. when polling for email validation, if the email
- // has not yet been validated). This appears to be a Synapse bug, which
- // we workaround here.
- if (!error.data.flows && !error.data.completed && !error.data.session) {
- error.data.flows = this.data.flows;
- error.data.completed = this.data.completed;
- error.data.session = this.data.session;
- }
- this.data = error.data;
- try {
- this.startNextAuthStage();
- } catch (e) {
- this.attemptAuthDeferred.reject(e);
- this.attemptAuthDeferred = null;
- return;
- }
- if (!this.emailSid && (_this$chosenFlow = this.chosenFlow) !== null && _this$chosenFlow !== void 0 && _this$chosenFlow.stages.includes(AuthType.Email)) {
- try {
- await this.requestEmailToken();
- // NB. promise is not resolved here - at some point, doRequest
- // will be called again and if the user has jumped through all
- // the hoops correctly, auth will be complete and the request
- // will succeed.
- // Also, we should expose the fact that this request has compledted
- // so clients can know that the email has actually been sent.
- } catch (e) {
- // we failed to request an email token, so fail the request.
- // This could be due to the email already beeing registered
- // (or not being registered, depending on what we're trying
- // to do) or it could be a network failure. Either way, pass
- // the failure up as the user can't complete auth if we can't
- // send the email, for whatever reason.
- this.attemptAuthDeferred.reject(e);
- this.attemptAuthDeferred = null;
- }
- }
- }
- }
-
- /**
- * Pick the next stage and call the callback
- *
- * @internal
- * @throws {@link NoAuthFlowFoundError} If no suitable authentication flow can be found
- */
- startNextAuthStage() {
- var _this$data3, _this$data4;
- const nextStage = this.chooseStage();
- if (!nextStage) {
- throw new Error("No incomplete flows from the server");
- }
- this.currentStage = nextStage;
- if (nextStage === AuthType.Dummy) {
- this.submitAuthDict({
- type: "m.login.dummy"
- });
- return;
- }
- if ((_this$data3 = this.data) !== null && _this$data3 !== void 0 && _this$data3.errcode || (_this$data4 = this.data) !== null && _this$data4 !== void 0 && _this$data4.error) {
- var _this$data5, _this$data6;
- this.stateUpdatedCallback(nextStage, {
- errcode: ((_this$data5 = this.data) === null || _this$data5 === void 0 ? void 0 : _this$data5.errcode) || "",
- error: ((_this$data6 = this.data) === null || _this$data6 === void 0 ? void 0 : _this$data6.error) || ""
- });
- return;
- }
- this.stateUpdatedCallback(nextStage, nextStage === EMAIL_STAGE_TYPE ? {
- emailSid: this.emailSid
- } : {});
- }
-
- /**
- * Pick the next auth stage
- *
- * @internal
- * @returns login type
- * @throws {@link NoAuthFlowFoundError} If no suitable authentication flow can be found
- */
- chooseStage() {
- if (this.chosenFlow === null) {
- this.chosenFlow = this.chooseFlow();
- }
- _logger.logger.log("Active flow => %s", JSON.stringify(this.chosenFlow));
- const nextStage = this.firstUncompletedStage(this.chosenFlow);
- _logger.logger.log("Next stage: %s", nextStage);
- return nextStage;
- }
-
- /**
- * Pick one of the flows from the returned list
- * If a flow using all of the inputs is found, it will
- * be returned, otherwise, null will be returned.
- *
- * Only flows using all given inputs are chosen because it
- * is likely to be surprising if the user provides a
- * credential and it is not used. For example, for registration,
- * this could result in the email not being used which would leave
- * the account with no means to reset a password.
- *
- * @internal
- * @returns flow
- * @throws {@link NoAuthFlowFoundError} If no suitable authentication flow can be found
- */
- chooseFlow() {
- const flows = this.data.flows || [];
-
- // we've been given an email or we've already done an email part
- const haveEmail = Boolean(this.inputs.emailAddress) || Boolean(this.emailSid);
- const haveMsisdn = Boolean(this.inputs.phoneCountry) && Boolean(this.inputs.phoneNumber);
- for (const flow of flows) {
- let flowHasEmail = false;
- let flowHasMsisdn = false;
- for (const stage of flow.stages) {
- if (stage === EMAIL_STAGE_TYPE) {
- flowHasEmail = true;
- } else if (stage == MSISDN_STAGE_TYPE) {
- flowHasMsisdn = true;
- }
- }
- if (flowHasEmail == haveEmail && flowHasMsisdn == haveMsisdn) {
- return flow;
- }
- }
- const requiredStages = [];
- if (haveEmail) requiredStages.push(EMAIL_STAGE_TYPE);
- if (haveMsisdn) requiredStages.push(MSISDN_STAGE_TYPE);
- // Throw an error with a fairly generic description, but with more
- // information such that the app can give a better one if so desired.
- throw new NoAuthFlowFoundError("No appropriate authentication flow found", requiredStages, flows);
- }
-
- /**
- * Get the first uncompleted stage in the given flow
- *
- * @internal
- * @returns login type
- */
- firstUncompletedStage(flow) {
- const completed = this.data.completed || [];
- return flow.stages.find(stageType => !completed.includes(stageType));
- }
-}
-exports.InteractiveAuth = InteractiveAuth;
-//# sourceMappingURL=interactive-auth.js.map \ No newline at end of file