Skip to content

Commit

Permalink
Fix login and logout flow for MCS
Browse files Browse the repository at this point in the history
fixes: #184

There was a bug in Safari in related to the browser not setting the session token
correctly in localstorage, this was because we were using
window.location.href for redirect instead of history.push after login, the redirect execution was faster
was faster that the promise function getting the response after the login request
and it seems to be that Safari will kill all current request of a
window when the page is getting redirected.

Test this:

Try to sign-in using Safari browser (latest version is recommended)
  • Loading branch information
Alevsk committed Jun 30, 2020
1 parent 1e7f272 commit 9e3fa27
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 18 deletions.
11 changes: 8 additions & 3 deletions portal-ui/src/common/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import storage from "local-storage-fallback";
import request from "superagent";
import get from "lodash/get";
import { clearSession } from "../utils";

export class API {
invoke(method: string, url: string, data?: object) {
Expand All @@ -28,8 +29,11 @@ export class API {
.catch((err) => {
// if we get unauthorized, kick out the user
if (err.status === 401) {
storage.removeItem("token");
window.location.href = "/";
clearSession();
// Refresh the whole page to ensure cache is clear
// and we dont end on an infinite loop
window.location.href = "/login";
return;
}
return this.onError(err);
});
Expand All @@ -48,7 +52,8 @@ export class API {

return Promise.reject(throwMessage);
} else {
return Promise.reject("Unknown error");
clearSession();
window.location.href = "/login";
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions portal-ui/src/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

import storage from "local-storage-fallback";

export const units = [
"B",
"KiB",
Expand Down Expand Up @@ -50,6 +52,20 @@ export const setCookie = (name: string, val: string) => {
name + "=" + value + "; expires=" + date.toUTCString() + "; path=/";
};

export const deleteCookie = (name: string) => {
document.cookie = name + "=; expires=Thu, 01 Jan 1970 00:00:01 GMT;";
};

export const setSession = (token: string) => {
setCookie("token", token);
storage.setItem("token", token);
};

export const clearSession = () => {
storage.removeItem("token");
deleteCookie("token");
};

// timeFromdate gets time string from date input
export const timeFromDate = (d: Date) => {
let h = d.getHours() < 10 ? `0${d.getHours()}` : `${d.getHours()}`;
Expand Down
10 changes: 7 additions & 3 deletions portal-ui/src/screens/Console/Console.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import ListTenants from "./Tenants/ListTenants/ListTenants";
import { ISessionResponse } from "./types";
import { saveSessionResponse } from "./actions";
import TenantDetails from "./Tenants/TenantDetails/TenantDetails";
import { clearSession } from "../../common/utils";

function Copyright() {
return (
Expand Down Expand Up @@ -206,9 +207,12 @@ const Console = ({
.then((res) => {
saveSessionResponse(res);
})
.catch((err) => {
storage.removeItem("token");
history.push("/");
.catch(() => {
// if server returns 401 for /api/v1/session call invoke function will internally call call clearSession()
// and redirecto to window.location.href = "/"; and this code will be not reached
// in case that not happen we clear session here and redirect as well
clearSession();
window.location.href = "/login";
});
}, [saveSessionResponse]);

Expand Down
5 changes: 3 additions & 2 deletions portal-ui/src/screens/Console/Menu/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import {
UsersIcon,
WarpIcon,
} from "../../../icons";
import { clearSession } from "../../../common/utils";

const styles = (theme: Theme) =>
createStyles({
Expand Down Expand Up @@ -156,9 +157,9 @@ const Menu = ({ userLoggedIn, classes, pages }: IMenuProps) => {

const logout = () => {
const deleteSession = () => {
storage.removeItem("token");
clearSession();
userLoggedIn(false);
history.push("/");
history.push("/login");
};
api
.invoke("POST", `/api/v1/logout`)
Expand Down
22 changes: 12 additions & 10 deletions portal-ui/src/screens/LoginPage/LoginPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ import { SystemState } from "../../types";
import { userLoggedIn } from "../../actions";
import api from "../../common/api";
import { ILoginDetails, loginStrategyType } from "./types";
import { setCookie } from "../../common/utils";
import { setSession } from "../../common/utils";
import history from "../../history";

const styles = (theme: Theme) =>
createStyles({
Expand Down Expand Up @@ -120,13 +121,13 @@ const Login = ({ classes, userLoggedIn }: ILoginProps) => {
});

const loginStrategyEndpoints: LoginStrategyRoutes = {
"form": "/api/v1/login",
form: "/api/v1/login",
"service-account": "/api/v1/login/mkube",
}
};
const loginStrategyPayload: LoginStrategyPayload = {
"form": { accessKey, secretKey },
form: { accessKey, secretKey },
"service-account": { jwt },
}
};

const fetchConfiguration = () => {
setLoading(true);
Expand All @@ -147,15 +148,15 @@ const Login = ({ classes, userLoggedIn }: ILoginProps) => {
const formSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
request
.post(loginStrategyEndpoints[loginStrategy.loginStrategy] || "/api/v1/login")
.post(
loginStrategyEndpoints[loginStrategy.loginStrategy] || "/api/v1/login"
)
.send(loginStrategyPayload[loginStrategy.loginStrategy])
.then((res: any) => {
const bodyResponse = res.body;
if (bodyResponse.sessionId) {
// store the jwt token
setCookie("token", bodyResponse.sessionId);
storage.setItem("token", bodyResponse.sessionId);
//return res.body.sessionId;
setSession(bodyResponse.sessionId);
} else if (bodyResponse.error) {
// throw will be moved to catch block once bad login returns 403
throw bodyResponse.error;
Expand All @@ -166,7 +167,8 @@ const Login = ({ classes, userLoggedIn }: ILoginProps) => {
userLoggedIn(true);
// There is a browser cache issue if we change the policy associated to an account and then logout and history.push("/") after login
// therefore after login we need to use window.location redirect
window.location.href = "/";
// window.location.href = "/";
history.push("/");
})
.catch((err) => {
setError(err.message);
Expand Down

0 comments on commit 9e3fa27

Please sign in to comment.