Accept device information at the login fallback endpoint. (#7629)

This commit is contained in:
Patrick Cloke 2020-06-08 10:13:24 -04:00 committed by GitHub
parent 737b4a936e
commit 375ca0cceb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 120 additions and 34 deletions

1
changelog.d/7629.bugfix Normal file
View file

@ -0,0 +1 @@
Pass device information through to the login endpoint when using the login fallback.

View file

@ -4,30 +4,41 @@ window.matrixLogin = {
serverAcceptsSso: false, serverAcceptsSso: false,
}; };
var title_pre_auth = "Log in with one of the following methods"; // Titles get updated through the process to give users feedback.
var title_post_auth = "Logging in..."; var TITLE_PRE_AUTH = "Log in with one of the following methods";
var TITLE_POST_AUTH = "Logging in...";
var submitPassword = function(user, pwd) { // The cookie used to store the original query parameters when using SSO.
console.log("Logging in with password..."); var COOKIE_KEY = "synapse_login_fallback_qs";
set_title(title_post_auth);
var data = { /*
type: "m.login.password", * Submit a login request.
user: user, *
password: pwd, * type: The login type as a string (e.g. "m.login.foo").
}; * data: An object of data specific to the login type.
$.post(matrixLogin.endpoint, JSON.stringify(data), function(response) { * extra: (Optional) An object to search for extra information to send with the
matrixLogin.onLogin(response); * login request, e.g. device_id.
}).fail(errorFunc); * 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;
}
var submitToken = function(loginToken) {
console.log("Logging in with login token...");
set_title(title_post_auth);
var data = {
type: "m.login.token",
token: loginToken
};
$.post(matrixLogin.endpoint, JSON.stringify(data), function(response) { $.post(matrixLogin.endpoint, JSON.stringify(data), function(response) {
if (callback) {
callback();
}
matrixLogin.onLogin(response); matrixLogin.onLogin(response);
}).fail(errorFunc); }).fail(errorFunc);
}; };
@ -50,12 +61,19 @@ var setFeedbackString = function(text) {
}; };
var show_login = function(inhibit_redirect) { var show_login = function(inhibit_redirect) {
// Set the redirect to come back to this page, a login token will get added
// and handled after the redirect.
var this_page = window.location.origin + window.location.pathname; var this_page = window.location.origin + window.location.pathname;
$("#sso_redirect_url").val(this_page); $("#sso_redirect_url").val(this_page);
// If inhibit_redirect is false, and SSO is the only supported login method, we can // If inhibit_redirect is false, and SSO is the only supported login method,
// redirect straight to the SSO page // we can redirect straight to the SSO page.
if (matrixLogin.serverAcceptsSso) { if (matrixLogin.serverAcceptsSso) {
// Before submitting SSO, set the current query parameters into a cookie
// for retrieval later.
var qs = parseQsFromUrl();
setCookie(COOKIE_KEY, JSON.stringify(qs));
if (!inhibit_redirect && !matrixLogin.serverAcceptsPassword) { if (!inhibit_redirect && !matrixLogin.serverAcceptsPassword) {
$("#sso_form").submit(); $("#sso_form").submit();
return; return;
@ -73,7 +91,7 @@ var show_login = function(inhibit_redirect) {
$("#no_login_types").show(); $("#no_login_types").show();
} }
set_title(title_pre_auth); set_title(TITLE_PRE_AUTH);
$("#loading").hide(); $("#loading").hide();
}; };
@ -123,7 +141,10 @@ matrixLogin.password_login = function() {
setFeedbackString(""); setFeedbackString("");
show_spinner(); show_spinner();
submitPassword(user, pwd); submitLogin(
"m.login.password",
{user: user, password: pwd},
parseQsFromUrl());
}; };
matrixLogin.onLogin = function(response) { matrixLogin.onLogin = function(response) {
@ -131,7 +152,16 @@ matrixLogin.onLogin = function(response) {
console.warn("onLogin - This function should be replaced to proceed."); console.warn("onLogin - This function should be replaced to proceed.");
}; };
var parseQsFromUrl = function(query) { /*
* 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);
var result = {}; var result = {};
query.split("&").forEach(function(part) { query.split("&").forEach(function(part) {
var item = part.split("="); var item = part.split("=");
@ -141,25 +171,80 @@ var parseQsFromUrl = function(query) {
if (val) { if (val) {
val = decodeURIComponent(val); val = decodeURIComponent(val);
} }
result[key] = val result[key] = val;
}); });
return result; return result;
}; };
/*
* 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.
*/
var try_token = function() { var try_token = function() {
var pos = window.location.href.indexOf("?"); // Check if the login token is in the query parameters.
if (pos == -1) { var qs = parseQsFromUrl();
return false;
}
var qs = parseQsFromUrl(window.location.href.substr(pos+1));
var loginToken = qs.loginToken; var loginToken = qs.loginToken;
if (!loginToken) { if (!loginToken) {
return false; return false;
} }
submitToken(loginToken); // 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);
return true; return true;
}; };