diff --git a/src/IdentityAuthClient.js b/src/IdentityAuthClient.js index 755205d5e2..d3b4d8a6de 100644 --- a/src/IdentityAuthClient.js +++ b/src/IdentityAuthClient.js @@ -14,15 +14,50 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { SERVICE_TYPES } from 'matrix-js-sdk'; +import { createClient, SERVICE_TYPES } from 'matrix-js-sdk'; import MatrixClientPeg from './MatrixClientPeg'; import { Service, startTermsFlow, TermsNotSignedError } from './Terms'; export default class IdentityAuthClient { - constructor() { + /** + * Creates a new identity auth client + * @param {string} identityUrl The URL to contact the identity server with. + * When provided, this class will operate solely within memory, refusing to + * persist any information such as tokens. Default null (not provided). + */ + constructor(identityUrl = null) { this.accessToken = null; this.authEnabled = true; + + if (identityUrl) { + // XXX: We shouldn't have to create a whole new MatrixClient just to + // do identity server auth. The functions don't take an identity URL + // though, and making all of them take one could lead to developer + // confusion about what the idBaseUrl does on a client. Therefore, we + // just make a new client and live with it. + this.tempClient = createClient({ + baseUrl: "", // invalid by design + idBaseUrl: identityUrl, + }); + } else { + // Indicates that we're using the real client, not some workaround. + this.tempClient = null; + } + } + + get _matrixClient() { + return this.tempClient ? this.tempClient : MatrixClientPeg.get(); + } + + _writeToken() { + if (this.tempClient) return; // temporary client: ignore + window.localStorage.setItem("mx_is_access_token", this.accessToken); + } + + _readToken() { + if (this.tempClient) return null; // temporary client: ignore + return window.localStorage.getItem("mx_is_access_token"); } hasCredentials() { @@ -38,14 +73,14 @@ export default class IdentityAuthClient { let token = this.accessToken; if (!token) { - token = window.localStorage.getItem("mx_is_access_token"); + token = this._readToken(); } if (!token) { token = await this.registerForToken(); if (token) { this.accessToken = token; - window.localStorage.setItem("mx_is_access_token", token); + this._writeToken(); } return token; } @@ -61,7 +96,7 @@ export default class IdentityAuthClient { token = await this.registerForToken(); if (token) { this.accessToken = token; - window.localStorage.setItem("mx_is_access_token", token); + this._writeToken(); } } @@ -70,13 +105,13 @@ export default class IdentityAuthClient { async _checkToken(token) { try { - await MatrixClientPeg.get().getIdentityAccount(token); + await this._matrixClient.getIdentityAccount(token); } catch (e) { if (e.errcode === "M_TERMS_NOT_SIGNED") { console.log("Identity Server requires new terms to be agreed to"); await startTermsFlow([new Service( SERVICE_TYPES.IS, - MatrixClientPeg.get().idBaseUrl, + this._matrixClient.getIdentityServerUrl(), token, )]); return; @@ -95,7 +130,7 @@ export default class IdentityAuthClient { try { const hsOpenIdToken = await MatrixClientPeg.get().getOpenIdToken(); const { access_token: identityAccessToken } = - await MatrixClientPeg.get().registerWithIdentityServer(hsOpenIdToken); + await this._matrixClient.registerWithIdentityServer(hsOpenIdToken); await this._checkToken(identityAccessToken); return identityAccessToken; } catch (e) { diff --git a/src/components/views/settings/SetIdServer.js b/src/components/views/settings/SetIdServer.js index 8b9c3150a3..9bb9fdd0e3 100644 --- a/src/components/views/settings/SetIdServer.js +++ b/src/components/views/settings/SetIdServer.js @@ -23,6 +23,8 @@ import SdkConfig from "../../../SdkConfig"; import Modal from '../../../Modal'; import dis from "../../../dispatcher"; import { getThreepidBindStatus } from '../../../boundThreepids'; +import IdentityAuthClient from "../../../IdentityAuthClient"; +import {SERVICE_TYPES} from "matrix-js-sdk"; /** * If a url has no path component, etc. abbreviate it to just the hostname @@ -101,6 +103,7 @@ export default class SetIdServer extends React.Component { error: null, busy: false, disconnectBusy: false, + checking: false, }; } @@ -111,14 +114,14 @@ export default class SetIdServer extends React.Component { }; _getTooltip = () => { - if (this.state.busy) { + if (this.state.checking) { const InlineSpinner = sdk.getComponent('views.elements.InlineSpinner'); return