Skip to content

Commit 59a5c9d

Browse files
authored
Fix login and logout flow for MCS (#185)
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)
1 parent 1e7f272 commit 59a5c9d

File tree

5 files changed

+45
-20
lines changed

5 files changed

+45
-20
lines changed

portal-ui/src/common/api/index.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import storage from "local-storage-fallback";
1818
import request from "superagent";
1919
import get from "lodash/get";
20+
import { clearSession } from "../utils";
2021

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

4953
return Promise.reject(throwMessage);
5054
} else {
51-
return Promise.reject("Unknown error");
55+
clearSession();
56+
window.location.href = "/login";
5257
}
5358
}
5459
}

portal-ui/src/common/utils.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
// You should have received a copy of the GNU Affero General Public License
1515
// along with this program. If not, see <http://www.gnu.org/licenses/>.
1616

17+
import storage from "local-storage-fallback";
18+
1719
export const units = [
1820
"B",
1921
"KiB",
@@ -50,6 +52,20 @@ export const setCookie = (name: string, val: string) => {
5052
name + "=" + value + "; expires=" + date.toUTCString() + "; path=/";
5153
};
5254

55+
export const deleteCookie = (name: string) => {
56+
document.cookie = name + "=; expires=Thu, 01 Jan 1970 00:00:01 GMT;";
57+
};
58+
59+
export const setSession = (token: string) => {
60+
setCookie("token", token);
61+
storage.setItem("token", token);
62+
};
63+
64+
export const clearSession = () => {
65+
storage.removeItem("token");
66+
deleteCookie("token");
67+
};
68+
5369
// timeFromdate gets time string from date input
5470
export const timeFromDate = (d: Date) => {
5571
let h = d.getHours() < 10 ? `0${d.getHours()}` : `${d.getHours()}`;

portal-ui/src/screens/Console/Console.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ import ListTenants from "./Tenants/ListTenants/ListTenants";
6868
import { ISessionResponse } from "./types";
6969
import { saveSessionResponse } from "./actions";
7070
import TenantDetails from "./Tenants/TenantDetails/TenantDetails";
71+
import { clearSession } from "../../common/utils";
7172

7273
function Copyright() {
7374
return (
@@ -206,9 +207,12 @@ const Console = ({
206207
.then((res) => {
207208
saveSessionResponse(res);
208209
})
209-
.catch((err) => {
210-
storage.removeItem("token");
211-
history.push("/");
210+
.catch(() => {
211+
// if server returns 401 for /api/v1/session call invoke function will internally call clearSession()
212+
// and redirecto to window.location.href = "/"; and this code will be not reached
213+
// in case that not happen we clear session here and redirect as well
214+
clearSession();
215+
window.location.href = "/login";
212216
});
213217
}, [saveSessionResponse]);
214218

portal-ui/src/screens/Console/Menu/Menu.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import {
5050
UsersIcon,
5151
WarpIcon,
5252
} from "../../../icons";
53+
import { clearSession } from "../../../common/utils";
5354

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

157158
const logout = () => {
158159
const deleteSession = () => {
159-
storage.removeItem("token");
160+
clearSession();
160161
userLoggedIn(false);
161-
history.push("/");
162+
history.push("/login");
162163
};
163164
api
164165
.invoke("POST", `/api/v1/logout`)

portal-ui/src/screens/LoginPage/LoginPage.tsx

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ import { SystemState } from "../../types";
2828
import { userLoggedIn } from "../../actions";
2929
import api from "../../common/api";
3030
import { ILoginDetails, loginStrategyType } from "./types";
31-
import { setCookie } from "../../common/utils";
31+
import { setSession } from "../../common/utils";
32+
import history from "../../history";
3233

3334
const styles = (theme: Theme) =>
3435
createStyles({
@@ -120,13 +121,13 @@ const Login = ({ classes, userLoggedIn }: ILoginProps) => {
120121
});
121122

122123
const loginStrategyEndpoints: LoginStrategyRoutes = {
123-
"form": "/api/v1/login",
124+
form: "/api/v1/login",
124125
"service-account": "/api/v1/login/mkube",
125-
}
126+
};
126127
const loginStrategyPayload: LoginStrategyPayload = {
127-
"form": { accessKey, secretKey },
128+
form: { accessKey, secretKey },
128129
"service-account": { jwt },
129-
}
130+
};
130131

131132
const fetchConfiguration = () => {
132133
setLoading(true);
@@ -147,15 +148,15 @@ const Login = ({ classes, userLoggedIn }: ILoginProps) => {
147148
const formSubmit = (e: React.FormEvent<HTMLFormElement>) => {
148149
e.preventDefault();
149150
request
150-
.post(loginStrategyEndpoints[loginStrategy.loginStrategy] || "/api/v1/login")
151+
.post(
152+
loginStrategyEndpoints[loginStrategy.loginStrategy] || "/api/v1/login"
153+
)
151154
.send(loginStrategyPayload[loginStrategy.loginStrategy])
152155
.then((res: any) => {
153156
const bodyResponse = res.body;
154157
if (bodyResponse.sessionId) {
155158
// store the jwt token
156-
setCookie("token", bodyResponse.sessionId);
157-
storage.setItem("token", bodyResponse.sessionId);
158-
//return res.body.sessionId;
159+
setSession(bodyResponse.sessionId);
159160
} else if (bodyResponse.error) {
160161
// throw will be moved to catch block once bad login returns 403
161162
throw bodyResponse.error;
@@ -164,9 +165,7 @@ const Login = ({ classes, userLoggedIn }: ILoginProps) => {
164165
.then(() => {
165166
// We set the state in redux
166167
userLoggedIn(true);
167-
// There is a browser cache issue if we change the policy associated to an account and then logout and history.push("/") after login
168-
// therefore after login we need to use window.location redirect
169-
window.location.href = "/";
168+
history.push("/");
170169
})
171170
.catch((err) => {
172171
setError(err.message);

0 commit comments

Comments
 (0)