@vocollege/app 0.0.171 → 0.0.173
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/global.d.ts +8 -7
- package/dist/interceptor.js +71 -50
- package/dist/modules/Services/I18n/strings.json +2 -1
- package/dist/modules/Services/Vapor/Vapor.js +4 -4
- package/dist/modules/VoApi/GraphClient.js +1 -1
- package/dist/modules/VoApi/VoApi.d.ts +1 -1
- package/dist/modules/VoApi/VoApi.js +1 -1
- package/dist/modules/VoAuth.d.ts +2 -0
- package/dist/modules/VoAuth.js +62 -27
- package/dist/modules/VoConfig.d.ts +1 -1
- package/dist/modules/VoConfig.js +1 -0
- package/dist/modules/VoDocs/VoDocs.d.ts +1 -1
- package/dist/modules/VoDocs/VoDocs.js +4 -4
- package/dist/modules/VoHelpers.d.ts +4 -4
- package/dist/modules/VoHelpers.js +2 -2
- package/dist/modules/VoRouter.d.ts +1 -1
- package/dist/modules/VoUtils_REMOVE.d.ts +2 -2
- package/package.json +4 -3
- package/src/global.ts +1 -0
- package/src/interceptor.ts +60 -31
- package/src/modules/Services/I18n/strings.json +2 -1
- package/src/modules/VoAuth.ts +61 -31
- package/src/modules/VoConfig.ts +1 -0
package/dist/global.d.ts
CHANGED
|
@@ -1,39 +1,40 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type AuthStorageConfigType = {
|
|
2
2
|
STATE: string;
|
|
3
3
|
VERIFIER: string;
|
|
4
4
|
REFRESH_TOKEN: string;
|
|
5
5
|
ACCESS_TOKEN: string;
|
|
6
6
|
TOKEN_TYPE: string;
|
|
7
7
|
};
|
|
8
|
-
export
|
|
8
|
+
export type AuthConfigType = {
|
|
9
9
|
BASE_URL: string;
|
|
10
10
|
CLIENT_ID?: string;
|
|
11
11
|
LOGIN?: string;
|
|
12
12
|
ENDPOINT?: string;
|
|
13
13
|
STORAGE?: AuthStorageConfigType;
|
|
14
14
|
};
|
|
15
|
-
export
|
|
15
|
+
export type ApiConfigType = {
|
|
16
16
|
BASE_URL: string;
|
|
17
17
|
ENDPOINT?: string;
|
|
18
18
|
GRAPHQL?: string;
|
|
19
19
|
};
|
|
20
|
-
export
|
|
20
|
+
export type AppConfigType = {
|
|
21
21
|
BASE_URL: string;
|
|
22
22
|
AUTH?: string;
|
|
23
23
|
HOME?: string;
|
|
24
24
|
LOGIN?: string;
|
|
25
25
|
};
|
|
26
|
-
export
|
|
26
|
+
export type VoAppType = {
|
|
27
27
|
configure: Function;
|
|
28
28
|
config?: Function;
|
|
29
29
|
auth: any;
|
|
30
30
|
api: any;
|
|
31
31
|
};
|
|
32
|
-
export
|
|
32
|
+
export type VoTokenType = {
|
|
33
33
|
access_token: string;
|
|
34
34
|
refresh_token: string;
|
|
35
|
+
expiry_token: string;
|
|
35
36
|
};
|
|
36
37
|
export interface GeneralObject {
|
|
37
38
|
[key: string]: any;
|
|
38
39
|
}
|
|
39
|
-
export
|
|
40
|
+
export type TypeNullObject = null | GeneralObject;
|
package/dist/interceptor.js
CHANGED
|
@@ -14,7 +14,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
14
14
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
15
|
function step(op) {
|
|
16
16
|
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (_) try {
|
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
18
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
19
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
20
|
switch (op[0]) {
|
|
@@ -46,76 +46,97 @@ var react_toastify_1 = require("react-toastify");
|
|
|
46
46
|
var js_cookie_1 = __importDefault(require("js-cookie"));
|
|
47
47
|
// Custom.
|
|
48
48
|
var I18n_1 = __importDefault(require("./modules/Services/I18n"));
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
switch (_a.label) {
|
|
56
|
-
case 0:
|
|
57
|
-
_a.trys.push([0, 2, , 3]);
|
|
58
|
-
//console.log("@vocollege/api->interceptor.ts->redirect()");
|
|
59
|
-
js_cookie_1.default.set("voapp_redirectTo", window.location.origin, {
|
|
60
|
-
domain: ".vo-college.se",
|
|
61
|
-
sameSite: "Lax",
|
|
62
|
-
});
|
|
63
|
-
return [4 /*yield*/, VoAuth_1.default.logout()];
|
|
64
|
-
case 1:
|
|
65
|
-
_a.sent();
|
|
66
|
-
VoRouter_1.default.redirectToLogout();
|
|
67
|
-
return [3 /*break*/, 3];
|
|
68
|
-
case 2:
|
|
69
|
-
error_1 = _a.sent();
|
|
70
|
-
console.error("Interceptor", error_1);
|
|
71
|
-
VoAuth_1.default.resetSession();
|
|
72
|
-
return [3 /*break*/, 3];
|
|
73
|
-
case 3: return [2 /*return*/];
|
|
74
|
-
}
|
|
75
|
-
});
|
|
49
|
+
var isRefreshingToken = false;
|
|
50
|
+
var failedRequestQueue = [];
|
|
51
|
+
function retryFailedRequests() {
|
|
52
|
+
if (failedRequestQueue.length && !isRefreshingToken) {
|
|
53
|
+
failedRequestQueue.forEach(function (request) {
|
|
54
|
+
axios_1.default.request(request);
|
|
76
55
|
});
|
|
56
|
+
failedRequestQueue = [];
|
|
77
57
|
}
|
|
78
|
-
|
|
58
|
+
}
|
|
59
|
+
function redirect() {
|
|
60
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
61
|
+
var error_1;
|
|
62
|
+
return __generator(this, function (_a) {
|
|
63
|
+
switch (_a.label) {
|
|
64
|
+
case 0:
|
|
65
|
+
_a.trys.push([0, 2, , 3]);
|
|
66
|
+
js_cookie_1.default.set("voapp_redirectTo", window.location.origin, {
|
|
67
|
+
domain: ".vo-college.se",
|
|
68
|
+
sameSite: "Lax",
|
|
69
|
+
});
|
|
70
|
+
return [4 /*yield*/, VoAuth_1.default.logout()];
|
|
71
|
+
case 1:
|
|
72
|
+
_a.sent();
|
|
73
|
+
VoRouter_1.default.redirectToLogout();
|
|
74
|
+
return [3 /*break*/, 3];
|
|
75
|
+
case 2:
|
|
76
|
+
error_1 = _a.sent();
|
|
77
|
+
console.error("Interceptor", error_1);
|
|
78
|
+
VoAuth_1.default.resetSession();
|
|
79
|
+
return [3 /*break*/, 3];
|
|
80
|
+
case 3: return [2 /*return*/];
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
(function () {
|
|
86
|
+
var _this = this;
|
|
79
87
|
axios_1.default.defaults.withCredentials = true;
|
|
80
88
|
axios_1.default.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
|
|
81
89
|
axios_1.default.interceptors.request.use(function (req) {
|
|
82
|
-
|
|
90
|
+
var token = VoAuth_1.default.getToken();
|
|
91
|
+
if (!req.headers.Authorization && token) {
|
|
92
|
+
req.headers.Authorization = "Bearer ".concat(token.access_token);
|
|
93
|
+
}
|
|
83
94
|
return req;
|
|
84
95
|
});
|
|
85
96
|
axios_1.default.interceptors.response.use(function (res) {
|
|
86
97
|
return res;
|
|
87
98
|
}, function (error) { return __awaiter(_this, void 0, void 0, function () {
|
|
88
|
-
var config, isTokenRequest,
|
|
99
|
+
var config, isTokenRequest, newToken, refreshError_1, error_2;
|
|
89
100
|
var _a;
|
|
90
101
|
return __generator(this, function (_b) {
|
|
91
102
|
switch (_b.label) {
|
|
92
103
|
case 0:
|
|
93
104
|
config = error.config;
|
|
94
105
|
isTokenRequest = config.url.includes("oauth/token");
|
|
106
|
+
if (isTokenRequest) {
|
|
107
|
+
react_toastify_1.toast.error(I18n_1.default.get.messages.sessionExpired, { autoClose: false });
|
|
108
|
+
redirect();
|
|
109
|
+
return [2 /*return*/, Promise.reject(error)];
|
|
110
|
+
}
|
|
95
111
|
_b.label = 1;
|
|
96
112
|
case 1:
|
|
97
|
-
_b.trys.push([1,
|
|
98
|
-
if (!(
|
|
99
|
-
|
|
100
|
-
|
|
113
|
+
_b.trys.push([1, 7, , 8]);
|
|
114
|
+
if (![400, 401, 403].includes((_a = error.response) === null || _a === void 0 ? void 0 : _a.status)) return [3 /*break*/, 6];
|
|
115
|
+
if (!(!isRefreshingToken && !config._retry)) return [3 /*break*/, 6];
|
|
116
|
+
isRefreshingToken = true;
|
|
117
|
+
config._retry = true;
|
|
118
|
+
_b.label = 2;
|
|
101
119
|
case 2:
|
|
102
|
-
_b.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
case 3: return [3 /*break*/, 5];
|
|
120
|
+
_b.trys.push([2, 4, 5, 6]);
|
|
121
|
+
return [4 /*yield*/, VoAuth_1.default.refreshToken()];
|
|
122
|
+
case 3:
|
|
123
|
+
newToken = _b.sent();
|
|
124
|
+
config.headers.Authorization = "Bearer ".concat(newToken === null || newToken === void 0 ? void 0 : newToken.access_token);
|
|
125
|
+
retryFailedRequests();
|
|
126
|
+
return [2 /*return*/, (0, axios_1.default)(config)];
|
|
110
127
|
case 4:
|
|
111
|
-
|
|
112
|
-
|
|
128
|
+
refreshError_1 = _b.sent();
|
|
129
|
+
redirect();
|
|
130
|
+
return [2 /*return*/, Promise.reject(refreshError_1)];
|
|
113
131
|
case 5:
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
132
|
+
isRefreshingToken = false;
|
|
133
|
+
return [7 /*endfinally*/];
|
|
134
|
+
case 6: return [3 /*break*/, 8];
|
|
135
|
+
case 7:
|
|
136
|
+
error_2 = _b.sent();
|
|
137
|
+
console.error("Interceptor error:", error_2);
|
|
138
|
+
return [3 /*break*/, 8];
|
|
139
|
+
case 8: return [2 /*return*/, Promise.reject(error)];
|
|
119
140
|
}
|
|
120
141
|
});
|
|
121
142
|
}); });
|
|
@@ -1054,7 +1054,8 @@
|
|
|
1054
1054
|
"createLanguageRepresentativeDiploma": "Skapa diplom för språkombud",
|
|
1055
1055
|
"place": "Region/Ort",
|
|
1056
1056
|
"educator1": "Utbildare 1",
|
|
1057
|
-
"educator2": "Utbildare 2"
|
|
1057
|
+
"educator2": "Utbildare 2",
|
|
1058
|
+
"educator3": "Utbildare 3"
|
|
1058
1059
|
},
|
|
1059
1060
|
"messages": {
|
|
1060
1061
|
"intro": "För diplom till de som genomgått utbildning till språkombud.",
|
|
@@ -28,7 +28,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
28
28
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
29
29
|
function step(op) {
|
|
30
30
|
if (f) throw new TypeError("Generator is already executing.");
|
|
31
|
-
while (_) try {
|
|
31
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
32
32
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
33
33
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
34
34
|
switch (op[0]) {
|
|
@@ -69,10 +69,10 @@ var Vapor = /** @class */ (function () {
|
|
|
69
69
|
/**
|
|
70
70
|
* Store a file in S3 and return its UUID, key, and other information.
|
|
71
71
|
*/
|
|
72
|
-
Vapor.prototype.store = function (
|
|
73
|
-
|
|
74
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
72
|
+
Vapor.prototype.store = function (file_1) {
|
|
73
|
+
return __awaiter(this, arguments, void 0, function (file, options) {
|
|
75
74
|
var response, instance, headers, cancelToken;
|
|
75
|
+
if (options === void 0) { options = {}; }
|
|
76
76
|
return __generator(this, function (_a) {
|
|
77
77
|
switch (_a.label) {
|
|
78
78
|
case 0: return [4 /*yield*/, axios_1.default.post(
|
|
@@ -25,7 +25,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
25
25
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
26
|
function step(op) {
|
|
27
27
|
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
-
while (_) try {
|
|
28
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
29
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
30
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
31
|
switch (op[0]) {
|
|
@@ -6,7 +6,7 @@ declare class VoApi extends VoBase {
|
|
|
6
6
|
init(params?: GeneralObject): void;
|
|
7
7
|
get getGraphqlUrl(): string;
|
|
8
8
|
get getGraphqlSubscriptionUrl(): string;
|
|
9
|
-
getUser(): Promise<import("axios").AxiosResponse<any>>;
|
|
9
|
+
getUser(): Promise<import("axios").AxiosResponse<any, any>>;
|
|
10
10
|
logout(): Promise<boolean>;
|
|
11
11
|
}
|
|
12
12
|
declare const _default: VoApi;
|
|
@@ -29,7 +29,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
29
29
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
30
30
|
function step(op) {
|
|
31
31
|
if (f) throw new TypeError("Generator is already executing.");
|
|
32
|
-
while (_) try {
|
|
32
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
33
33
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
34
34
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
35
35
|
switch (op[0]) {
|
package/dist/modules/VoAuth.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ declare class VoAuth extends VoBase {
|
|
|
8
8
|
user: any;
|
|
9
9
|
ability: AnyMongoAbility;
|
|
10
10
|
globalAbility: AnyMongoAbility;
|
|
11
|
+
tokenRefreshTimeout: any;
|
|
11
12
|
constructor(key: string);
|
|
12
13
|
get getAppLoginUrl(): string;
|
|
13
14
|
auth(): Promise<unknown>;
|
|
@@ -16,6 +17,7 @@ declare class VoAuth extends VoBase {
|
|
|
16
17
|
setSession(token: any, updateCookie?: boolean): void;
|
|
17
18
|
resetSession(): void;
|
|
18
19
|
refreshToken(): Promise<void | VoTokenType>;
|
|
20
|
+
startTokenRefreshTimer(): void;
|
|
19
21
|
check(forceRedirect?: boolean, forceLoad?: boolean): Promise<any>;
|
|
20
22
|
loadUser(force?: boolean): Promise<any>;
|
|
21
23
|
get currentUser(): any;
|
package/dist/modules/VoAuth.js
CHANGED
|
@@ -52,7 +52,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
52
52
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
53
53
|
function step(op) {
|
|
54
54
|
if (f) throw new TypeError("Generator is already executing.");
|
|
55
|
-
while (_) try {
|
|
55
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
56
56
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
57
57
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
58
58
|
switch (op[0]) {
|
|
@@ -121,6 +121,7 @@ var VoAuth = /** @class */ (function (_super) {
|
|
|
121
121
|
var _this = this;
|
|
122
122
|
return new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
|
|
123
123
|
var urlParams, code, state, initiatedAuth, params, url, response, state_1, verifier, error_1;
|
|
124
|
+
var _this = this;
|
|
124
125
|
return __generator(this, function (_a) {
|
|
125
126
|
switch (_a.label) {
|
|
126
127
|
case 0:
|
|
@@ -159,6 +160,8 @@ var VoAuth = /** @class */ (function (_super) {
|
|
|
159
160
|
return [4 /*yield*/, this.loadUser(true)];
|
|
160
161
|
case 3:
|
|
161
162
|
_a.sent();
|
|
163
|
+
this.startTokenRefreshTimer();
|
|
164
|
+
window.addEventListener("beforeunload", function () { return clearTimeout(_this.tokenRefreshTimeout); });
|
|
162
165
|
resolve(true);
|
|
163
166
|
return [3 /*break*/, 5];
|
|
164
167
|
case 4:
|
|
@@ -198,33 +201,34 @@ var VoAuth = /** @class */ (function (_super) {
|
|
|
198
201
|
};
|
|
199
202
|
VoAuth.prototype.setSession = function (token, updateCookie) {
|
|
200
203
|
if (updateCookie === void 0) { updateCookie = true; }
|
|
201
|
-
|
|
202
|
-
var access_token = token.access_token, refresh_token = token.refresh_token;
|
|
204
|
+
var access_token = token.access_token, refresh_token = token.refresh_token, expires_in = token.expires_in;
|
|
203
205
|
if (updateCookie) {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
+
//console.log("setSession updatingCookie");
|
|
207
|
+
var expiryTime = new Date().getTime() + (expires_in || 3600) * 1000;
|
|
208
|
+
js_cookie_1.default.set(VoConfig_1.default.get.AUTH_STORAGE_EXPIRE_TOKEN || "", expiryTime.toString(), {
|
|
209
|
+
expires: 21,
|
|
210
|
+
sameSite: "Lax",
|
|
211
|
+
domain: VoConfig_1.default.get.AUTH_DOMAIN,
|
|
212
|
+
});
|
|
213
|
+
js_cookie_1.default.set(VoConfig_1.default.get.AUTH_STORAGE_REFRESH_TOKEN || "", refresh_token, {
|
|
206
214
|
expires: 21,
|
|
207
215
|
sameSite: "Lax",
|
|
208
216
|
domain: VoConfig_1.default.get.AUTH_DOMAIN,
|
|
209
217
|
});
|
|
210
218
|
var expires = new Date(new Date().getTime() + 4 * 60 * 60 * 1000);
|
|
211
|
-
|
|
212
|
-
js_cookie_1.default.set(accessTokenKey, access_token, {
|
|
219
|
+
js_cookie_1.default.set(VoConfig_1.default.get.AUTH_STORAGE_ACCESS_TOKEN || "", access_token, {
|
|
213
220
|
expires: expires,
|
|
214
221
|
sameSite: "Lax",
|
|
215
222
|
domain: VoConfig_1.default.get.AUTH_DOMAIN,
|
|
216
223
|
});
|
|
217
224
|
}
|
|
218
|
-
axios_1.default.defaults.headers.common["Authorization"] =
|
|
219
|
-
// token_type + " " + access_token;
|
|
220
|
-
"Bearer " + access_token;
|
|
225
|
+
axios_1.default.defaults.headers.common["Authorization"] = "Bearer " + access_token;
|
|
221
226
|
var currentGroup = VoGroups_1.default.getCurrent(true);
|
|
222
|
-
axios_1.default.defaults.headers.common["VoGroup"] = currentGroup
|
|
223
|
-
|
|
224
|
-
: "";
|
|
227
|
+
axios_1.default.defaults.headers.common["VoGroup"] = currentGroup ? currentGroup.id : "";
|
|
228
|
+
this.startTokenRefreshTimer();
|
|
225
229
|
};
|
|
226
230
|
VoAuth.prototype.resetSession = function () {
|
|
227
|
-
console.log("Resetting session");
|
|
231
|
+
//console.log("Resetting session");
|
|
228
232
|
var refreshTokenKey = VoConfig_1.default.get.AUTH_STORAGE_REFRESH_TOKEN || "";
|
|
229
233
|
Helpers.localStorage.remove(refreshTokenKey);
|
|
230
234
|
js_cookie_1.default.remove(refreshTokenKey, {
|
|
@@ -277,13 +281,47 @@ var VoAuth = /** @class */ (function (_super) {
|
|
|
277
281
|
});
|
|
278
282
|
});
|
|
279
283
|
};
|
|
284
|
+
VoAuth.prototype.startTokenRefreshTimer = function () {
|
|
285
|
+
var _this = this;
|
|
286
|
+
var expiresAt = js_cookie_1.default.get(VoConfig_1.default.get.AUTH_STORAGE_EXPIRE_TOKEN);
|
|
287
|
+
if (!expiresAt)
|
|
288
|
+
return;
|
|
289
|
+
var expiresInMs = parseInt(expiresAt) - (new Date().getTime());
|
|
290
|
+
var refreshAt = expiresInMs - (30 * 1000); // 30 sec before expiration
|
|
291
|
+
clearTimeout(this.tokenRefreshTimeout);
|
|
292
|
+
this.tokenRefreshTimeout = setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
293
|
+
var newToken, error_3;
|
|
294
|
+
return __generator(this, function (_a) {
|
|
295
|
+
switch (_a.label) {
|
|
296
|
+
case 0:
|
|
297
|
+
_a.trys.push([0, 2, , 3]);
|
|
298
|
+
return [4 /*yield*/, this.refreshToken()];
|
|
299
|
+
case 1:
|
|
300
|
+
newToken = _a.sent();
|
|
301
|
+
this.setSession(newToken);
|
|
302
|
+
this.startTokenRefreshTimer();
|
|
303
|
+
return [3 /*break*/, 3];
|
|
304
|
+
case 2:
|
|
305
|
+
error_3 = _a.sent();
|
|
306
|
+
console.error("Token refresh failed:", error_3);
|
|
307
|
+
this.resetSession();
|
|
308
|
+
if (window.location.pathname !== "/login") {
|
|
309
|
+
window.location.href = "/login";
|
|
310
|
+
}
|
|
311
|
+
return [3 /*break*/, 3];
|
|
312
|
+
case 3: return [2 /*return*/];
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
}); }, refreshAt);
|
|
316
|
+
//console.log("Setting token refresh timeout in: ", refreshAt);
|
|
317
|
+
};
|
|
280
318
|
VoAuth.prototype.check = function (forceRedirect, forceLoad) {
|
|
281
319
|
var _this = this;
|
|
282
320
|
if (forceRedirect === void 0) { forceRedirect = false; }
|
|
283
321
|
if (forceLoad === void 0) { forceLoad = false; }
|
|
284
322
|
this.checkConfig();
|
|
285
323
|
return new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
|
|
286
|
-
var currentCookies, cookieName, token,
|
|
324
|
+
var currentCookies, cookieName, token, error_4;
|
|
287
325
|
return __generator(this, function (_a) {
|
|
288
326
|
switch (_a.label) {
|
|
289
327
|
case 0:
|
|
@@ -314,8 +352,8 @@ var VoAuth = /** @class */ (function (_super) {
|
|
|
314
352
|
resolve(this.user);
|
|
315
353
|
return [3 /*break*/, 4];
|
|
316
354
|
case 3:
|
|
317
|
-
|
|
318
|
-
reject(
|
|
355
|
+
error_4 = _a.sent();
|
|
356
|
+
reject(error_4);
|
|
319
357
|
return [3 /*break*/, 4];
|
|
320
358
|
case 4: return [3 /*break*/, 6];
|
|
321
359
|
case 5:
|
|
@@ -335,7 +373,7 @@ var VoAuth = /** @class */ (function (_super) {
|
|
|
335
373
|
var _this = this;
|
|
336
374
|
if (force === void 0) { force = false; }
|
|
337
375
|
return new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
|
|
338
|
-
var response,
|
|
376
|
+
var response, error_5;
|
|
339
377
|
return __generator(this, function (_a) {
|
|
340
378
|
switch (_a.label) {
|
|
341
379
|
case 0:
|
|
@@ -354,8 +392,8 @@ var VoAuth = /** @class */ (function (_super) {
|
|
|
354
392
|
resolve(this.user);
|
|
355
393
|
return [3 /*break*/, 4];
|
|
356
394
|
case 3:
|
|
357
|
-
|
|
358
|
-
reject(
|
|
395
|
+
error_5 = _a.sent();
|
|
396
|
+
reject(error_5);
|
|
359
397
|
return [3 /*break*/, 4];
|
|
360
398
|
case 4: return [2 /*return*/];
|
|
361
399
|
}
|
|
@@ -382,10 +420,9 @@ var VoAuth = /** @class */ (function (_super) {
|
|
|
382
420
|
});
|
|
383
421
|
VoAuth.prototype.getToken = function () {
|
|
384
422
|
try {
|
|
385
|
-
var
|
|
386
|
-
var
|
|
387
|
-
var
|
|
388
|
-
var accessToken = js_cookie_1.default.get(accessTokenKey);
|
|
423
|
+
var refreshToken = js_cookie_1.default.get(VoConfig_1.default.get.AUTH_STORAGE_REFRESH_TOKEN || "");
|
|
424
|
+
var accessToken = js_cookie_1.default.get(VoConfig_1.default.get.AUTH_STORAGE_ACCESS_TOKEN || "");
|
|
425
|
+
var expiryToken = js_cookie_1.default.get(VoConfig_1.default.get.AUTH_STORAGE_EXPIRE_TOKEN || "");
|
|
389
426
|
// let tokenTypeKey = VoConfig.get.AUTH_STORAGE_TOKEN_TYPE || "";
|
|
390
427
|
// const tokenType = JsCookies.get(tokenTypeKey);
|
|
391
428
|
// let expiresInKey = VoConfig.get.AUTH_STORAGE_EXPIRES_IN || "";
|
|
@@ -395,6 +432,7 @@ var VoAuth = /** @class */ (function (_super) {
|
|
|
395
432
|
return {
|
|
396
433
|
refresh_token: refreshToken,
|
|
397
434
|
access_token: accessToken || "",
|
|
435
|
+
expiry_token: expiryToken || "",
|
|
398
436
|
// token_type: tokenType,
|
|
399
437
|
// expires_in: expiresIn,
|
|
400
438
|
};
|
|
@@ -404,9 +442,6 @@ var VoAuth = /** @class */ (function (_super) {
|
|
|
404
442
|
throw error;
|
|
405
443
|
}
|
|
406
444
|
};
|
|
407
|
-
// const getLoginUrl = () => {
|
|
408
|
-
// return 'http://localhost:8000/oauth/authorize?client_id=91c51b49-e705-4993-a8c7-497ee47e869e&redirect_uri=http://localhost:3000/auth&response_type=code&scope=*&state=' + state + '&code_challenge=' + challenge + '&code_challenge_method=S256'
|
|
409
|
-
// }
|
|
410
445
|
VoAuth.prototype.initAuth = function () {
|
|
411
446
|
try {
|
|
412
447
|
var state = Helpers.createRandomString(40);
|
package/dist/modules/VoConfig.js
CHANGED
|
@@ -47,6 +47,7 @@ var VoConfig = /** @class */ (function () {
|
|
|
47
47
|
AUTH_STORAGE_VERIFIER: "vo_verifier",
|
|
48
48
|
AUTH_STORAGE_REFRESH_TOKEN: "vo_rtoken",
|
|
49
49
|
AUTH_STORAGE_ACCESS_TOKEN: "vo_atoken",
|
|
50
|
+
AUTH_STORAGE_EXPIRE_TOKEN: "vo_etoken",
|
|
50
51
|
// AUTH_STORAGE_TOKEN_TYPE: "voapp_tokentype",
|
|
51
52
|
// AUTH_STORAGE_EXPIRES_IN: "voapp_expiresin",
|
|
52
53
|
AUTH_DOMAIN: ".vo-college.se",
|
|
@@ -3,7 +3,7 @@ declare class VoDocs extends VoBase {
|
|
|
3
3
|
graphqlClient: any;
|
|
4
4
|
init(): void;
|
|
5
5
|
get getGraphqlUrl(): string;
|
|
6
|
-
getTemporaryFileUrl(id: string, publicDownload?: boolean): Promise<import("axios").AxiosResponse<any>>;
|
|
6
|
+
getTemporaryFileUrl(id: string, publicDownload?: boolean): Promise<import("axios").AxiosResponse<any, any>>;
|
|
7
7
|
}
|
|
8
8
|
declare const _default: VoDocs;
|
|
9
9
|
export default _default;
|
|
@@ -29,7 +29,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
29
29
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
30
30
|
function step(op) {
|
|
31
31
|
if (f) throw new TypeError("Generator is already executing.");
|
|
32
|
-
while (_) try {
|
|
32
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
33
33
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
34
34
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
35
35
|
switch (op[0]) {
|
|
@@ -77,10 +77,10 @@ var VoDocs = /** @class */ (function (_super) {
|
|
|
77
77
|
enumerable: false,
|
|
78
78
|
configurable: true
|
|
79
79
|
});
|
|
80
|
-
VoDocs.prototype.getTemporaryFileUrl = function (
|
|
81
|
-
|
|
82
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
80
|
+
VoDocs.prototype.getTemporaryFileUrl = function (id_1) {
|
|
81
|
+
return __awaiter(this, arguments, void 0, function (id, publicDownload) {
|
|
83
82
|
var currentGroup, endpoint, url;
|
|
83
|
+
if (publicDownload === void 0) { publicDownload = false; }
|
|
84
84
|
return __generator(this, function (_a) {
|
|
85
85
|
try {
|
|
86
86
|
currentGroup = VoGroups_1.default.getCurrent(true);
|
|
@@ -7,7 +7,7 @@ export declare const localStorage: {
|
|
|
7
7
|
get: (key: string) => string | false | null;
|
|
8
8
|
remove: (key: string) => true | undefined;
|
|
9
9
|
};
|
|
10
|
-
|
|
10
|
+
type encodeQueryDataType = {
|
|
11
11
|
[key: string]: any;
|
|
12
12
|
};
|
|
13
13
|
export declare const encodeQueryData: (data: encodeQueryDataType) => string;
|
|
@@ -20,7 +20,7 @@ export declare const regexPatterns: {
|
|
|
20
20
|
personalNumber: RegExp;
|
|
21
21
|
orgnr: RegExp;
|
|
22
22
|
};
|
|
23
|
-
|
|
23
|
+
type errorObjectType = {
|
|
24
24
|
message: string;
|
|
25
25
|
fields?: {
|
|
26
26
|
[key: string]: any;
|
|
@@ -33,8 +33,8 @@ export declare const wrapPromise: (promise: any) => {
|
|
|
33
33
|
read: () => any;
|
|
34
34
|
};
|
|
35
35
|
export declare const downloadFile: (url: string) => void;
|
|
36
|
-
export declare const orderByPosition: (a: any, b: any) =>
|
|
37
|
-
export declare const orderByField: (a: any, b: any, field: string, descending?: boolean) =>
|
|
36
|
+
export declare const orderByPosition: (a: any, b: any) => 0 | 1 | -1;
|
|
37
|
+
export declare const orderByField: (a: any, b: any, field: string, descending?: boolean) => 0 | 1 | -1;
|
|
38
38
|
export declare const shortenText: (str: string, limit?: number, stripHtml?: boolean, addEllipsis?: boolean) => string;
|
|
39
39
|
export declare const getImageContact: (item: any, width?: number, height?: number) => string;
|
|
40
40
|
export declare const getImage: (item: any, width: number, height: number, field?: string) => string;
|
|
@@ -25,7 +25,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
25
25
|
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
26
|
function step(op) {
|
|
27
27
|
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
-
while (_) try {
|
|
28
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
29
|
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
30
|
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
31
|
switch (op[0]) {
|
|
@@ -121,7 +121,7 @@ exports.regexPatterns = {
|
|
|
121
121
|
username: /(^[a-z]{3,})([\.]|[\_]|[\-]|[a-z]|[0-9]?)+$/,
|
|
122
122
|
email: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
|
|
123
123
|
stringNonDigit: /^[^0-9]+$/,
|
|
124
|
-
password: /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[a-zA-Z]).{8,}$/,
|
|
124
|
+
password: /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[a-zA-Z]).{8,}$/, // At least 8 characters, 1 uppercase, 1 lowercase and 1 digit.
|
|
125
125
|
cleanName: /(^[a-z]{1,})(\w|-?)+$/,
|
|
126
126
|
personalNumber: /^(\d{8})[-]\d{4}$/,
|
|
127
127
|
orgnr: /^(\d{6})[-]\d{4}$/,
|
|
@@ -6,7 +6,7 @@ declare const localStorage: {
|
|
|
6
6
|
get: (key: string) => string | false | null;
|
|
7
7
|
remove: (key: string) => true | undefined;
|
|
8
8
|
};
|
|
9
|
-
|
|
9
|
+
type encodeQueryDataType = {
|
|
10
10
|
[key: string]: any;
|
|
11
11
|
};
|
|
12
12
|
declare const encodeQueryData: (data: encodeQueryDataType) => string;
|
|
@@ -16,7 +16,7 @@ declare const regexPatterns: {
|
|
|
16
16
|
stringNonDigit: RegExp;
|
|
17
17
|
password: RegExp;
|
|
18
18
|
};
|
|
19
|
-
|
|
19
|
+
type errorObjectType = {
|
|
20
20
|
message: string;
|
|
21
21
|
fields?: {
|
|
22
22
|
[key: string]: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vocollege/app",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.173",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"@apollo/client": "^3.10.5",
|
|
14
14
|
"@casl/ability": "^6.7.1",
|
|
15
15
|
"@casl/react": "^4.0.0",
|
|
16
|
-
"
|
|
16
|
+
"apollo-upload-client": "^16.0.0",
|
|
17
17
|
"@types/crypto-js": "^4.2.2",
|
|
18
18
|
"@types/he": "^1.2.3",
|
|
19
19
|
"@types/js-cookie": "^3.0.6",
|
|
@@ -41,5 +41,6 @@
|
|
|
41
41
|
"js-cookie": "^3.0.1",
|
|
42
42
|
"react": "^18.3.1",
|
|
43
43
|
"react-toastify": "^8.0.0"
|
|
44
|
-
}
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {}
|
|
45
46
|
}
|
package/src/global.ts
CHANGED
package/src/interceptor.ts
CHANGED
|
@@ -7,28 +7,41 @@ import Cookies from "js-cookie";
|
|
|
7
7
|
// Custom.
|
|
8
8
|
import I18n from "./modules/Services/I18n";
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
VoRouter.redirectToLogout();
|
|
20
|
-
} catch (error) {
|
|
21
|
-
console.error("Interceptor", error);
|
|
22
|
-
VoAuth.resetSession();
|
|
23
|
-
}
|
|
10
|
+
let isRefreshingToken = false;
|
|
11
|
+
let failedRequestQueue: any[] = [];
|
|
12
|
+
|
|
13
|
+
function retryFailedRequests() {
|
|
14
|
+
if (failedRequestQueue.length && !isRefreshingToken) {
|
|
15
|
+
failedRequestQueue.forEach((request) => {
|
|
16
|
+
axios.request(request);
|
|
17
|
+
});
|
|
18
|
+
failedRequestQueue = [];
|
|
24
19
|
}
|
|
20
|
+
}
|
|
25
21
|
|
|
26
|
-
|
|
22
|
+
async function redirect() {
|
|
23
|
+
try {
|
|
24
|
+
Cookies.set("voapp_redirectTo", window.location.origin, {
|
|
25
|
+
domain: ".vo-college.se",
|
|
26
|
+
sameSite: "Lax",
|
|
27
|
+
});
|
|
28
|
+
await VoAuth.logout();
|
|
29
|
+
VoRouter.redirectToLogout();
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.error("Interceptor", error);
|
|
32
|
+
VoAuth.resetSession();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
(function () {
|
|
27
37
|
axios.defaults.withCredentials = true;
|
|
28
38
|
axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
|
|
29
39
|
|
|
30
40
|
axios.interceptors.request.use((req) => {
|
|
31
|
-
|
|
41
|
+
const token = VoAuth.getToken();
|
|
42
|
+
if (!req.headers.Authorization && token) {
|
|
43
|
+
req.headers.Authorization = `Bearer ${token.access_token}`;
|
|
44
|
+
}
|
|
32
45
|
return req;
|
|
33
46
|
});
|
|
34
47
|
|
|
@@ -39,28 +52,44 @@ import I18n from "./modules/Services/I18n";
|
|
|
39
52
|
async (error) => {
|
|
40
53
|
const { config } = error;
|
|
41
54
|
let isTokenRequest = config.url.includes("oauth/token");
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
55
|
+
|
|
56
|
+
if (isTokenRequest) {
|
|
57
|
+
toast.error(I18n.get.messages.sessionExpired, { autoClose: false });
|
|
58
|
+
redirect();
|
|
59
|
+
return Promise.reject(error);
|
|
60
|
+
}
|
|
61
|
+
|
|
46
62
|
try {
|
|
47
|
-
if (
|
|
48
|
-
!
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
63
|
+
if ([400, 401, 403].includes(error.response?.status)) {
|
|
64
|
+
if (!isRefreshingToken && !config._retry) {
|
|
65
|
+
isRefreshingToken = true;
|
|
66
|
+
config._retry = true;
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
const newToken = await VoAuth.refreshToken();
|
|
70
|
+
config.headers.Authorization = `Bearer ${newToken?.access_token}`;
|
|
71
|
+
retryFailedRequests();
|
|
72
|
+
return axios(config);
|
|
73
|
+
} catch (refreshError) {
|
|
74
|
+
redirect();
|
|
75
|
+
return Promise.reject(refreshError);
|
|
76
|
+
} finally {
|
|
77
|
+
isRefreshingToken = false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/*await VoAuth.refreshToken();
|
|
52
82
|
const token: any = VoAuth.getToken();
|
|
53
83
|
if (token) {
|
|
54
84
|
config.headers["Authorization"] = "Bearer " + token.access_token;
|
|
55
85
|
return axios.request(config);
|
|
56
86
|
}
|
|
57
|
-
}
|
|
58
|
-
} catch (error) {
|
|
59
|
-
|
|
60
|
-
if (isTokenRequest) {
|
|
61
|
-
toast.error(I18n.get.messages.sessionExpired, { autoClose: false });
|
|
62
|
-
redirect();
|
|
87
|
+
}*/
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error("Interceptor error:", error);
|
|
63
90
|
}
|
|
91
|
+
|
|
92
|
+
|
|
64
93
|
return Promise.reject(error);
|
|
65
94
|
},
|
|
66
95
|
);
|
|
@@ -1054,7 +1054,8 @@
|
|
|
1054
1054
|
"createLanguageRepresentativeDiploma": "Skapa diplom för språkombud",
|
|
1055
1055
|
"place": "Region/Ort",
|
|
1056
1056
|
"educator1": "Utbildare 1",
|
|
1057
|
-
"educator2": "Utbildare 2"
|
|
1057
|
+
"educator2": "Utbildare 2",
|
|
1058
|
+
"educator3": "Utbildare 3"
|
|
1058
1059
|
},
|
|
1059
1060
|
"messages": {
|
|
1060
1061
|
"intro": "För diplom till de som genomgått utbildning till språkombud.",
|
package/src/modules/VoAuth.ts
CHANGED
|
@@ -18,6 +18,7 @@ class VoAuth extends VoBase {
|
|
|
18
18
|
user: any = null;
|
|
19
19
|
ability: AnyMongoAbility;
|
|
20
20
|
globalAbility: AnyMongoAbility;
|
|
21
|
+
tokenRefreshTimeout: any;
|
|
21
22
|
|
|
22
23
|
constructor(key: string) {
|
|
23
24
|
super(key);
|
|
@@ -76,6 +77,8 @@ class VoAuth extends VoBase {
|
|
|
76
77
|
|
|
77
78
|
this.setSession(response.data);
|
|
78
79
|
await this.loadUser(true);
|
|
80
|
+
this.startTokenRefreshTimer();
|
|
81
|
+
window.addEventListener("beforeunload", () => clearTimeout(this.tokenRefreshTimeout));
|
|
79
82
|
resolve(true);
|
|
80
83
|
} else {
|
|
81
84
|
reject("Authorization failed");
|
|
@@ -99,44 +102,48 @@ class VoAuth extends VoBase {
|
|
|
99
102
|
}
|
|
100
103
|
|
|
101
104
|
setSession(token: any, updateCookie = true) {
|
|
102
|
-
|
|
103
|
-
const { access_token, refresh_token } = token;
|
|
105
|
+
const { access_token, refresh_token, expires_in } = token;
|
|
104
106
|
|
|
105
107
|
if (updateCookie) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
+
|
|
109
|
+
//console.log("setSession updatingCookie");
|
|
110
|
+
const expiryTime = new Date().getTime() + (expires_in || 3600) * 1000;
|
|
111
|
+
JsCookies.set(VoConfig.get.AUTH_STORAGE_EXPIRE_TOKEN || "", expiryTime.toString(), {
|
|
112
|
+
expires: 21,
|
|
113
|
+
sameSite: "Lax",
|
|
114
|
+
domain: VoConfig.get.AUTH_DOMAIN,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
JsCookies.set(VoConfig.get.AUTH_STORAGE_REFRESH_TOKEN || "", refresh_token, {
|
|
108
118
|
expires: 21,
|
|
109
119
|
sameSite: "Lax",
|
|
110
120
|
domain: VoConfig.get.AUTH_DOMAIN,
|
|
111
121
|
});
|
|
112
122
|
|
|
113
123
|
let expires = new Date(new Date().getTime() + 4 * 60 * 60 * 1000);
|
|
114
|
-
|
|
115
|
-
JsCookies.set(accessTokenKey, access_token, {
|
|
124
|
+
JsCookies.set(VoConfig.get.AUTH_STORAGE_ACCESS_TOKEN || "", access_token, {
|
|
116
125
|
expires,
|
|
117
126
|
sameSite: "Lax",
|
|
118
127
|
domain: VoConfig.get.AUTH_DOMAIN,
|
|
119
128
|
});
|
|
120
129
|
}
|
|
121
130
|
|
|
122
|
-
axios.defaults.headers.common["Authorization"] =
|
|
123
|
-
// token_type + " " + access_token;
|
|
124
|
-
"Bearer " + access_token;
|
|
131
|
+
axios.defaults.headers.common["Authorization"] = "Bearer " + access_token;
|
|
125
132
|
let currentGroup = VoGroups.getCurrent(true);
|
|
126
|
-
axios.defaults.headers.common["VoGroup"] = currentGroup
|
|
127
|
-
|
|
128
|
-
: "";
|
|
133
|
+
axios.defaults.headers.common["VoGroup"] = currentGroup ? currentGroup.id : "";
|
|
134
|
+
this.startTokenRefreshTimer();
|
|
129
135
|
}
|
|
136
|
+
|
|
130
137
|
resetSession() {
|
|
131
|
-
console.log("Resetting session");
|
|
132
|
-
|
|
138
|
+
//console.log("Resetting session");
|
|
139
|
+
const refreshTokenKey = VoConfig.get.AUTH_STORAGE_REFRESH_TOKEN || "";
|
|
133
140
|
Helpers.localStorage.remove(refreshTokenKey);
|
|
134
141
|
JsCookies.remove(refreshTokenKey, {
|
|
135
142
|
domain: VoConfig.get.AUTH_DOMAIN,
|
|
136
143
|
sameSite: "Lax",
|
|
137
144
|
});
|
|
138
145
|
|
|
139
|
-
|
|
146
|
+
const accessTokenKey = VoConfig.get.AUTH_STORAGE_ACCESS_TOKEN || "";
|
|
140
147
|
Helpers.localStorage.remove(accessTokenKey);
|
|
141
148
|
JsCookies.remove(accessTokenKey, {
|
|
142
149
|
domain: VoConfig.get.AUTH_DOMAIN,
|
|
@@ -149,6 +156,7 @@ class VoAuth extends VoBase {
|
|
|
149
156
|
|
|
150
157
|
delete axios.defaults.headers.common["Authorization"];
|
|
151
158
|
}
|
|
159
|
+
|
|
152
160
|
async refreshToken() {
|
|
153
161
|
try {
|
|
154
162
|
const token: any = this.getToken();
|
|
@@ -175,6 +183,29 @@ class VoAuth extends VoBase {
|
|
|
175
183
|
}
|
|
176
184
|
}
|
|
177
185
|
|
|
186
|
+
startTokenRefreshTimer() {
|
|
187
|
+
const expiresAt = JsCookies.get(VoConfig.get.AUTH_STORAGE_EXPIRE_TOKEN);
|
|
188
|
+
if (!expiresAt) return;
|
|
189
|
+
|
|
190
|
+
const expiresInMs = parseInt(expiresAt) - (new Date().getTime());
|
|
191
|
+
const refreshAt = expiresInMs - (30 * 1000); // 30 sec before expiration
|
|
192
|
+
clearTimeout(this.tokenRefreshTimeout);
|
|
193
|
+
this.tokenRefreshTimeout = setTimeout(async () => {
|
|
194
|
+
try {
|
|
195
|
+
const newToken = await this.refreshToken();
|
|
196
|
+
this.setSession(newToken);
|
|
197
|
+
this.startTokenRefreshTimer();
|
|
198
|
+
} catch (error) {
|
|
199
|
+
console.error("Token refresh failed:", error);
|
|
200
|
+
this.resetSession();
|
|
201
|
+
if (window.location.pathname !== "/login") {
|
|
202
|
+
window.location.href = "/login";
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}, refreshAt);
|
|
206
|
+
//console.log("Setting token refresh timeout in: ", refreshAt);
|
|
207
|
+
}
|
|
208
|
+
|
|
178
209
|
check(forceRedirect = false, forceLoad = false): Promise<any> {
|
|
179
210
|
this.checkConfig();
|
|
180
211
|
return new Promise(async (resolve, reject) => {
|
|
@@ -214,6 +245,7 @@ class VoAuth extends VoBase {
|
|
|
214
245
|
}
|
|
215
246
|
});
|
|
216
247
|
}
|
|
248
|
+
|
|
217
249
|
loadUser(force = false): Promise<any> {
|
|
218
250
|
return new Promise(async (resolve, reject) => {
|
|
219
251
|
try {
|
|
@@ -231,9 +263,11 @@ class VoAuth extends VoBase {
|
|
|
231
263
|
}
|
|
232
264
|
});
|
|
233
265
|
}
|
|
266
|
+
|
|
234
267
|
get currentUser() {
|
|
235
268
|
return this.user;
|
|
236
269
|
}
|
|
270
|
+
|
|
237
271
|
get isOnlyValidigCandidate() {
|
|
238
272
|
if (this.user?.validig) {
|
|
239
273
|
return this.user?.roles?.length == 1 && this.user?.roles.find((r: any) => r.name ==="candidate");
|
|
@@ -243,11 +277,9 @@ class VoAuth extends VoBase {
|
|
|
243
277
|
|
|
244
278
|
getToken(): VoTokenType | void {
|
|
245
279
|
try {
|
|
246
|
-
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
let accessTokenKey = VoConfig.get.AUTH_STORAGE_ACCESS_TOKEN || "";
|
|
250
|
-
const accessToken = JsCookies.get(accessTokenKey);
|
|
280
|
+
const refreshToken = JsCookies.get(VoConfig.get.AUTH_STORAGE_REFRESH_TOKEN || "");
|
|
281
|
+
const accessToken = JsCookies.get(VoConfig.get.AUTH_STORAGE_ACCESS_TOKEN || "");
|
|
282
|
+
const expiryToken = JsCookies.get(VoConfig.get.AUTH_STORAGE_EXPIRE_TOKEN || "");
|
|
251
283
|
|
|
252
284
|
// let tokenTypeKey = VoConfig.get.AUTH_STORAGE_TOKEN_TYPE || "";
|
|
253
285
|
// const tokenType = JsCookies.get(tokenTypeKey);
|
|
@@ -260,6 +292,7 @@ class VoAuth extends VoBase {
|
|
|
260
292
|
return {
|
|
261
293
|
refresh_token: refreshToken,
|
|
262
294
|
access_token: accessToken || "",
|
|
295
|
+
expiry_token: expiryToken || "",
|
|
263
296
|
// token_type: tokenType,
|
|
264
297
|
// expires_in: expiresIn,
|
|
265
298
|
};
|
|
@@ -269,17 +302,13 @@ class VoAuth extends VoBase {
|
|
|
269
302
|
}
|
|
270
303
|
}
|
|
271
304
|
|
|
272
|
-
// const getLoginUrl = () => {
|
|
273
|
-
// return 'http://localhost:8000/oauth/authorize?client_id=91c51b49-e705-4993-a8c7-497ee47e869e&redirect_uri=http://localhost:3000/auth&response_type=code&scope=*&state=' + state + '&code_challenge=' + challenge + '&code_challenge_method=S256'
|
|
274
|
-
// }
|
|
275
|
-
|
|
276
305
|
initAuth(): { state: string; challenge: string } {
|
|
277
306
|
try {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
307
|
+
const state = Helpers.createRandomString(40);
|
|
308
|
+
const verifier = Helpers.createRandomString(128);
|
|
309
|
+
const challenge = Helpers.base64Url(crypto.SHA256(verifier));
|
|
281
310
|
|
|
282
|
-
|
|
311
|
+
const stateKey = VoConfig.get.AUTH_STORAGE_STATE || "";
|
|
283
312
|
Helpers.localStorage.remove(stateKey);
|
|
284
313
|
JsCookies.set(stateKey, state, {
|
|
285
314
|
expires: 1,
|
|
@@ -287,7 +316,7 @@ class VoAuth extends VoBase {
|
|
|
287
316
|
domain: VoConfig.get.AUTH_DOMAIN,
|
|
288
317
|
});
|
|
289
318
|
|
|
290
|
-
|
|
319
|
+
const verifierKey = VoConfig.get.AUTH_STORAGE_VERIFIER || "";
|
|
291
320
|
Helpers.localStorage.remove(verifierKey);
|
|
292
321
|
JsCookies.set(verifierKey, verifier, {
|
|
293
322
|
expires: 1,
|
|
@@ -295,7 +324,7 @@ class VoAuth extends VoBase {
|
|
|
295
324
|
domain: VoConfig.get.AUTH_DOMAIN,
|
|
296
325
|
});
|
|
297
326
|
|
|
298
|
-
|
|
327
|
+
const accessTokenKey = VoConfig.get.AUTH_STORAGE_ACCESS_TOKEN || "";
|
|
299
328
|
Helpers.localStorage.remove(accessTokenKey);
|
|
300
329
|
JsCookies.remove(accessTokenKey, {
|
|
301
330
|
domain: VoConfig.get.AUTH_DOMAIN,
|
|
@@ -303,7 +332,7 @@ class VoAuth extends VoBase {
|
|
|
303
332
|
expires: 1,
|
|
304
333
|
});
|
|
305
334
|
|
|
306
|
-
|
|
335
|
+
const refreshTokenKey = VoConfig.get.AUTH_STORAGE_REFRESH_TOKEN || "";
|
|
307
336
|
Helpers.localStorage.remove(refreshTokenKey);
|
|
308
337
|
JsCookies.remove(refreshTokenKey, {
|
|
309
338
|
domain: VoConfig.get.AUTH_DOMAIN,
|
|
@@ -327,6 +356,7 @@ class VoAuth extends VoBase {
|
|
|
327
356
|
throw error;
|
|
328
357
|
}
|
|
329
358
|
}
|
|
359
|
+
|
|
330
360
|
getInitiatedAuth(): { state: string; verifier: string } {
|
|
331
361
|
let stateKey = VoConfig.get.AUTH_STORAGE_STATE || "";
|
|
332
362
|
// const state = Helpers.localStorage.get(stateKey);
|
package/src/modules/VoConfig.ts
CHANGED
|
@@ -47,6 +47,7 @@ class VoConfig {
|
|
|
47
47
|
AUTH_STORAGE_VERIFIER: "vo_verifier",
|
|
48
48
|
AUTH_STORAGE_REFRESH_TOKEN: "vo_rtoken",
|
|
49
49
|
AUTH_STORAGE_ACCESS_TOKEN: "vo_atoken",
|
|
50
|
+
AUTH_STORAGE_EXPIRE_TOKEN: "vo_etoken",
|
|
50
51
|
// AUTH_STORAGE_TOKEN_TYPE: "voapp_tokentype",
|
|
51
52
|
// AUTH_STORAGE_EXPIRES_IN: "voapp_expiresin",
|
|
52
53
|
AUTH_DOMAIN: ".vo-college.se",
|