authscape 1.0.710 → 1.0.714
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/index.js +125 -61
- package/package.json +1 -1
- package/src/components/AuthScapeApp.js +153 -59
package/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
4
3
|
Object.defineProperty(exports, "__esModule", {
|
|
5
4
|
value: true
|
|
6
5
|
});
|
|
@@ -30,6 +29,50 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
|
|
|
30
29
|
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
31
30
|
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
32
31
|
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
32
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
33
|
+
// ---- optional: import your cookie util if not global ----
|
|
34
|
+
// import { setCookie } from "cookies-next";
|
|
35
|
+
// import { apiService } from "@/services/api"; // wherever yours lives
|
|
36
|
+
|
|
37
|
+
// Decorate a user object with role/permission helpers (idempotent)
|
|
38
|
+
function ensureUserHelpers(u) {
|
|
39
|
+
if (!u || _typeof(u) !== "object") return u;
|
|
40
|
+
|
|
41
|
+
// Avoid redefining on every call
|
|
42
|
+
if (typeof u.hasRole === "function" && typeof u.hasRoleId === "function" && typeof u.hasPermission === "function") {
|
|
43
|
+
return u;
|
|
44
|
+
}
|
|
45
|
+
var rolesArr = Array.isArray(u.roles) ? u.roles : [];
|
|
46
|
+
var permsArr = Array.isArray(u.permissions) ? u.permissions : [];
|
|
47
|
+
|
|
48
|
+
// defineProperty keeps them non-enumerable
|
|
49
|
+
Object.defineProperty(u, "hasRole", {
|
|
50
|
+
value: function hasRole(name) {
|
|
51
|
+
if (!name) return false;
|
|
52
|
+
return rolesArr.some(function (r) {
|
|
53
|
+
return (r === null || r === void 0 ? void 0 : r.name) === name;
|
|
54
|
+
});
|
|
55
|
+
},
|
|
56
|
+
writable: false
|
|
57
|
+
});
|
|
58
|
+
Object.defineProperty(u, "hasRoleId", {
|
|
59
|
+
value: function hasRoleId(id) {
|
|
60
|
+
if (id === undefined || id === null) return false;
|
|
61
|
+
return rolesArr.some(function (r) {
|
|
62
|
+
return (r === null || r === void 0 ? void 0 : r.id) === id;
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
writable: false
|
|
66
|
+
});
|
|
67
|
+
Object.defineProperty(u, "hasPermission", {
|
|
68
|
+
value: function hasPermission(name) {
|
|
69
|
+
if (!name) return false;
|
|
70
|
+
return permsArr.includes(name);
|
|
71
|
+
},
|
|
72
|
+
writable: false
|
|
73
|
+
});
|
|
74
|
+
return u;
|
|
75
|
+
}
|
|
33
76
|
function AuthScapeApp(_ref) {
|
|
34
77
|
var Component = _ref.Component,
|
|
35
78
|
layout = _ref.layout,
|
|
@@ -60,95 +103,103 @@ function AuthScapeApp(_ref) {
|
|
|
60
103
|
var queryCodeUsed = (0, _react.useRef)(null);
|
|
61
104
|
var ga4React = (0, _react.useRef)(null);
|
|
62
105
|
var searchParams = (0, _navigation.useSearchParams)();
|
|
63
|
-
var queryCode = searchParams.get(
|
|
106
|
+
var queryCode = searchParams.get("code");
|
|
64
107
|
var pathname = (0, _navigation.usePathname)();
|
|
65
108
|
|
|
66
|
-
//
|
|
109
|
+
// ----- PKCE Sign-in (browser-only) -----
|
|
67
110
|
var signInValidator = /*#__PURE__*/function () {
|
|
68
|
-
var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(
|
|
69
|
-
var codeVerifier, headers,
|
|
111
|
+
var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(codeFromQuery) {
|
|
112
|
+
var codeVerifier, headers, body, response, domainHost, redirectUri;
|
|
70
113
|
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
71
114
|
while (1) switch (_context.prev = _context.next) {
|
|
72
115
|
case 0:
|
|
73
|
-
if (!(queryCodeUsed.current ===
|
|
116
|
+
if (!(queryCodeUsed.current === codeFromQuery)) {
|
|
74
117
|
_context.next = 2;
|
|
75
118
|
break;
|
|
76
119
|
}
|
|
77
120
|
return _context.abrupt("return");
|
|
78
121
|
case 2:
|
|
79
|
-
queryCodeUsed.current =
|
|
122
|
+
queryCodeUsed.current = codeFromQuery;
|
|
123
|
+
if (!(typeof window === "undefined")) {
|
|
124
|
+
_context.next = 5;
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
return _context.abrupt("return");
|
|
128
|
+
case 5:
|
|
80
129
|
codeVerifier = window.localStorage.getItem("verifier");
|
|
81
|
-
if (!(!
|
|
82
|
-
_context.next =
|
|
130
|
+
if (!(!codeFromQuery || !codeVerifier)) {
|
|
131
|
+
_context.next = 8;
|
|
83
132
|
break;
|
|
84
133
|
}
|
|
85
134
|
return _context.abrupt("return");
|
|
86
|
-
case
|
|
135
|
+
case 8:
|
|
87
136
|
headers = {
|
|
88
|
-
|
|
137
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
89
138
|
};
|
|
90
|
-
|
|
91
|
-
code:
|
|
139
|
+
body = _queryString["default"].stringify({
|
|
140
|
+
code: codeFromQuery,
|
|
92
141
|
grant_type: "authorization_code",
|
|
93
142
|
redirect_uri: window.location.origin + "/signin-oidc",
|
|
94
143
|
client_id: process.env.client_id,
|
|
95
144
|
client_secret: process.env.client_secret,
|
|
96
145
|
code_verifier: codeVerifier
|
|
97
146
|
});
|
|
98
|
-
_context.prev =
|
|
99
|
-
_context.next =
|
|
100
|
-
return _axios["default"].post(process.env.authorityUri +
|
|
147
|
+
_context.prev = 10;
|
|
148
|
+
_context.next = 13;
|
|
149
|
+
return _axios["default"].post(process.env.authorityUri + "/connect/token", body, {
|
|
101
150
|
headers: headers
|
|
102
151
|
});
|
|
103
|
-
case
|
|
152
|
+
case 13:
|
|
104
153
|
response = _context.sent;
|
|
105
|
-
domainHost = window.location.hostname.split(
|
|
154
|
+
domainHost = window.location.hostname.split(".").slice(-2).join(".");
|
|
106
155
|
window.localStorage.removeItem("verifier");
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
maxAge: 60 * 60 * 24 * 365,
|
|
110
|
-
path: '/',
|
|
111
|
-
domain: domainHost,
|
|
112
|
-
secure: true
|
|
113
|
-
});
|
|
114
|
-
case 16:
|
|
156
|
+
|
|
157
|
+
// NOTE: replace setCookie below with your implementation if different
|
|
115
158
|
_context.next = 18;
|
|
116
|
-
return setCookie(
|
|
159
|
+
return setCookie("access_token", response.data.access_token, {
|
|
117
160
|
maxAge: 60 * 60 * 24 * 365,
|
|
118
|
-
path:
|
|
161
|
+
path: "/",
|
|
119
162
|
domain: domainHost,
|
|
120
163
|
secure: true
|
|
121
164
|
});
|
|
122
165
|
case 18:
|
|
123
166
|
_context.next = 20;
|
|
124
|
-
return setCookie(
|
|
167
|
+
return setCookie("expires_in", response.data.expires_in, {
|
|
125
168
|
maxAge: 60 * 60 * 24 * 365,
|
|
126
|
-
path:
|
|
169
|
+
path: "/",
|
|
127
170
|
domain: domainHost,
|
|
128
171
|
secure: true
|
|
129
172
|
});
|
|
130
173
|
case 20:
|
|
131
|
-
|
|
132
|
-
|
|
174
|
+
_context.next = 22;
|
|
175
|
+
return setCookie("refresh_token", response.data.refresh_token, {
|
|
176
|
+
maxAge: 60 * 60 * 24 * 365,
|
|
177
|
+
path: "/",
|
|
178
|
+
domain: domainHost,
|
|
179
|
+
secure: true
|
|
180
|
+
});
|
|
181
|
+
case 22:
|
|
182
|
+
redirectUri = window.localStorage.getItem("redirectUri");
|
|
183
|
+
window.localStorage.clear();
|
|
133
184
|
window.location.href = redirectUri || "/";
|
|
134
|
-
_context.next =
|
|
185
|
+
_context.next = 30;
|
|
135
186
|
break;
|
|
136
|
-
case
|
|
137
|
-
_context.prev =
|
|
138
|
-
_context.t0 = _context["catch"](
|
|
187
|
+
case 27:
|
|
188
|
+
_context.prev = 27;
|
|
189
|
+
_context.t0 = _context["catch"](10);
|
|
139
190
|
console.error("PKCE sign-in failed", _context.t0);
|
|
140
|
-
case
|
|
191
|
+
case 30:
|
|
141
192
|
case "end":
|
|
142
193
|
return _context.stop();
|
|
143
194
|
}
|
|
144
|
-
}, _callee, null, [[
|
|
195
|
+
}, _callee, null, [[10, 27]]);
|
|
145
196
|
}));
|
|
146
197
|
return function signInValidator(_x) {
|
|
147
198
|
return _ref2.apply(this, arguments);
|
|
148
199
|
};
|
|
149
200
|
}();
|
|
150
201
|
|
|
151
|
-
//
|
|
202
|
+
// ----- GA + Clarity -----
|
|
152
203
|
function initGA(_x2) {
|
|
153
204
|
return _initGA.apply(this, arguments);
|
|
154
205
|
}
|
|
@@ -157,7 +208,7 @@ function AuthScapeApp(_ref) {
|
|
|
157
208
|
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
|
|
158
209
|
while (1) switch (_context2.prev = _context2.next) {
|
|
159
210
|
case 0:
|
|
160
|
-
if (!(!_ga4React["default"].isInitialized() && G
|
|
211
|
+
if (!(typeof window !== "undefined" && !_ga4React["default"].isInitialized() && G)) {
|
|
161
212
|
_context2.next = 10;
|
|
162
213
|
break;
|
|
163
214
|
}
|
|
@@ -183,13 +234,13 @@ function AuthScapeApp(_ref) {
|
|
|
183
234
|
return _initGA.apply(this, arguments);
|
|
184
235
|
}
|
|
185
236
|
var logEvent = function logEvent(category, action, label) {
|
|
186
|
-
if (ga4React.current)
|
|
187
|
-
|
|
188
|
-
}
|
|
237
|
+
if (ga4React.current) ga4React.current.event(action, label, category);
|
|
238
|
+
// your DB analytics can go here if desired
|
|
189
239
|
};
|
|
190
240
|
var databaseDrivenPageView = function databaseDrivenPageView(pathName) {
|
|
191
241
|
var _signedInUser$current, _signedInUser$current2, _signedInUser$current3;
|
|
192
242
|
if (process.env.enableDatabaseAnalytics !== "true") return;
|
|
243
|
+
if (typeof window === "undefined") return;
|
|
193
244
|
if (pathName === "/signin-oidc") return;
|
|
194
245
|
var host = window.location.protocol + "//" + window.location.host;
|
|
195
246
|
apiService().post("/Analytics/PageView", {
|
|
@@ -201,16 +252,23 @@ function AuthScapeApp(_ref) {
|
|
|
201
252
|
});
|
|
202
253
|
};
|
|
203
254
|
|
|
204
|
-
//
|
|
255
|
+
// ----- Auth init (runs once) -----
|
|
205
256
|
(0, _react.useEffect)(function () {
|
|
206
257
|
if (queryCode) {
|
|
207
258
|
signInValidator(queryCode);
|
|
208
|
-
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
if (!loadingAuth.current) {
|
|
209
262
|
loadingAuth.current = true;
|
|
210
263
|
if (enableAuth) {
|
|
211
264
|
apiService().GetCurrentUser().then(function (usr) {
|
|
212
|
-
signedInUser.current = usr;
|
|
213
|
-
setSignedInUserState(
|
|
265
|
+
signedInUser.current = ensureUserHelpers(usr);
|
|
266
|
+
setSignedInUserState(signedInUser.current);
|
|
267
|
+
setFrontEndLoadedState(true);
|
|
268
|
+
})["catch"](function () {
|
|
269
|
+
// no user / anonymous
|
|
270
|
+
signedInUser.current = null;
|
|
271
|
+
setSignedInUserState(null);
|
|
214
272
|
setFrontEndLoadedState(true);
|
|
215
273
|
});
|
|
216
274
|
} else {
|
|
@@ -219,9 +277,9 @@ function AuthScapeApp(_ref) {
|
|
|
219
277
|
}
|
|
220
278
|
}, [queryCode, enableAuth]);
|
|
221
279
|
|
|
222
|
-
//
|
|
280
|
+
// ----- Analytics init -----
|
|
223
281
|
(0, _react.useEffect)(function () {
|
|
224
|
-
if (!frontEndLoadedState) return;
|
|
282
|
+
if (!frontEndLoadedState || typeof window === "undefined") return;
|
|
225
283
|
if (pageProps.googleAnalytics4Code) {
|
|
226
284
|
initGA(pageProps.googleAnalytics4Code);
|
|
227
285
|
} else if (process.env.googleAnalytics4) {
|
|
@@ -233,44 +291,50 @@ function AuthScapeApp(_ref) {
|
|
|
233
291
|
_reactMicrosoftClarity.clarity.init(process.env.microsoftClarityTrackingCode);
|
|
234
292
|
}
|
|
235
293
|
databaseDrivenPageView(window.location.pathname);
|
|
236
|
-
|
|
294
|
+
var handler = function handler(url) {
|
|
237
295
|
var _ga4React$current;
|
|
238
296
|
(_ga4React$current = ga4React.current) === null || _ga4React$current === void 0 || _ga4React$current.pageview(url);
|
|
239
297
|
databaseDrivenPageView(url);
|
|
240
|
-
}
|
|
241
|
-
|
|
298
|
+
};
|
|
299
|
+
_router["default"].events.on("routeChangeComplete", handler);
|
|
300
|
+
return function () {
|
|
301
|
+
return _router["default"].events.off("routeChangeComplete", handler);
|
|
302
|
+
};
|
|
303
|
+
}, [frontEndLoadedState, pageProps.googleAnalytics4Code, pageProps.microsoftClarityCode]);
|
|
242
304
|
|
|
243
|
-
//
|
|
305
|
+
// ----- Enforce login (client) -----
|
|
244
306
|
(0, _react.useEffect)(function () {
|
|
245
307
|
if (enforceLoggedIn && pathname !== "/signin-oidc" && frontEndLoadedState && !signedInUserState) {
|
|
246
308
|
(0, _authscape.authService)().login();
|
|
247
309
|
}
|
|
248
310
|
}, [signedInUserState, enforceLoggedIn, frontEndLoadedState, pathname]);
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
311
|
+
|
|
312
|
+
// Stable getter for current user (with helpers)
|
|
313
|
+
var currentUser = (0, _react.useMemo)(function () {
|
|
314
|
+
return ensureUserHelpers(signedInUser.current);
|
|
315
|
+
}, [signedInUserState]);
|
|
316
|
+
var useStore = (0, _zustand.create)(function () {
|
|
253
317
|
return store;
|
|
254
318
|
});
|
|
255
319
|
|
|
256
|
-
//
|
|
320
|
+
// ----- Render (SSR-safe; always output page so <title> is visible) -----
|
|
257
321
|
var pageContent = layout ? layout({
|
|
258
322
|
children: /*#__PURE__*/_react["default"].createElement(Component, _extends({}, pageProps, {
|
|
259
|
-
currentUser:
|
|
323
|
+
currentUser: currentUser,
|
|
260
324
|
loadedUser: frontEndLoadedState,
|
|
261
325
|
setIsLoading: setIsLoadingShow,
|
|
262
326
|
logEvent: logEvent,
|
|
263
327
|
store: useStore,
|
|
264
328
|
toast: _reactToastify.toast
|
|
265
329
|
})),
|
|
266
|
-
currentUser:
|
|
330
|
+
currentUser: currentUser,
|
|
267
331
|
setIsLoading: setIsLoadingShow,
|
|
268
332
|
logEvent: logEvent,
|
|
269
333
|
toast: _reactToastify.toast,
|
|
270
334
|
store: useStore,
|
|
271
335
|
pageProps: pageProps
|
|
272
336
|
}) : /*#__PURE__*/_react["default"].createElement(Component, _extends({}, pageProps, {
|
|
273
|
-
currentUser:
|
|
337
|
+
currentUser: currentUser,
|
|
274
338
|
loadedUser: frontEndLoadedState,
|
|
275
339
|
setIsLoading: setIsLoadingShow,
|
|
276
340
|
logEvent: logEvent,
|
package/package.json
CHANGED
|
@@ -1,15 +1,61 @@
|
|
|
1
|
-
import React, { useState, useRef, useEffect } from
|
|
2
|
-
import { ToastContainer, toast } from
|
|
3
|
-
import { ThemeProvider } from
|
|
1
|
+
import React, { useState, useRef, useEffect, useMemo } from "react";
|
|
2
|
+
import { ToastContainer, toast } from "react-toastify";
|
|
3
|
+
import { ThemeProvider } from "@mui/material/styles";
|
|
4
4
|
import Head from "next/head";
|
|
5
|
-
import { useSearchParams, usePathname } from
|
|
6
|
-
import axios from
|
|
5
|
+
import { useSearchParams, usePathname } from "next/navigation";
|
|
6
|
+
import axios from "axios";
|
|
7
7
|
import querystring from "query-string";
|
|
8
|
-
import Router from
|
|
9
|
-
import GA4React from
|
|
10
|
-
import { create } from
|
|
11
|
-
import { clarity } from
|
|
12
|
-
import { authService } from
|
|
8
|
+
import Router from "next/router";
|
|
9
|
+
import GA4React from "ga-4-react";
|
|
10
|
+
import { create } from "zustand";
|
|
11
|
+
import { clarity } from "react-microsoft-clarity";
|
|
12
|
+
import { authService } from "authscape";
|
|
13
|
+
|
|
14
|
+
// ---- optional: import your cookie util if not global ----
|
|
15
|
+
// import { setCookie } from "cookies-next";
|
|
16
|
+
// import { apiService } from "@/services/api"; // wherever yours lives
|
|
17
|
+
|
|
18
|
+
// Decorate a user object with role/permission helpers (idempotent)
|
|
19
|
+
function ensureUserHelpers(u) {
|
|
20
|
+
if (!u || typeof u !== "object") return u;
|
|
21
|
+
|
|
22
|
+
// Avoid redefining on every call
|
|
23
|
+
if (typeof u.hasRole === "function" &&
|
|
24
|
+
typeof u.hasRoleId === "function" &&
|
|
25
|
+
typeof u.hasPermission === "function") {
|
|
26
|
+
return u;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const rolesArr = Array.isArray(u.roles) ? u.roles : [];
|
|
30
|
+
const permsArr = Array.isArray(u.permissions) ? u.permissions : [];
|
|
31
|
+
|
|
32
|
+
// defineProperty keeps them non-enumerable
|
|
33
|
+
Object.defineProperty(u, "hasRole", {
|
|
34
|
+
value: function hasRole(name) {
|
|
35
|
+
if (!name) return false;
|
|
36
|
+
return rolesArr.some(r => r?.name === name);
|
|
37
|
+
},
|
|
38
|
+
writable: false
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
Object.defineProperty(u, "hasRoleId", {
|
|
42
|
+
value: function hasRoleId(id) {
|
|
43
|
+
if (id === undefined || id === null) return false;
|
|
44
|
+
return rolesArr.some(r => r?.id === id);
|
|
45
|
+
},
|
|
46
|
+
writable: false
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
Object.defineProperty(u, "hasPermission", {
|
|
50
|
+
value: function hasPermission(name) {
|
|
51
|
+
if (!name) return false;
|
|
52
|
+
return permsArr.includes(name);
|
|
53
|
+
},
|
|
54
|
+
writable: false
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return u;
|
|
58
|
+
}
|
|
13
59
|
|
|
14
60
|
export function AuthScapeApp({
|
|
15
61
|
Component,
|
|
@@ -19,7 +65,7 @@ export function AuthScapeApp({
|
|
|
19
65
|
muiTheme = {},
|
|
20
66
|
store = {},
|
|
21
67
|
enforceLoggedIn = false,
|
|
22
|
-
enableAuth = true
|
|
68
|
+
enableAuth = true,
|
|
23
69
|
}) {
|
|
24
70
|
const [frontEndLoadedState, setFrontEndLoadedState] = useState(false);
|
|
25
71
|
const [isLoadingShow, setIsLoadingShow] = useState(false);
|
|
@@ -31,64 +77,72 @@ export function AuthScapeApp({
|
|
|
31
77
|
const ga4React = useRef(null);
|
|
32
78
|
|
|
33
79
|
const searchParams = useSearchParams();
|
|
34
|
-
const queryCode = searchParams.get(
|
|
80
|
+
const queryCode = searchParams.get("code");
|
|
35
81
|
const pathname = usePathname();
|
|
36
82
|
|
|
37
|
-
//
|
|
38
|
-
const signInValidator = async (
|
|
39
|
-
if (queryCodeUsed.current ===
|
|
40
|
-
queryCodeUsed.current =
|
|
83
|
+
// ----- PKCE Sign-in (browser-only) -----
|
|
84
|
+
const signInValidator = async (codeFromQuery) => {
|
|
85
|
+
if (queryCodeUsed.current === codeFromQuery) return;
|
|
86
|
+
queryCodeUsed.current = codeFromQuery;
|
|
87
|
+
|
|
88
|
+
if (typeof window === "undefined") return;
|
|
41
89
|
|
|
42
90
|
const codeVerifier = window.localStorage.getItem("verifier");
|
|
43
|
-
if (!
|
|
91
|
+
if (!codeFromQuery || !codeVerifier) return;
|
|
44
92
|
|
|
45
|
-
const headers = {
|
|
93
|
+
const headers = { "Content-Type": "application/x-www-form-urlencoded" };
|
|
46
94
|
|
|
47
|
-
const
|
|
48
|
-
code:
|
|
95
|
+
const body = querystring.stringify({
|
|
96
|
+
code: codeFromQuery,
|
|
49
97
|
grant_type: "authorization_code",
|
|
50
98
|
redirect_uri: window.location.origin + "/signin-oidc",
|
|
51
99
|
client_id: process.env.client_id,
|
|
52
100
|
client_secret: process.env.client_secret,
|
|
53
|
-
code_verifier: codeVerifier
|
|
101
|
+
code_verifier: codeVerifier,
|
|
54
102
|
});
|
|
55
103
|
|
|
56
104
|
try {
|
|
57
|
-
const response = await axios.post(
|
|
58
|
-
|
|
105
|
+
const response = await axios.post(
|
|
106
|
+
process.env.authorityUri + "/connect/token",
|
|
107
|
+
body,
|
|
108
|
+
{ headers }
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const domainHost = window.location.hostname.split(".").slice(-2).join(".");
|
|
59
112
|
|
|
60
113
|
window.localStorage.removeItem("verifier");
|
|
61
114
|
|
|
62
|
-
|
|
115
|
+
// NOTE: replace setCookie below with your implementation if different
|
|
116
|
+
await setCookie("access_token", response.data.access_token, {
|
|
63
117
|
maxAge: 60 * 60 * 24 * 365,
|
|
64
|
-
path:
|
|
118
|
+
path: "/",
|
|
65
119
|
domain: domainHost,
|
|
66
|
-
secure: true
|
|
120
|
+
secure: true,
|
|
67
121
|
});
|
|
68
|
-
await setCookie(
|
|
122
|
+
await setCookie("expires_in", response.data.expires_in, {
|
|
69
123
|
maxAge: 60 * 60 * 24 * 365,
|
|
70
|
-
path:
|
|
124
|
+
path: "/",
|
|
71
125
|
domain: domainHost,
|
|
72
|
-
secure: true
|
|
126
|
+
secure: true,
|
|
73
127
|
});
|
|
74
|
-
await setCookie(
|
|
128
|
+
await setCookie("refresh_token", response.data.refresh_token, {
|
|
75
129
|
maxAge: 60 * 60 * 24 * 365,
|
|
76
|
-
path:
|
|
130
|
+
path: "/",
|
|
77
131
|
domain: domainHost,
|
|
78
|
-
secure: true
|
|
132
|
+
secure: true,
|
|
79
133
|
});
|
|
80
134
|
|
|
81
|
-
const redirectUri = localStorage.getItem("redirectUri");
|
|
82
|
-
localStorage.clear();
|
|
135
|
+
const redirectUri = window.localStorage.getItem("redirectUri");
|
|
136
|
+
window.localStorage.clear();
|
|
83
137
|
window.location.href = redirectUri || "/";
|
|
84
138
|
} catch (exp) {
|
|
85
139
|
console.error("PKCE sign-in failed", exp);
|
|
86
140
|
}
|
|
87
141
|
};
|
|
88
142
|
|
|
89
|
-
//
|
|
143
|
+
// ----- GA + Clarity -----
|
|
90
144
|
async function initGA(G) {
|
|
91
|
-
if (!GA4React.isInitialized() && G
|
|
145
|
+
if (typeof window !== "undefined" && !GA4React.isInitialized() && G) {
|
|
92
146
|
ga4React.current = new GA4React(G, { debug_mode: !process.env.production });
|
|
93
147
|
try {
|
|
94
148
|
await ga4React.current.initialize();
|
|
@@ -99,13 +153,13 @@ export function AuthScapeApp({
|
|
|
99
153
|
}
|
|
100
154
|
|
|
101
155
|
const logEvent = (category, action, label) => {
|
|
102
|
-
if (ga4React.current)
|
|
103
|
-
|
|
104
|
-
}
|
|
156
|
+
if (ga4React.current) ga4React.current.event(action, label, category);
|
|
157
|
+
// your DB analytics can go here if desired
|
|
105
158
|
};
|
|
106
159
|
|
|
107
160
|
const databaseDrivenPageView = (pathName) => {
|
|
108
161
|
if (process.env.enableDatabaseAnalytics !== "true") return;
|
|
162
|
+
if (typeof window === "undefined") return;
|
|
109
163
|
if (pathName === "/signin-oidc") return;
|
|
110
164
|
|
|
111
165
|
const host = window.location.protocol + "//" + window.location.host;
|
|
@@ -115,20 +169,29 @@ export function AuthScapeApp({
|
|
|
115
169
|
locationId: signedInUser.current?.locationId,
|
|
116
170
|
companyId: signedInUser.current?.companyId,
|
|
117
171
|
uri: pathName,
|
|
118
|
-
host
|
|
172
|
+
host,
|
|
119
173
|
});
|
|
120
174
|
};
|
|
121
175
|
|
|
122
|
-
//
|
|
176
|
+
// ----- Auth init (runs once) -----
|
|
123
177
|
useEffect(() => {
|
|
124
178
|
if (queryCode) {
|
|
125
179
|
signInValidator(queryCode);
|
|
126
|
-
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (!loadingAuth.current) {
|
|
127
184
|
loadingAuth.current = true;
|
|
185
|
+
|
|
128
186
|
if (enableAuth) {
|
|
129
187
|
apiService().GetCurrentUser().then((usr) => {
|
|
130
|
-
signedInUser.current = usr;
|
|
131
|
-
setSignedInUserState(
|
|
188
|
+
signedInUser.current = ensureUserHelpers(usr);
|
|
189
|
+
setSignedInUserState(signedInUser.current);
|
|
190
|
+
setFrontEndLoadedState(true);
|
|
191
|
+
}).catch(() => {
|
|
192
|
+
// no user / anonymous
|
|
193
|
+
signedInUser.current = null;
|
|
194
|
+
setSignedInUserState(null);
|
|
132
195
|
setFrontEndLoadedState(true);
|
|
133
196
|
});
|
|
134
197
|
} else {
|
|
@@ -137,9 +200,9 @@ export function AuthScapeApp({
|
|
|
137
200
|
}
|
|
138
201
|
}, [queryCode, enableAuth]);
|
|
139
202
|
|
|
140
|
-
//
|
|
203
|
+
// ----- Analytics init -----
|
|
141
204
|
useEffect(() => {
|
|
142
|
-
if (!frontEndLoadedState) return;
|
|
205
|
+
if (!frontEndLoadedState || typeof window === "undefined") return;
|
|
143
206
|
|
|
144
207
|
if (pageProps.googleAnalytics4Code) {
|
|
145
208
|
initGA(pageProps.googleAnalytics4Code);
|
|
@@ -155,40 +218,71 @@ export function AuthScapeApp({
|
|
|
155
218
|
|
|
156
219
|
databaseDrivenPageView(window.location.pathname);
|
|
157
220
|
|
|
158
|
-
|
|
221
|
+
const handler = (url) => {
|
|
159
222
|
ga4React.current?.pageview(url);
|
|
160
223
|
databaseDrivenPageView(url);
|
|
161
|
-
}
|
|
162
|
-
|
|
224
|
+
};
|
|
225
|
+
Router.events.on("routeChangeComplete", handler);
|
|
226
|
+
return () => Router.events.off("routeChangeComplete", handler);
|
|
227
|
+
}, [frontEndLoadedState, pageProps.googleAnalytics4Code, pageProps.microsoftClarityCode]);
|
|
163
228
|
|
|
164
|
-
//
|
|
229
|
+
// ----- Enforce login (client) -----
|
|
165
230
|
useEffect(() => {
|
|
166
|
-
if (
|
|
231
|
+
if (
|
|
232
|
+
enforceLoggedIn &&
|
|
233
|
+
pathname !== "/signin-oidc" &&
|
|
234
|
+
frontEndLoadedState &&
|
|
235
|
+
!signedInUserState
|
|
236
|
+
) {
|
|
167
237
|
authService().login();
|
|
168
238
|
}
|
|
169
239
|
}, [signedInUserState, enforceLoggedIn, frontEndLoadedState, pathname]);
|
|
170
240
|
|
|
171
|
-
|
|
241
|
+
// Stable getter for current user (with helpers)
|
|
242
|
+
const currentUser = useMemo(() => ensureUserHelpers(signedInUser.current), [signedInUserState]);
|
|
172
243
|
|
|
173
|
-
const useStore = create((
|
|
244
|
+
const useStore = create(() => store);
|
|
174
245
|
|
|
175
|
-
//
|
|
246
|
+
// ----- Render (SSR-safe; always output page so <title> is visible) -----
|
|
176
247
|
const pageContent = layout
|
|
177
248
|
? layout({
|
|
178
|
-
children:
|
|
179
|
-
|
|
249
|
+
children: (
|
|
250
|
+
<Component
|
|
251
|
+
{...pageProps}
|
|
252
|
+
currentUser={currentUser}
|
|
253
|
+
loadedUser={frontEndLoadedState}
|
|
254
|
+
setIsLoading={setIsLoadingShow}
|
|
255
|
+
logEvent={logEvent}
|
|
256
|
+
store={useStore}
|
|
257
|
+
toast={toast}
|
|
258
|
+
/>
|
|
259
|
+
),
|
|
260
|
+
currentUser,
|
|
180
261
|
setIsLoading: setIsLoadingShow,
|
|
181
262
|
logEvent,
|
|
182
263
|
toast,
|
|
183
264
|
store: useStore,
|
|
184
|
-
pageProps
|
|
265
|
+
pageProps,
|
|
185
266
|
})
|
|
186
|
-
:
|
|
267
|
+
: (
|
|
268
|
+
<Component
|
|
269
|
+
{...pageProps}
|
|
270
|
+
currentUser={currentUser}
|
|
271
|
+
loadedUser={frontEndLoadedState}
|
|
272
|
+
setIsLoading={setIsLoadingShow}
|
|
273
|
+
logEvent={logEvent}
|
|
274
|
+
store={useStore}
|
|
275
|
+
toast={toast}
|
|
276
|
+
/>
|
|
277
|
+
);
|
|
187
278
|
|
|
188
279
|
return (
|
|
189
280
|
<>
|
|
190
281
|
<Head>
|
|
191
|
-
<meta
|
|
282
|
+
<meta
|
|
283
|
+
name="viewport"
|
|
284
|
+
content="width=device-width, initial-scale=0.86, maximum-scale=5.0, minimum-scale=0.86"
|
|
285
|
+
/>
|
|
192
286
|
</Head>
|
|
193
287
|
|
|
194
288
|
<ThemeProvider theme={muiTheme}>
|