-
Notifications
You must be signed in to change notification settings - Fork 700
/
auth.ts
120 lines (106 loc) · 3.54 KB
/
auth.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Copyright 2018-2022 the Kubeapps contributors.
// SPDX-License-Identifier: Apache-2.0
import { ThunkAction } from "redux-thunk";
import { Auth } from "shared/Auth";
import * as Namespace from "shared/Namespace";
import { IStoreState, UnauthorizedNetworkError } from "shared/types";
import { ActionType, deprecated } from "typesafe-actions";
import { clearClusters, NamespaceAction } from "./namespace";
const { createAction } = deprecated;
export const setAuthenticated = createAction("SET_AUTHENTICATED", resolve => {
return (authenticated: boolean, oidc: boolean) => resolve({ authenticated, oidc });
});
export const authenticating = createAction("AUTHENTICATING");
export const authenticationError = createAction("AUTHENTICATION_ERROR", resolve => {
return (errorMsg: string) => resolve(errorMsg);
});
export const setSessionExpired = createAction("SET_AUTHENTICATION_SESSION_EXPIRED", resolve => {
return (sessionExpired: boolean) => resolve({ sessionExpired });
});
const allActions = [setAuthenticated, authenticating, authenticationError, setSessionExpired];
export type AuthAction = ActionType<typeof allActions[number]>;
export function authenticate(
cluster: string,
token: string,
oidc: boolean,
): ThunkAction<Promise<void>, IStoreState, null, AuthAction> {
return async dispatch => {
dispatch(authenticating());
try {
if (!oidc) {
await Auth.validateToken(cluster, token);
}
Auth.setAuthToken(token, oidc);
dispatch(setAuthenticated(true, oidc));
if (oidc) {
dispatch(setSessionExpired(false));
}
} catch (e: any) {
dispatch(authenticationError(e.toString()));
}
};
}
export function logout(): ThunkAction<
Promise<void>,
IStoreState,
null,
AuthAction | NamespaceAction
> {
return async (dispatch, getState) => {
// We can't do anything before calling unsetAuthCookie as otherwise the
// state changes and the redirect to the logout URI is lost.
if (Auth.usingOIDCToken()) {
const { config } = getState();
Auth.unsetAuthCookie(config);
} else {
Auth.unsetAuthToken();
dispatch(setAuthenticated(false, false));
dispatch(clearClusters());
}
Namespace.unsetStoredNamespace();
};
}
export function logoutByAuthenticationError(): ThunkAction<
Promise<void>,
IStoreState,
null,
AuthAction | NamespaceAction
> {
return async dispatch => {
dispatch(logout());
dispatch(authenticationError("Unauthorized"));
dispatch(expireSession());
};
}
export function handleErrorAction(error: any, action?: ActionType<any>) {
if (error.constructor === UnauthorizedNetworkError) {
return logoutByAuthenticationError();
} else if (action) {
return action;
}
}
export function expireSession(): ThunkAction<Promise<void>, IStoreState, null, AuthAction> {
return async dispatch => {
if (Auth.usingOIDCToken()) {
dispatch(setSessionExpired(true));
}
return dispatch(logout());
};
}
export function checkCookieAuthentication(
cluster: string,
): ThunkAction<Promise<boolean>, IStoreState, null, AuthAction> {
return async dispatch => {
// The call to authenticate below will also dispatch authenticating,
// but we dispatch it early so that the login screen is shown as
// loading while we query isAuthenticatedWithCookie().
dispatch(authenticating());
const isAuthed = await Auth.isAuthenticatedWithCookie(cluster);
if (isAuthed) {
await dispatch(authenticate(cluster, "", true));
} else {
dispatch(setAuthenticated(false, false));
}
return isAuthed;
};
}