2015-10-26 18:35:24 +01:00
|
|
|
window.matrixLogin = {
|
2018-11-27 08:51:52 +01:00
|
|
|
endpoint: location.origin + "/_matrix/client/r0/login",
|
2015-10-26 18:35:24 +01:00
|
|
|
serverAcceptsPassword: false,
|
2018-11-27 08:51:52 +01:00
|
|
|
serverAcceptsSso: false,
|
2015-10-26 18:35:24 +01:00
|
|
|
};
|
|
|
|
|
2020-06-08 16:13:24 +02:00
|
|
|
// Titles get updated through the process to give users feedback.
|
|
|
|
var TITLE_PRE_AUTH = "Log in with one of the following methods";
|
|
|
|
var TITLE_POST_AUTH = "Logging in...";
|
|
|
|
|
|
|
|
// The cookie used to store the original query parameters when using SSO.
|
|
|
|
var COOKIE_KEY = "synapse_login_fallback_qs";
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Submit a login request.
|
|
|
|
*
|
|
|
|
* type: The login type as a string (e.g. "m.login.foo").
|
|
|
|
* data: An object of data specific to the login type.
|
|
|
|
* extra: (Optional) An object to search for extra information to send with the
|
|
|
|
* login request, e.g. device_id.
|
|
|
|
* callback: (Optional) Function to call on successful login.
|
|
|
|
*/
|
|
|
|
var submitLogin = function(type, data, extra, callback) {
|
|
|
|
console.log("Logging in with " + type);
|
|
|
|
set_title(TITLE_POST_AUTH);
|
|
|
|
|
|
|
|
// Add the login type.
|
|
|
|
data.type = type;
|
|
|
|
|
|
|
|
// Add the device information, if it was provided.
|
|
|
|
if (extra.device_id) {
|
|
|
|
data.device_id = extra.device_id;
|
|
|
|
}
|
|
|
|
if (extra.initial_device_display_name) {
|
|
|
|
data.initial_device_display_name = extra.initial_device_display_name;
|
|
|
|
}
|
2015-10-26 18:35:24 +01:00
|
|
|
|
|
|
|
$.post(matrixLogin.endpoint, JSON.stringify(data), function(response) {
|
2020-06-08 16:13:24 +02:00
|
|
|
if (callback) {
|
|
|
|
callback();
|
|
|
|
}
|
2015-10-26 18:35:24 +01:00
|
|
|
matrixLogin.onLogin(response);
|
2020-04-09 13:23:30 +02:00
|
|
|
}).fail(errorFunc);
|
2015-10-26 18:35:24 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
var errorFunc = function(err) {
|
2020-03-27 15:44:13 +01:00
|
|
|
// We want to show the error to the user rather than redirecting immediately to the
|
|
|
|
// SSO portal (if SSO is the only login option), so we inhibit the redirect.
|
|
|
|
show_login(true);
|
2015-10-26 18:35:24 +01:00
|
|
|
|
|
|
|
if (err.responseJSON && err.responseJSON.error) {
|
|
|
|
setFeedbackString(err.responseJSON.error + " (" + err.responseJSON.errcode + ")");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
setFeedbackString("Request failed: " + err.status);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
var setFeedbackString = function(text) {
|
|
|
|
$("#feedback").text(text);
|
|
|
|
};
|
|
|
|
|
2020-03-27 15:44:13 +01:00
|
|
|
var show_login = function(inhibit_redirect) {
|
2020-06-08 16:13:24 +02:00
|
|
|
// Set the redirect to come back to this page, a login token will get added
|
|
|
|
// and handled after the redirect.
|
2018-11-27 08:51:52 +01:00
|
|
|
var this_page = window.location.origin + window.location.pathname;
|
2019-04-04 13:05:56 +02:00
|
|
|
$("#sso_redirect_url").val(this_page);
|
2018-11-27 08:51:52 +01:00
|
|
|
|
2020-06-08 16:13:24 +02:00
|
|
|
// If inhibit_redirect is false, and SSO is the only supported login method,
|
|
|
|
// we can redirect straight to the SSO page.
|
2020-03-27 15:44:13 +01:00
|
|
|
if (matrixLogin.serverAcceptsSso) {
|
2020-06-08 16:13:24 +02:00
|
|
|
// Before submitting SSO, set the current query parameters into a cookie
|
|
|
|
// for retrieval later.
|
|
|
|
var qs = parseQsFromUrl();
|
|
|
|
setCookie(COOKIE_KEY, JSON.stringify(qs));
|
|
|
|
|
2020-03-27 15:44:13 +01:00
|
|
|
if (!inhibit_redirect && !matrixLogin.serverAcceptsPassword) {
|
|
|
|
$("#sso_form").submit();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, show the SSO form
|
2020-04-07 18:31:50 +02:00
|
|
|
$("#sso_flow").show();
|
2015-10-26 18:35:24 +01:00
|
|
|
}
|
|
|
|
|
2020-03-27 15:44:13 +01:00
|
|
|
if (matrixLogin.serverAcceptsPassword) {
|
|
|
|
$("#password_flow").show();
|
2015-10-26 18:35:24 +01:00
|
|
|
}
|
|
|
|
|
2020-03-27 15:44:13 +01:00
|
|
|
if (!matrixLogin.serverAcceptsPassword && !matrixLogin.serverAcceptsSso) {
|
2015-10-26 18:35:24 +01:00
|
|
|
$("#no_login_types").show();
|
|
|
|
}
|
2020-03-27 15:44:13 +01:00
|
|
|
|
2020-06-08 16:13:24 +02:00
|
|
|
set_title(TITLE_PRE_AUTH);
|
2020-03-27 15:44:13 +01:00
|
|
|
|
|
|
|
$("#loading").hide();
|
2015-10-26 18:35:24 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
var show_spinner = function() {
|
2018-11-27 08:51:52 +01:00
|
|
|
$("#password_flow").hide();
|
|
|
|
$("#sso_flow").hide();
|
2015-10-26 18:35:24 +01:00
|
|
|
$("#no_login_types").hide();
|
|
|
|
$("#loading").show();
|
|
|
|
};
|
|
|
|
|
2020-03-27 15:44:13 +01:00
|
|
|
var set_title = function(title) {
|
|
|
|
$("#title").text(title);
|
|
|
|
};
|
2015-10-26 18:35:24 +01:00
|
|
|
|
|
|
|
var fetch_info = function(cb) {
|
|
|
|
$.get(matrixLogin.endpoint, function(response) {
|
|
|
|
var serverAcceptsPassword = false;
|
|
|
|
for (var i=0; i<response.flows.length; i++) {
|
|
|
|
var flow = response.flows[i];
|
2018-11-27 08:51:52 +01:00
|
|
|
if ("m.login.sso" === flow.type) {
|
|
|
|
matrixLogin.serverAcceptsSso = true;
|
|
|
|
console.log("Server accepts SSO");
|
|
|
|
}
|
2015-10-26 18:35:24 +01:00
|
|
|
if ("m.login.password" === flow.type) {
|
|
|
|
matrixLogin.serverAcceptsPassword = true;
|
|
|
|
console.log("Server accepts password");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cb();
|
2020-04-09 13:23:30 +02:00
|
|
|
}).fail(errorFunc);
|
2015-10-26 18:35:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
matrixLogin.onLoad = function() {
|
|
|
|
fetch_info(function() {
|
2015-11-05 22:32:47 +01:00
|
|
|
if (!try_token()) {
|
2020-03-27 15:44:13 +01:00
|
|
|
show_login(false);
|
2015-10-26 18:35:24 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
matrixLogin.password_login = function() {
|
|
|
|
var user = $("#user_id").val();
|
|
|
|
var pwd = $("#password").val();
|
|
|
|
|
|
|
|
setFeedbackString("");
|
|
|
|
|
|
|
|
show_spinner();
|
2020-06-08 16:13:24 +02:00
|
|
|
submitLogin(
|
|
|
|
"m.login.password",
|
|
|
|
{user: user, password: pwd},
|
|
|
|
parseQsFromUrl());
|
2015-10-26 18:35:24 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
matrixLogin.onLogin = function(response) {
|
|
|
|
// clobber this function
|
2020-04-09 13:38:38 +02:00
|
|
|
console.warn("onLogin - This function should be replaced to proceed.");
|
2015-10-26 18:35:24 +01:00
|
|
|
};
|
|
|
|
|
2020-06-08 16:13:24 +02:00
|
|
|
/*
|
|
|
|
* Process the query parameters from the current URL into an object.
|
|
|
|
*/
|
|
|
|
var parseQsFromUrl = function() {
|
|
|
|
var pos = window.location.href.indexOf("?");
|
|
|
|
if (pos == -1) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
var query = window.location.href.substr(pos + 1);
|
|
|
|
|
2015-10-26 18:35:24 +01:00
|
|
|
var result = {};
|
|
|
|
query.split("&").forEach(function(part) {
|
|
|
|
var item = part.split("=");
|
|
|
|
var key = item[0];
|
|
|
|
var val = item[1];
|
|
|
|
|
|
|
|
if (val) {
|
|
|
|
val = decodeURIComponent(val);
|
|
|
|
}
|
2020-06-08 16:13:24 +02:00
|
|
|
result[key] = val;
|
2015-10-26 18:35:24 +01:00
|
|
|
});
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
|
2020-06-08 16:13:24 +02:00
|
|
|
/*
|
|
|
|
* Process the cookies and return an object.
|
|
|
|
*/
|
|
|
|
var parseCookies = function() {
|
|
|
|
var allCookies = document.cookie;
|
|
|
|
var result = {};
|
|
|
|
allCookies.split(";").forEach(function(part) {
|
|
|
|
var item = part.split("=");
|
|
|
|
// Cookies might have arbitrary whitespace between them.
|
|
|
|
var key = item[0].trim();
|
|
|
|
// You can end up with a broken cookie that doesn't have an equals sign
|
|
|
|
// in it. Set to an empty value.
|
|
|
|
var val = (item[1] || "").trim();
|
|
|
|
// Values might be URI encoded.
|
|
|
|
if (val) {
|
|
|
|
val = decodeURIComponent(val);
|
|
|
|
}
|
|
|
|
result[key] = val;
|
|
|
|
});
|
|
|
|
return result;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set a cookie that is valid for 1 hour.
|
|
|
|
*/
|
|
|
|
var setCookie = function(key, value) {
|
|
|
|
// The maximum age is set in seconds.
|
|
|
|
var maxAge = 60 * 60;
|
|
|
|
// Set the cookie, this defaults to the current domain and path.
|
|
|
|
document.cookie = key + "=" + encodeURIComponent(value) + ";max-age=" + maxAge + ";sameSite=lax";
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Removes a cookie by key.
|
|
|
|
*/
|
|
|
|
var deleteCookie = function(key) {
|
|
|
|
// Delete a cookie by setting the expiration to 0. (Note that the value
|
|
|
|
// doesn't matter.)
|
|
|
|
document.cookie = key + "=deleted;expires=0";
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Submits the login token if one is found in the query parameters. Returns a
|
|
|
|
* boolean of whether the login token was found or not.
|
|
|
|
*/
|
2015-11-05 22:32:47 +01:00
|
|
|
var try_token = function() {
|
2020-06-08 16:13:24 +02:00
|
|
|
// Check if the login token is in the query parameters.
|
|
|
|
var qs = parseQsFromUrl();
|
2015-10-26 18:35:24 +01:00
|
|
|
|
2015-11-05 22:32:47 +01:00
|
|
|
var loginToken = qs.loginToken;
|
|
|
|
if (!loginToken) {
|
2015-10-26 18:35:24 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-06-08 16:13:24 +02:00
|
|
|
// Retrieve the original query parameters (from before the SSO redirect).
|
|
|
|
// They are stored as JSON in a cookie.
|
|
|
|
var cookies = parseCookies();
|
|
|
|
var original_query_params = JSON.parse(cookies[COOKIE_KEY] || "{}")
|
|
|
|
|
|
|
|
// If the login is successful, delete the cookie.
|
|
|
|
var callback = function() {
|
|
|
|
deleteCookie(COOKIE_KEY);
|
|
|
|
}
|
|
|
|
|
|
|
|
submitLogin(
|
|
|
|
"m.login.token",
|
|
|
|
{token: loginToken},
|
|
|
|
original_query_params,
|
|
|
|
callback);
|
2015-10-26 18:35:24 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
};
|