UNPKG

22.4 kBSource Map (JSON)View Raw
1{"version":3,"sources":["../src/autodiscovery.js"],"names":["logger","require","DiscoveredClientConfig","state","AutoDiscovery","PROMPT","error","base_url","domain","length","Error","clientConfig","FAIL_ERROR","_fetchWellKnownObject","wellknown","action","raw","reason","FAIL_PROMPT","Promise","resolve","hsUrl","_sanitizeWellKnownUrl","hsVersions","SUCCESS","isUrl","failingClientConfig","isResponse","filter","k","map","url","parsed","NodeURL","URL","e","hostname","protocol","port","path","pathname","saferUrl","endsWith","substring","reject","request","getRequest","method","uri","err","response","body","statusCode","message","JSON","parse","name"],"mappings":"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","file":"autodiscovery.js","sourcesContent":["/*\nCopyright 2018 New Vector Ltd\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\n/** @module auto-discovery */\n\nimport Promise from 'bluebird';\nconst logger = require(\"./logger\");\nimport { URL as NodeURL } from \"url\";\n\n// Dev note: Auto discovery is part of the spec.\n// See: https://matrix.org/docs/spec/client_server/r0.4.0.html#server-discovery\n\n/**\n * Description for what an automatically discovered client configuration\n * would look like. Although this is a class, it is recommended that it\n * be treated as an interface definition rather than as a class.\n *\n * Additional properties than those defined here may be present, and\n * should follow the Java package naming convention.\n */\nclass DiscoveredClientConfig { // eslint-disable-line no-unused-vars\n // Dev note: this is basically a copy/paste of the .well-known response\n // object as defined in the spec. It does have additional information,\n // however. Overall, this exists to serve as a place for documentation\n // and not functionality.\n // See https://matrix.org/docs/spec/client_server/r0.4.0.html#get-well-known-matrix-client\n\n constructor() {\n /**\n * The homeserver configuration the client should use. This will\n * always be present on the object.\n * @type {{state: string, base_url: string}} The configuration.\n */\n this[\"m.homeserver\"] = {\n /**\n * The lookup result state. If this is anything other than\n * AutoDiscovery.SUCCESS then base_url may be falsey. Additionally,\n * if this is not AutoDiscovery.SUCCESS then the client should\n * assume the other properties in the client config (such as\n * the identity server configuration) are not valid.\n */\n state: AutoDiscovery.PROMPT,\n\n /**\n * If the state is AutoDiscovery.FAIL_ERROR or .FAIL_PROMPT\n * then this will contain a human-readable (English) message\n * for what went wrong. If the state is none of those previously\n * mentioned, this will be falsey.\n */\n error: \"Something went wrong\",\n\n /**\n * The base URL clients should use to talk to the homeserver,\n * particularly for the login process. May be falsey if the\n * state is not AutoDiscovery.SUCCESS.\n */\n base_url: \"https://matrix.org\",\n };\n\n /**\n * The identity server configuration the client should use. This\n * will always be present on teh object.\n * @type {{state: string, base_url: string}} The configuration.\n */\n this[\"m.identity_server\"] = {\n /**\n * The lookup result state. If this is anything other than\n * AutoDiscovery.SUCCESS then base_url may be falsey.\n */\n state: AutoDiscovery.PROMPT,\n\n /**\n * The base URL clients should use for interacting with the\n * identity server. May be falsey if the state is not\n * AutoDiscovery.SUCCESS.\n */\n base_url: \"https://vector.im\",\n };\n }\n}\n\n/**\n * Utilities for automatically discovery resources, such as homeservers\n * for users to log in to.\n */\nexport class AutoDiscovery {\n // Dev note: the constants defined here are related to but not\n // exactly the same as those in the spec. This is to hopefully\n // translate the meaning of the states in the spec, but also\n // support our own if needed.\n\n /**\n * The auto discovery failed. The client is expected to communicate\n * the error to the user and refuse logging in.\n * @return {string}\n * @constructor\n */\n static get FAIL_ERROR() { return \"FAIL_ERROR\"; }\n\n /**\n * The auto discovery failed, however the client may still recover\n * from the problem. The client is recommended to that the same\n * action it would for PROMPT while also warning the user about\n * what went wrong. The client may also treat this the same as\n * a FAIL_ERROR state.\n * @return {string}\n * @constructor\n */\n static get FAIL_PROMPT() { return \"FAIL_PROMPT\"; }\n\n /**\n * The auto discovery didn't fail but did not find anything of\n * interest. The client is expected to prompt the user for more\n * information, or fail if it prefers.\n * @return {string}\n * @constructor\n */\n static get PROMPT() { return \"PROMPT\"; }\n\n /**\n * The auto discovery was successful.\n * @return {string}\n * @constructor\n */\n static get SUCCESS() { return \"SUCCESS\"; }\n\n /**\n * Attempts to automatically discover client configuration information\n * prior to logging in. Such information includes the homeserver URL\n * and identity server URL the client would want. Additional details\n * may also be discovered, and will be transparently included in the\n * response object unaltered.\n * @param {string} domain The homeserver domain to perform discovery\n * on. For example, \"matrix.org\".\n * @return {Promise<DiscoveredClientConfig>} Resolves to the discovered\n * configuration, which may include error states. Rejects on unexpected\n * failure, not when discovery fails.\n */\n static async findClientConfig(domain) {\n if (!domain || typeof(domain) !== \"string\" || domain.length === 0) {\n throw new Error(\"'domain' must be a string of non-zero length\");\n }\n\n // We use a .well-known lookup for all cases. According to the spec, we\n // can do other discovery mechanisms if we want such as custom lookups\n // however we won't bother with that here (mostly because the spec only\n // supports .well-known right now).\n //\n // By using .well-known, we need to ensure we at least pull out a URL\n // for the homeserver. We don't really need an identity server configuration\n // but will return one anyways (with state PROMPT) to make development\n // easier for clients. If we can't get a homeserver URL, all bets are\n // off on the rest of the config and we'll assume it is invalid too.\n\n // We default to an error state to make the first few checks easier to\n // write. We'll update the properties of this object over the duration\n // of this function.\n const clientConfig = {\n \"m.homeserver\": {\n state: AutoDiscovery.FAIL_ERROR,\n error: \"Invalid homeserver discovery response\",\n base_url: null,\n },\n \"m.identity_server\": {\n // Technically, we don't have a problem with the identity server\n // config at this point.\n state: AutoDiscovery.PROMPT,\n error: null,\n base_url: null,\n },\n };\n\n // Step 1: Actually request the .well-known JSON file and make sure it\n // at least has a homeserver definition.\n const wellknown = await this._fetchWellKnownObject(\n `https://${domain}/.well-known/matrix/client`,\n );\n if (!wellknown || wellknown.action !== \"SUCCESS\"\n || !wellknown.raw[\"m.homeserver\"]\n || !wellknown.raw[\"m.homeserver\"][\"base_url\"]) {\n logger.error(\"No m.homeserver key in well-known response\");\n if (wellknown.reason) logger.error(wellknown.reason);\n if (wellknown.action === \"IGNORE\") {\n clientConfig[\"m.homeserver\"] = {\n state: AutoDiscovery.PROMPT,\n error: null,\n base_url: null,\n };\n } else {\n // this can only ever be FAIL_PROMPT at this point.\n clientConfig[\"m.homeserver\"].state = AutoDiscovery.FAIL_PROMPT;\n }\n return Promise.resolve(clientConfig);\n }\n\n // Step 2: Make sure the homeserver URL is valid *looking*. We'll make\n // sure it points to a homeserver in Step 3.\n const hsUrl = this._sanitizeWellKnownUrl(\n wellknown.raw[\"m.homeserver\"][\"base_url\"],\n );\n if (!hsUrl) {\n logger.error(\"Invalid base_url for m.homeserver\");\n return Promise.resolve(clientConfig);\n }\n\n // Step 3: Make sure the homeserver URL points to a homeserver.\n const hsVersions = await this._fetchWellKnownObject(\n `${hsUrl}/_matrix/client/versions`,\n );\n if (!hsVersions || !hsVersions.raw[\"versions\"]) {\n logger.error(\"Invalid /versions response\");\n return Promise.resolve(clientConfig);\n }\n\n // Step 4: Now that the homeserver looks valid, update our client config.\n clientConfig[\"m.homeserver\"] = {\n state: AutoDiscovery.SUCCESS,\n error: null,\n base_url: hsUrl,\n };\n\n // Step 5: Try to pull out the identity server configuration\n let isUrl = \"\";\n if (wellknown.raw[\"m.identity_server\"]) {\n // We prepare a failing identity server response to save lines later\n // in this branch. Note that we also fail the homeserver check in the\n // object because according to the spec we're supposed to FAIL_ERROR\n // if *anything* goes wrong with the IS validation, including invalid\n // format. This means we're supposed to stop discovery completely.\n const failingClientConfig = {\n \"m.homeserver\": {\n state: AutoDiscovery.FAIL_ERROR,\n error: \"Invalid identity server discovery response\",\n\n // We'll provide the base_url that was previously valid for\n // debugging purposes.\n base_url: clientConfig[\"m.homeserver\"].base_url,\n },\n \"m.identity_server\": {\n state: AutoDiscovery.FAIL_ERROR,\n error: \"Invalid identity server discovery response\",\n base_url: null,\n },\n };\n\n // Step 5a: Make sure the URL is valid *looking*. We'll make sure it\n // points to an identity server in Step 5b.\n isUrl = this._sanitizeWellKnownUrl(\n wellknown.raw[\"m.identity_server\"][\"base_url\"],\n );\n if (!isUrl) {\n logger.error(\"Invalid base_url for m.identity_server\");\n return Promise.resolve(failingClientConfig);\n }\n\n // Step 5b: Verify there is an identity server listening on the provided\n // URL.\n const isResponse = await this._fetchWellKnownObject(\n `${isUrl}/_matrix/identity/api/v1`,\n );\n if (!isResponse || !isResponse.raw || isResponse.action !== \"SUCCESS\") {\n logger.error(\"Invalid /api/v1 response\");\n return Promise.resolve(failingClientConfig);\n }\n }\n\n // Step 6: Now that the identity server is valid, or never existed,\n // populate the IS section.\n if (isUrl && isUrl.length > 0) {\n clientConfig[\"m.identity_server\"] = {\n state: AutoDiscovery.SUCCESS,\n error: null,\n base_url: isUrl,\n };\n }\n\n // Step 7: Copy any other keys directly into the clientConfig. This is for\n // things like custom configuration of services.\n Object.keys(wellknown.raw)\n .filter((k) => k !== \"m.homeserver\" && k !== \"m.identity_server\")\n .map((k) => clientConfig[k] = wellknown.raw[k]);\n\n // Step 8: Give the config to the caller (finally)\n return Promise.resolve(clientConfig);\n }\n\n /**\n * Sanitizes a given URL to ensure it is either an HTTP or HTTP URL and\n * is suitable for the requirements laid out by .well-known auto discovery.\n * If valid, the URL will also be stripped of any trailing slashes.\n * @param {string} url The potentially invalid URL to sanitize.\n * @return {string|boolean} The sanitized URL or a falsey value if the URL is invalid.\n * @private\n */\n static _sanitizeWellKnownUrl(url) {\n if (!url) return false;\n\n try {\n // We have to try and parse the URL using the NodeJS URL\n // library if we're on NodeJS and use the browser's URL\n // library when we're in a browser. To accomplish this, we\n // try the NodeJS version first and fall back to the browser.\n let parsed = null;\n try {\n if (NodeURL) parsed = new NodeURL(url);\n else parsed = new URL(url);\n } catch (e) {\n parsed = new URL(url);\n }\n\n if (!parsed || !parsed.hostname) return false;\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") return false;\n\n const port = parsed.port ? `:${parsed.port}` : \"\";\n const path = parsed.pathname ? parsed.pathname : \"\";\n let saferUrl = `${parsed.protocol}//${parsed.hostname}${port}${path}`;\n if (saferUrl.endsWith(\"/\")) {\n saferUrl = saferUrl.substring(0, saferUrl.length - 1);\n }\n return saferUrl;\n } catch (e) {\n logger.error(e);\n return false;\n }\n }\n\n /**\n * Fetches a JSON object from a given URL, as expected by all .well-known\n * related lookups. If the server gives a 404 then the `action` will be\n * IGNORE. If the server returns something that isn't JSON, the `action`\n * will be FAIL_PROMPT. For any other failure the `action` will be FAIL_PROMPT.\n *\n * The returned object will be a result of the call in object form with\n * the following properties:\n * raw: The JSON object returned by the server.\n * action: One of SUCCESS, IGNORE, or FAIL_PROMPT.\n * reason: Relatively human readable description of what went wrong.\n * error: The actual Error, if one exists.\n * @param {string} url The URL to fetch a JSON object from.\n * @return {Promise<object>} Resolves to the returned state.\n * @private\n */\n static async _fetchWellKnownObject(url) {\n return new Promise(function(resolve, reject) {\n const request = require(\"./matrix\").getRequest();\n if (!request) throw new Error(\"No request library available\");\n request(\n { method: \"GET\", uri: url },\n (err, response, body) => {\n if (err || response.statusCode < 200 || response.statusCode >= 300) {\n let action = \"FAIL_PROMPT\";\n let reason = (err ? err.message : null) || \"General failure\";\n if (response.statusCode === 404) {\n action = \"IGNORE\";\n reason = \"No .well-known JSON file found\";\n }\n resolve({raw: {}, action: action, reason: reason, error: err});\n return;\n }\n\n try {\n resolve({raw: JSON.parse(body), action: \"SUCCESS\"});\n } catch (e) {\n let reason = \"General failure\";\n if (e.name === \"SyntaxError\") reason = \"Invalid JSON\";\n resolve({\n raw: {},\n action: \"FAIL_PROMPT\",\n reason: reason, error: e,\n });\n }\n },\n );\n });\n }\n}\n"]}
\No newline at end of file