react-oauth-providers 1.0.0 → 1.0.1

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/index.mjs ADDED
@@ -0,0 +1,552 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __async = (__this, __arguments, generator) => {
21
+ return new Promise((resolve, reject) => {
22
+ var fulfilled = (value) => {
23
+ try {
24
+ step(generator.next(value));
25
+ } catch (e) {
26
+ reject(e);
27
+ }
28
+ };
29
+ var rejected = (value) => {
30
+ try {
31
+ step(generator.throw(value));
32
+ } catch (e) {
33
+ reject(e);
34
+ }
35
+ };
36
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
37
+ step((generator = generator.apply(__this, __arguments)).next());
38
+ });
39
+ };
40
+
41
+ // src/AuthContext.tsx
42
+ import { createContext } from "react";
43
+ var AuthContext = createContext({});
44
+
45
+ // src/AuthProvider.tsx
46
+ import React, { useCallback, useEffect, useMemo, useState } from "react";
47
+
48
+ // src/utils/session.ts
49
+ function setSessionItem(key, value, ttlMs) {
50
+ const data = {
51
+ value,
52
+ expires: Date.now() + ttlMs
53
+ };
54
+ sessionStorage.setItem(key, JSON.stringify(data));
55
+ }
56
+ function getSessionItem(key) {
57
+ const dataStr = sessionStorage.getItem(key);
58
+ if (!dataStr)
59
+ return null;
60
+ try {
61
+ const data = JSON.parse(dataStr);
62
+ if (Date.now() > data.expires) {
63
+ sessionStorage.removeItem(key);
64
+ return null;
65
+ }
66
+ return data.value;
67
+ } catch (e) {
68
+ return null;
69
+ }
70
+ }
71
+ function removeSessionItem(key) {
72
+ try {
73
+ sessionStorage.removeItem(key);
74
+ } catch (error) {
75
+ return null;
76
+ }
77
+ }
78
+
79
+ // src/utils/http.ts
80
+ function request(url, options) {
81
+ return __async(this, null, function* () {
82
+ var _a;
83
+ let body;
84
+ const headers = __spreadValues({}, (_a = options.headers) != null ? _a : {});
85
+ try {
86
+ body = options.body;
87
+ headers["Content-Type"] = headers["Content-Type"] || "application/json";
88
+ const response = yield fetch(url, {
89
+ method: options.method,
90
+ headers,
91
+ body
92
+ });
93
+ if (!response.ok) {
94
+ const error = yield response.json().catch(() => ({}));
95
+ const expectedError = response.status >= 400 && response.status < 500;
96
+ if (!expectedError) {
97
+ console.log({ error });
98
+ console.log("Unexpected error occurs");
99
+ }
100
+ return Promise.reject(__spreadValues({ status: response.status }, error));
101
+ }
102
+ return { data: yield response.json() };
103
+ } catch (error) {
104
+ console.log("Network or unexpected error:", error);
105
+ return Promise.reject(error);
106
+ }
107
+ });
108
+ }
109
+ var http_default = {
110
+ get: (url, options) => request(url, __spreadProps(__spreadValues({}, options), { method: "GET" })),
111
+ post: (url, body, options) => request(url, __spreadProps(__spreadValues({}, options), { method: "POST", body })),
112
+ put: (url, body, options) => request(url, __spreadProps(__spreadValues({}, options), { method: "PUT", body })),
113
+ delete: (url, options) => request(url, __spreadProps(__spreadValues({}, options), { method: "DELETE" }))
114
+ };
115
+
116
+ // src/utils/pkce.ts
117
+ import getPkce from "oauth-pkce";
118
+ var generatePkce = () => __async(void 0, null, function* () {
119
+ return new Promise((resolve, reject) => {
120
+ getPkce(50, (error, { verifier, challenge }) => {
121
+ if (error)
122
+ reject(error);
123
+ resolve({ verifier, challenge, algorithm: "S256" });
124
+ });
125
+ });
126
+ });
127
+
128
+ // src/utils/others.ts
129
+ var toURL = (input) => {
130
+ try {
131
+ return new URL(input);
132
+ } catch (e) {
133
+ return new URL(input, window.location.origin);
134
+ }
135
+ };
136
+ var makeKey = (key, prefix) => {
137
+ return prefix ? `${prefix}_${key}` : key;
138
+ };
139
+
140
+ // src/authConfig.ts
141
+ var config = null;
142
+ var getConfig = () => config;
143
+ function createInternalConfig(passedConfig) {
144
+ const {
145
+ preLogin = () => null,
146
+ postLogin = () => null,
147
+ onLogInError = () => null,
148
+ storage = "local",
149
+ spaCallbackUri = passedConfig.spaCallbackUri ? toURL(passedConfig.spaCallbackUri).toString() : window.location.origin,
150
+ logoutRedirect = passedConfig.logoutRedirect ? toURL(passedConfig.logoutRedirect).toString() : window.location.origin,
151
+ storageKeyPrefix = "auth_",
152
+ googleProvider
153
+ } = passedConfig;
154
+ config = __spreadProps(__spreadValues({}, passedConfig), {
155
+ preLogin,
156
+ postLogin,
157
+ onLogInError,
158
+ storage,
159
+ storageKeyPrefix,
160
+ spaCallbackUri,
161
+ logoutRedirect,
162
+ keys: createAuthKeys(storageKeyPrefix),
163
+ googleProvider: googleProvider ? __spreadValues({ type: "spa", scope: "openid email profile" }, googleProvider) : void 0
164
+ });
165
+ return config;
166
+ }
167
+ function createAuthKeys(prefix) {
168
+ return {
169
+ PROVIDER_TYPE: makeKey("provider_type", prefix),
170
+ PROVIDER: makeKey("provider", prefix),
171
+ VERIFIER: makeKey("verifier", prefix),
172
+ ACCESS_TOKEN: makeKey("access_token", prefix),
173
+ EXPIRES_IN: makeKey("expires_in", prefix),
174
+ REFRESH_TOKEN: makeKey("refresh_token", prefix),
175
+ TOKEN_TYPE: makeKey("token_type", prefix),
176
+ ID_TOKEN: makeKey("id_token", prefix)
177
+ };
178
+ }
179
+
180
+ // src/utils/constants.ts
181
+ var AUTH_PROVIDERS = { google: "google" };
182
+
183
+ // src/utils/storage.ts
184
+ var keepToStorage = (type, key, value) => {
185
+ if (type === "local")
186
+ localStorage.setItem(key, value);
187
+ else if (type === "session")
188
+ sessionStorage.setItem(key, value);
189
+ };
190
+ var removeFromStorage = (type, key) => {
191
+ if (type === "local")
192
+ localStorage.removeItem(key);
193
+ else if (type === "session")
194
+ sessionStorage.removeItem(key);
195
+ };
196
+ var getFromStorage = (type, key) => {
197
+ var _a, _b;
198
+ if (type === "local")
199
+ return (_a = localStorage.getItem(key)) != null ? _a : "";
200
+ else if (type === "session")
201
+ return (_b = sessionStorage.getItem(key)) != null ? _b : "";
202
+ return "";
203
+ };
204
+
205
+ // src/google/index.ts
206
+ var signinWithGoogleSpa = () => __async(void 0, null, function* () {
207
+ const config2 = getConfig();
208
+ if (!config2)
209
+ return;
210
+ const { googleProvider, keys } = config2;
211
+ const { verifier, challenge, algorithm } = yield generatePkce();
212
+ setSessionItem(keys.VERIFIER, verifier, 3 * 60 * 1e3);
213
+ setSessionItem(keys.PROVIDER, AUTH_PROVIDERS.google, 3 * 60 * 1e3);
214
+ setSessionItem(keys.PROVIDER_TYPE, googleProvider == null ? void 0 : googleProvider.type, 3 * 60 * 1e3);
215
+ const params = new URLSearchParams({
216
+ client_id: googleProvider == null ? void 0 : googleProvider.clientId,
217
+ redirect_uri: config2 == null ? void 0 : config2.spaCallbackUri,
218
+ response_type: "code",
219
+ scope: (googleProvider == null ? void 0 : googleProvider.scope) || "",
220
+ code_challenge: challenge,
221
+ code_challenge_method: algorithm,
222
+ access_type: "offline",
223
+ prompt: "consent"
224
+ });
225
+ window.location.href = `https://accounts.google.com/o/oauth2/v2/auth?${params.toString()}`;
226
+ });
227
+ var signinWithGoogleCallback = (code, verifier) => __async(void 0, null, function* () {
228
+ if (!code || !verifier)
229
+ return;
230
+ const config2 = getConfig();
231
+ if (!config2)
232
+ return;
233
+ const { googleProvider, keys } = config2;
234
+ const type = "spa";
235
+ try {
236
+ const data = new URLSearchParams({
237
+ client_id: googleProvider == null ? void 0 : googleProvider.clientId,
238
+ grant_type: "authorization_code",
239
+ code,
240
+ redirect_uri: config2 == null ? void 0 : config2.spaCallbackUri,
241
+ code_verifier: verifier
242
+ });
243
+ const res = yield http_default.post(
244
+ "https://oauth2.googleapis.com/token",
245
+ data.toString(),
246
+ {
247
+ headers: { "Content-Type": "application/x-www-form-urlencoded" }
248
+ }
249
+ );
250
+ const tokens = res.data;
251
+ if (tokens == null ? void 0 : tokens.access_token) {
252
+ removeSessionItem(keys.PROVIDER);
253
+ removeSessionItem(keys.VERIFIER);
254
+ removeSessionItem(keys.PROVIDER_TYPE);
255
+ keepToStorage(config2.storage, keys.PROVIDER, AUTH_PROVIDERS.google);
256
+ keepToStorage(config2.storage, keys.PROVIDER_TYPE, type);
257
+ keepToStorage(config2.storage, keys.ACCESS_TOKEN, tokens.access_token);
258
+ keepToStorage(
259
+ config2.storage,
260
+ keys.EXPIRES_IN,
261
+ String(Date.now() + tokens.expires_in * 1e3)
262
+ );
263
+ keepToStorage(config2.storage, keys.REFRESH_TOKEN, tokens.refresh_token);
264
+ keepToStorage(config2.storage, keys.TOKEN_TYPE, tokens.token_type);
265
+ keepToStorage(config2.storage, keys.ID_TOKEN, tokens.id_token);
266
+ }
267
+ } catch (error) {
268
+ return Promise.reject(error);
269
+ }
270
+ });
271
+ var getGoogleSessionUser = () => __async(void 0, null, function* () {
272
+ const config2 = getConfig();
273
+ if (!config2)
274
+ return;
275
+ const { keys } = config2;
276
+ try {
277
+ const accessToken = getFromStorage(config2.storage, keys.ACCESS_TOKEN);
278
+ if (!accessToken)
279
+ return;
280
+ const res = yield http_default.get(
281
+ `https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token=${accessToken}`
282
+ );
283
+ const user = res.data;
284
+ return user;
285
+ } catch (error) {
286
+ return Promise.reject(error);
287
+ }
288
+ });
289
+ var refreshGoogleAccessToken = () => __async(void 0, null, function* () {
290
+ const config2 = getConfig();
291
+ if (!config2)
292
+ return;
293
+ const { googleProvider, keys } = config2;
294
+ const refreshToken = getFromStorage(config2.storage, keys.REFRESH_TOKEN);
295
+ if (!refreshToken)
296
+ return;
297
+ try {
298
+ const data = new URLSearchParams({
299
+ client_id: googleProvider == null ? void 0 : googleProvider.clientId,
300
+ grant_type: "refresh_token",
301
+ refresh_token: refreshToken
302
+ });
303
+ const res = yield http_default.post(
304
+ "https://oauth2.googleapis.com/token",
305
+ data.toString(),
306
+ {
307
+ headers: { "Content-Type": "application/x-www-form-urlencoded" }
308
+ }
309
+ );
310
+ const tokens = res.data;
311
+ if (!tokens.access_token) {
312
+ console.error("Failed to refresh access token", tokens);
313
+ return null;
314
+ }
315
+ keepToStorage(config2.storage, keys.ACCESS_TOKEN, tokens.access_token);
316
+ if (tokens.expires_in) {
317
+ keepToStorage(
318
+ config2.storage,
319
+ keys.EXPIRES_IN,
320
+ String(Date.now() + tokens.expires_in * 1e3)
321
+ );
322
+ }
323
+ if (tokens.id_token)
324
+ keepToStorage(config2.storage, keys.ID_TOKEN, tokens.id_token);
325
+ if (tokens.token_type)
326
+ keepToStorage(config2.storage, keys.TOKEN_TYPE, tokens.token_type);
327
+ } catch (error) {
328
+ return Promise.reject(error);
329
+ }
330
+ });
331
+
332
+ // src/actions.ts
333
+ var refreshTimeout = null;
334
+ var handleCallback = () => __async(void 0, null, function* () {
335
+ const config2 = getConfig();
336
+ if (!config2)
337
+ return;
338
+ const keys = config2 == null ? void 0 : config2.keys;
339
+ const authMode = getSessionItem(keys.PROVIDER);
340
+ const verifier = getSessionItem(keys.VERIFIER);
341
+ if (!authMode || !verifier)
342
+ return;
343
+ try {
344
+ switch (authMode) {
345
+ case AUTH_PROVIDERS.google: {
346
+ const searchQuery = new URLSearchParams(window.location.search);
347
+ const code = searchQuery.get("code");
348
+ if (!code)
349
+ return;
350
+ yield signinWithGoogleCallback(code, verifier);
351
+ break;
352
+ }
353
+ default:
354
+ break;
355
+ }
356
+ } catch (error) {
357
+ return Promise.reject(error);
358
+ }
359
+ });
360
+ var handleFetchSessionUser = (retry = true) => __async(void 0, null, function* () {
361
+ const config2 = getConfig();
362
+ if (!config2)
363
+ return;
364
+ const keys = config2 == null ? void 0 : config2.keys;
365
+ const authMode = getFromStorage(config2.storage, keys.PROVIDER);
366
+ if (!authMode)
367
+ return;
368
+ let sessionUser = null;
369
+ try {
370
+ switch (authMode) {
371
+ case AUTH_PROVIDERS.google: {
372
+ sessionUser = yield getGoogleSessionUser();
373
+ break;
374
+ }
375
+ default:
376
+ break;
377
+ }
378
+ if (sessionUser)
379
+ handleScheduleTokenRefresh();
380
+ return sessionUser;
381
+ } catch (error) {
382
+ console.log("Fetch Session User Error:", error);
383
+ if (!retry)
384
+ return null;
385
+ switch (authMode) {
386
+ case AUTH_PROVIDERS.google: {
387
+ yield refreshGoogleAccessToken();
388
+ yield handleFetchSessionUser(false);
389
+ break;
390
+ }
391
+ default:
392
+ break;
393
+ }
394
+ return null;
395
+ }
396
+ });
397
+ var handleScheduleTokenRefresh = () => {
398
+ var _a;
399
+ const config2 = getConfig();
400
+ if (!config2)
401
+ return;
402
+ const keys = config2 == null ? void 0 : config2.keys;
403
+ const authMode = getFromStorage(config2.storage, keys.PROVIDER);
404
+ if (!authMode)
405
+ return;
406
+ const expiresIn = Number(
407
+ (_a = getFromStorage(config2.storage, keys.EXPIRES_IN)) != null ? _a : 0
408
+ );
409
+ if (!expiresIn)
410
+ return;
411
+ clearTokenRefresh();
412
+ const refreshTime = expiresIn - 60 * 1e3;
413
+ refreshTimeout = setTimeout(() => __async(void 0, null, function* () {
414
+ switch (authMode) {
415
+ case AUTH_PROVIDERS.google: {
416
+ yield refreshGoogleAccessToken();
417
+ break;
418
+ }
419
+ default:
420
+ break;
421
+ }
422
+ }), refreshTime);
423
+ };
424
+ var clearTokenRefresh = () => {
425
+ if (refreshTimeout) {
426
+ clearTimeout(refreshTimeout);
427
+ refreshTimeout = null;
428
+ }
429
+ };
430
+ var logout = () => {
431
+ clearTokens();
432
+ clearTokenRefresh();
433
+ };
434
+ var clearTokens = () => {
435
+ const config2 = getConfig();
436
+ if (!config2)
437
+ return;
438
+ const keys = config2 == null ? void 0 : config2.keys;
439
+ const {
440
+ PROVIDER,
441
+ ACCESS_TOKEN,
442
+ EXPIRES_IN,
443
+ REFRESH_TOKEN,
444
+ TOKEN_TYPE,
445
+ ID_TOKEN,
446
+ PROVIDER_TYPE
447
+ } = keys;
448
+ removeFromStorage(config2.storage, PROVIDER);
449
+ removeFromStorage(config2.storage, PROVIDER_TYPE);
450
+ removeFromStorage(config2.storage, ACCESS_TOKEN);
451
+ removeFromStorage(config2.storage, EXPIRES_IN);
452
+ removeFromStorage(config2.storage, REFRESH_TOKEN);
453
+ removeFromStorage(config2.storage, TOKEN_TYPE);
454
+ removeFromStorage(config2.storage, ID_TOKEN);
455
+ };
456
+
457
+ // src/AuthProvider.tsx
458
+ var AuthProvider = ({
459
+ authConfig,
460
+ children
461
+ }) => {
462
+ const config2 = useMemo(
463
+ () => createInternalConfig(authConfig),
464
+ [authConfig]
465
+ );
466
+ const tmpAuthProviderType = useMemo(
467
+ () => getSessionItem(config2.keys.PROVIDER_TYPE),
468
+ [config2]
469
+ );
470
+ const [loginInProgress, setLoginInProgress] = useState(true);
471
+ const [user, setUser] = useState();
472
+ useEffect(() => {
473
+ handleFetchSessionUser().then((user2) => {
474
+ setUser(user2);
475
+ setLoginInProgress(false);
476
+ });
477
+ }, []);
478
+ const signinWithGoogle = useCallback(() => __async(void 0, null, function* () {
479
+ var _a, _b, _c;
480
+ if (!((_a = config2.googleProvider) == null ? void 0 : _a.clientId)) {
481
+ throw Error(
482
+ "'clientId' must be set in the 'googleProvider' object in the AuthProvider Config"
483
+ );
484
+ }
485
+ (_b = config2.preLogin) == null ? void 0 : _b.call(config2);
486
+ try {
487
+ if (config2.googleProvider.type === "spa") {
488
+ yield signinWithGoogleSpa();
489
+ }
490
+ } catch (error) {
491
+ (_c = config2.onLogInError) == null ? void 0 : _c.call(config2, error);
492
+ }
493
+ }), []);
494
+ useEffect(() => {
495
+ if (!config2 || !tmpAuthProviderType)
496
+ return;
497
+ if (window.location.pathname !== new URL(config2.spaCallbackUri).pathname) {
498
+ return;
499
+ }
500
+ const callback = () => __async(void 0, null, function* () {
501
+ var _a, _b;
502
+ try {
503
+ yield handleCallback();
504
+ (_a = config2.postLogin) == null ? void 0 : _a.call(config2);
505
+ } catch (error) {
506
+ (_b = config2.onLogInError) == null ? void 0 : _b.call(config2, error);
507
+ }
508
+ });
509
+ callback();
510
+ }, [tmpAuthProviderType, config2]);
511
+ const logOut = useCallback(
512
+ ({ logoutHint, redirect = true, redirectUri } = {}) => {
513
+ logout();
514
+ if (!redirect)
515
+ return;
516
+ const baseUrl = redirectUri || config2.logoutRedirect || "/";
517
+ const params = new URLSearchParams();
518
+ if (logoutHint)
519
+ params.append("logout_hint", logoutHint);
520
+ const url = params.toString() ? `${baseUrl}?${params.toString()}` : baseUrl;
521
+ window.location.assign(url);
522
+ },
523
+ []
524
+ );
525
+ return /* @__PURE__ */ React.createElement(
526
+ AuthContext.Provider,
527
+ {
528
+ value: {
529
+ loginInProgress,
530
+ signinWithGoogle,
531
+ user,
532
+ logOut
533
+ }
534
+ },
535
+ children
536
+ );
537
+ };
538
+
539
+ // src/useAuth.tsx
540
+ import { useContext } from "react";
541
+ function useAuth() {
542
+ const ctx = useContext(AuthContext);
543
+ if (!ctx) {
544
+ throw new Error("useAuth must be used within an AuthProvider");
545
+ }
546
+ return ctx;
547
+ }
548
+ export {
549
+ AuthContext,
550
+ AuthProvider,
551
+ useAuth
552
+ };
package/package.json CHANGED
@@ -1,13 +1,16 @@
1
1
  {
2
2
  "name": "react-oauth-providers",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "main": "dist/index.cjs.js",
5
5
  "module": "dist/index.esm.js",
6
6
  "types": "dist/types/index.d.ts",
7
7
  "scripts": {
8
- "build": "tsup src/index.tsx --format cjs,esm --dts --out-dir dist",
8
+ "build": "tsup src/index.ts --format cjs,esm --dts --out-dir dist",
9
9
  "test": "echo \"Error: no test specified\" && exit 1"
10
10
  },
11
+ "files": [
12
+ "dist"
13
+ ],
11
14
  "dependencies": {
12
15
  "oauth-pkce": "^0.0.7"
13
16
  },
@@ -1,4 +0,0 @@
1
- import { createContext } from 'react'
2
- import type { IAuthContext } from './types'
3
-
4
- export const AuthContext = createContext({} as IAuthContext)
@@ -1,103 +0,0 @@
1
- import React, { useCallback, useEffect, useMemo, useState } from "react";
2
- import { AuthContext } from "./AuthContext";
3
- import * as actions from "./actions";
4
- import type { IAuthProvider, ILogoutFunc, IAuthInternalConfig } from "./types";
5
- import { createInternalConfig } from "./authConfig";
6
- import { getSessionItem } from "./utils/session";
7
-
8
- export const AuthProvider: React.FC<IAuthProvider> = ({
9
- authConfig,
10
- children,
11
- }) => {
12
- const config = useMemo<IAuthInternalConfig>(
13
- () => createInternalConfig(authConfig),
14
- [authConfig]
15
- );
16
- const tmpAuthProviderType = useMemo(
17
- () => getSessionItem(config.keys.PROVIDER_TYPE),
18
- [config]
19
- );
20
-
21
- const [loginInProgress, setLoginInProgress] = useState(true);
22
- const [user, setUser] = useState<null | any>();
23
-
24
- useEffect(() => {
25
- actions.handleFetchSessionUser().then((user) => {
26
- setUser(user);
27
- setLoginInProgress(false);
28
- });
29
- }, []);
30
-
31
- const signinWithGoogle = useCallback(async () => {
32
- if (!config.googleProvider?.clientId) {
33
- throw Error(
34
- "'clientId' must be set in the 'googleProvider' object in the AuthProvider Config"
35
- );
36
- }
37
-
38
- config.preLogin?.();
39
-
40
- try {
41
- if (config.googleProvider.type === "spa") {
42
- await actions.signinWithGoogleSpa();
43
- }
44
- } catch (error) {
45
- config.onLogInError?.(error);
46
- }
47
- }, []);
48
-
49
- // callback handler for spa login
50
- useEffect(() => {
51
- if (!config || !tmpAuthProviderType) return;
52
- if (window.location.pathname !== new URL(config.spaCallbackUri!).pathname) {
53
- return;
54
- }
55
-
56
- const callback = async () => {
57
- try {
58
- await actions.handleCallback();
59
-
60
- config.postLogin?.();
61
- } catch (error) {
62
- config.onLogInError?.(error);
63
- }
64
- };
65
-
66
- callback();
67
- }, [tmpAuthProviderType, config]);
68
-
69
- const logOut = useCallback<ILogoutFunc>(
70
- ({ logoutHint, redirect = true, redirectUri } = {}) => {
71
- actions.logout();
72
-
73
- if (!redirect) return;
74
-
75
- // Determine redirect URL or fallback to root
76
- const baseUrl = redirectUri || config.logoutRedirect || "/";
77
-
78
- const params = new URLSearchParams();
79
- if (logoutHint) params.append("logout_hint", logoutHint);
80
-
81
- // Append params only if there are any
82
- const url = params.toString()
83
- ? `${baseUrl}?${params.toString()}`
84
- : baseUrl;
85
-
86
- window.location.assign(url);
87
- },
88
- []
89
- );
90
-
91
- return (
92
- <AuthContext.Provider
93
- value={{
94
- loginInProgress,
95
- signinWithGoogle,
96
- user,
97
- logOut,
98
- }}
99
- >
100
- {children}
101
- </AuthContext.Provider>
102
- );
103
- };