@yiminlab/authkit 0.1.0

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.
@@ -0,0 +1,677 @@
1
+ // src/react/use-auth.ts
2
+ import { useState, useEffect, useCallback, useMemo } from "react";
3
+
4
+ // src/core/types.ts
5
+ var DEFAULT_AUTH_CONFIG = {
6
+ portalUrl: typeof process !== "undefined" ? process.env.NEXT_PUBLIC_PORTAL_URL || "https://yiminlab.site" : "https://yiminlab.site",
7
+ apiBaseUrl: typeof process !== "undefined" ? process.env.NEXT_PUBLIC_API_BASE_URL || "https://api.yiminlab.site" : "https://api.yiminlab.site",
8
+ callbackPath: "/auth/callback",
9
+ tokenKeys: {
10
+ accessToken: "authkit_access_token",
11
+ refreshToken: "authkit_refresh_token",
12
+ tokenExpiry: "authkit_token_expiry"
13
+ }
14
+ };
15
+
16
+ // src/core/token-manager.ts
17
+ var LocalStorageAdapter = class {
18
+ getItem(key) {
19
+ if (typeof window === "undefined") return null;
20
+ return localStorage.getItem(key);
21
+ }
22
+ setItem(key, value) {
23
+ if (typeof window === "undefined") return;
24
+ localStorage.setItem(key, value);
25
+ }
26
+ removeItem(key) {
27
+ if (typeof window === "undefined") return;
28
+ localStorage.removeItem(key);
29
+ }
30
+ };
31
+ var TokenManager = class {
32
+ constructor(storage, config) {
33
+ this.storage = storage || new LocalStorageAdapter();
34
+ this.config = { ...DEFAULT_AUTH_CONFIG, ...config };
35
+ }
36
+ /**
37
+ * 保存 tokens
38
+ */
39
+ setTokens(accessToken, refreshToken, expiresIn) {
40
+ const expiryTime = Date.now() + expiresIn * 1e3;
41
+ this.storage.setItem(this.config.tokenKeys.accessToken, accessToken);
42
+ this.storage.setItem(this.config.tokenKeys.refreshToken, refreshToken);
43
+ this.storage.setItem(this.config.tokenKeys.tokenExpiry, expiryTime.toString());
44
+ }
45
+ /**
46
+ * 获取 Access Token
47
+ */
48
+ getAccessToken() {
49
+ return this.storage.getItem(this.config.tokenKeys.accessToken);
50
+ }
51
+ /**
52
+ * 获取 Refresh Token
53
+ */
54
+ getRefreshToken() {
55
+ return this.storage.getItem(this.config.tokenKeys.refreshToken);
56
+ }
57
+ /**
58
+ * 获取 Token 过期时间
59
+ */
60
+ getTokenExpiry() {
61
+ const expiry = this.storage.getItem(this.config.tokenKeys.tokenExpiry);
62
+ return expiry ? parseInt(expiry, 10) : null;
63
+ }
64
+ /**
65
+ * 检查 Access Token 是否过期
66
+ * 提前 60 秒认为过期,留出刷新时间
67
+ */
68
+ isAccessTokenExpired() {
69
+ const expiryTime = this.getTokenExpiry();
70
+ if (!expiryTime) return true;
71
+ const now = Date.now();
72
+ return now >= expiryTime - 6e4;
73
+ }
74
+ /**
75
+ * 清除所有 tokens
76
+ */
77
+ clearTokens() {
78
+ this.storage.removeItem(this.config.tokenKeys.accessToken);
79
+ this.storage.removeItem(this.config.tokenKeys.refreshToken);
80
+ this.storage.removeItem(this.config.tokenKeys.tokenExpiry);
81
+ }
82
+ /**
83
+ * 检查是否有有效的认证信息
84
+ */
85
+ hasValidAuth() {
86
+ const accessToken = this.getAccessToken();
87
+ const refreshToken = this.getRefreshToken();
88
+ return !!(accessToken && !this.isAccessTokenExpired()) || !!refreshToken;
89
+ }
90
+ /**
91
+ * 获取配置
92
+ */
93
+ getConfig() {
94
+ return { ...this.config };
95
+ }
96
+ };
97
+ var instance = null;
98
+ function getTokenManager(config) {
99
+ if (!instance) {
100
+ instance = new TokenManager(void 0, config);
101
+ }
102
+ return instance;
103
+ }
104
+
105
+ // src/core/auth-redirect.ts
106
+ var ALLOWED_REDIRECT_DOMAINS = [
107
+ "yiminlab.site",
108
+ "jsontailor.yiminlab.site",
109
+ "ai.yiminlab.site",
110
+ "localhost"
111
+ ];
112
+ var AuthRedirect = class {
113
+ constructor(config) {
114
+ this.config = {
115
+ portalUrl: config?.portalUrl || DEFAULT_AUTH_CONFIG.portalUrl,
116
+ callbackPath: config?.callbackPath || DEFAULT_AUTH_CONFIG.callbackPath
117
+ };
118
+ }
119
+ /**
120
+ * 获取当前页面的完整 URL
121
+ */
122
+ getCurrentUrl() {
123
+ if (typeof window === "undefined") return "";
124
+ return window.location.href;
125
+ }
126
+ /**
127
+ * 获取当前页面的 origin
128
+ */
129
+ getCurrentOrigin() {
130
+ if (typeof window === "undefined") return "";
131
+ return window.location.origin;
132
+ }
133
+ /**
134
+ * 构建回调 URL
135
+ */
136
+ buildCallbackUrl() {
137
+ return `${this.getCurrentOrigin()}${this.config.callbackPath}`;
138
+ }
139
+ /**
140
+ * 构建登录跳转 URL
141
+ * @param returnPath 登录成功后返回的路径(默认当前页面)
142
+ */
143
+ buildLoginUrl(returnPath) {
144
+ const callbackUrl = this.buildCallbackUrl();
145
+ const loginUrl = new URL("/login", this.config.portalUrl);
146
+ loginUrl.searchParams.set("redirect", callbackUrl);
147
+ if (returnPath) {
148
+ loginUrl.searchParams.set("return", returnPath);
149
+ }
150
+ return loginUrl.toString();
151
+ }
152
+ /**
153
+ * 跳转到 Portal 登录页
154
+ * @param returnPath 登录成功后返回的路径
155
+ */
156
+ redirectToLogin(returnPath) {
157
+ if (typeof window === "undefined") return;
158
+ const currentPath = window.location.pathname + window.location.search;
159
+ const loginUrl = this.buildLoginUrl(returnPath || currentPath);
160
+ window.location.href = loginUrl;
161
+ }
162
+ /**
163
+ * 从 URL 参数中解析 Token
164
+ */
165
+ parseTokensFromUrl() {
166
+ if (typeof window === "undefined") return null;
167
+ const params = new URLSearchParams(window.location.search);
168
+ const accessToken = params.get("token");
169
+ const refreshToken = params.get("refresh");
170
+ const expiresInStr = params.get("expires");
171
+ const returnPath = params.get("return");
172
+ if (!accessToken || !refreshToken) {
173
+ return null;
174
+ }
175
+ return {
176
+ accessToken,
177
+ refreshToken,
178
+ expiresIn: expiresInStr ? parseInt(expiresInStr, 10) : 3600,
179
+ returnPath
180
+ };
181
+ }
182
+ /**
183
+ * 清除 URL 中的 Token 参数
184
+ */
185
+ clearTokensFromUrl() {
186
+ if (typeof window === "undefined") return;
187
+ const url = new URL(window.location.href);
188
+ url.searchParams.delete("token");
189
+ url.searchParams.delete("refresh");
190
+ url.searchParams.delete("expires");
191
+ url.searchParams.delete("return");
192
+ window.history.replaceState({}, "", url.pathname + url.search);
193
+ }
194
+ /**
195
+ * 验证跳转 URL 是否在白名单中
196
+ */
197
+ isAllowedRedirectUrl(url) {
198
+ try {
199
+ const { hostname } = new URL(url);
200
+ return ALLOWED_REDIRECT_DOMAINS.some(
201
+ (domain) => hostname === domain || hostname.endsWith("." + domain)
202
+ );
203
+ } catch {
204
+ return false;
205
+ }
206
+ }
207
+ };
208
+ var instance2 = null;
209
+ function getAuthRedirect(config) {
210
+ if (!instance2) {
211
+ instance2 = new AuthRedirect(config);
212
+ }
213
+ return instance2;
214
+ }
215
+
216
+ // src/core/authkit-client.ts
217
+ var AuthKitClient = class {
218
+ constructor(config) {
219
+ this.config = {
220
+ baseUrl: config.baseUrl || DEFAULT_AUTH_CONFIG.apiBaseUrl,
221
+ getAccessToken: config.getAccessToken
222
+ };
223
+ }
224
+ /**
225
+ * 构建请求头
226
+ */
227
+ buildHeaders() {
228
+ const headers = {
229
+ "Content-Type": "application/json"
230
+ };
231
+ const token = this.config.getAccessToken();
232
+ if (token) {
233
+ headers["Authorization"] = `Bearer ${token}`;
234
+ }
235
+ return headers;
236
+ }
237
+ /**
238
+ * 解析 API 响应为标准格式
239
+ */
240
+ parseTokenResponse(data) {
241
+ if (data.access_token) {
242
+ const expiresAt = new Date(Date.now() + data.expires_in * 1e3).toISOString();
243
+ return {
244
+ token: data.access_token,
245
+ expires_at: expiresAt,
246
+ scopes: data.scopes
247
+ };
248
+ }
249
+ throw new Error("Invalid response format");
250
+ }
251
+ /**
252
+ * 获取当前用户信息
253
+ */
254
+ async getMe() {
255
+ const response = await fetch(`${this.config.baseUrl}/api/auth/me`, {
256
+ method: "GET",
257
+ headers: this.buildHeaders()
258
+ });
259
+ if (!response.ok) {
260
+ const error = await response.json().catch(() => ({}));
261
+ throw new Error(error.error || error.message || `HTTP ${response.status}`);
262
+ }
263
+ return await response.json();
264
+ }
265
+ /**
266
+ * 获取全局 Scoped Token(自动创建/续期)
267
+ *
268
+ * @param scope 权限范围,如 'streamock:stream:read'
269
+ * @returns 短 token,如 'st_7kB2xM9pQr3n'
270
+ */
271
+ async getScopedToken(scope) {
272
+ const response = await fetch(
273
+ `${this.config.baseUrl}/api/auth/token/scoped?scope=${encodeURIComponent(scope)}`,
274
+ {
275
+ method: "GET",
276
+ headers: this.buildHeaders()
277
+ }
278
+ );
279
+ if (!response.ok) {
280
+ const error = await response.json().catch(() => ({}));
281
+ throw new Error(error.error || error.message || `HTTP ${response.status}`);
282
+ }
283
+ const data = await response.json();
284
+ return this.parseTokenResponse(data);
285
+ }
286
+ /**
287
+ * 轮换 Scoped Token(废弃旧的,生成新的)
288
+ *
289
+ * @param scope 权限范围,如 'streamock:stream:read'
290
+ * @returns 新的短 token
291
+ */
292
+ async rotateScopedToken(scope) {
293
+ const response = await fetch(
294
+ `${this.config.baseUrl}/api/auth/token/scoped/rotate?scope=${encodeURIComponent(scope)}`,
295
+ {
296
+ method: "POST",
297
+ headers: this.buildHeaders()
298
+ }
299
+ );
300
+ if (!response.ok) {
301
+ const error = await response.json().catch(() => ({}));
302
+ throw new Error(error.error || error.message || `HTTP ${response.status}`);
303
+ }
304
+ const data = await response.json();
305
+ return this.parseTokenResponse(data);
306
+ }
307
+ /**
308
+ * 创建 Scoped Token(短 token)- 保留兼容性
309
+ *
310
+ * @param scopes 权限范围,如 ['streamock:stream:read']
311
+ * @param expiresIn 过期时间(秒),默认 24 小时
312
+ * @returns 短 token,如 'st_7kB2xM9pQr3n'
313
+ * @deprecated 请使用 getScopedToken 获取全局 token
314
+ */
315
+ async createScopedToken(scopes, expiresIn = 86400) {
316
+ const response = await fetch(`${this.config.baseUrl}/api/auth/token/scoped`, {
317
+ method: "POST",
318
+ headers: this.buildHeaders(),
319
+ body: JSON.stringify({
320
+ scopes,
321
+ expires_in: expiresIn
322
+ })
323
+ });
324
+ if (!response.ok) {
325
+ const error = await response.json().catch(() => ({}));
326
+ throw new Error(error.error || error.message || `HTTP ${response.status}`);
327
+ }
328
+ const data = await response.json();
329
+ return this.parseTokenResponse(data);
330
+ }
331
+ };
332
+ var instance3 = null;
333
+ function getAuthKitClient(getAccessToken) {
334
+ if (!instance3) {
335
+ instance3 = new AuthKitClient({ getAccessToken });
336
+ }
337
+ return instance3;
338
+ }
339
+
340
+ // src/react/use-auth.ts
341
+ function useAuth(options = {}) {
342
+ const {
343
+ tokenManager = getTokenManager(options.config),
344
+ authRedirect = getAuthRedirect(options.config),
345
+ fetchUser = true
346
+ } = options;
347
+ const [authState, setAuthState] = useState({
348
+ isAuthenticated: false,
349
+ isLoading: true,
350
+ user: null,
351
+ error: null
352
+ });
353
+ const fetchUserInfo = useCallback(async () => {
354
+ try {
355
+ const client = getAuthKitClient(() => tokenManager.getAccessToken());
356
+ const user = await client.getMe();
357
+ setAuthState((prev) => ({
358
+ ...prev,
359
+ user,
360
+ error: null
361
+ }));
362
+ } catch (error) {
363
+ console.error("Failed to fetch user info:", error);
364
+ }
365
+ }, [tokenManager]);
366
+ const checkAuth = useCallback(async () => {
367
+ const hasValidAuth = tokenManager.hasValidAuth();
368
+ const accessToken = tokenManager.getAccessToken();
369
+ if (hasValidAuth && accessToken) {
370
+ setAuthState({
371
+ isAuthenticated: true,
372
+ isLoading: false,
373
+ user: null,
374
+ error: null
375
+ });
376
+ if (fetchUser) {
377
+ await fetchUserInfo();
378
+ }
379
+ } else {
380
+ setAuthState({
381
+ isAuthenticated: false,
382
+ isLoading: false,
383
+ user: null,
384
+ error: null
385
+ });
386
+ }
387
+ }, [tokenManager, fetchUser, fetchUserInfo]);
388
+ const login = useCallback(
389
+ (returnPath) => {
390
+ authRedirect.redirectToLogin(returnPath);
391
+ },
392
+ [authRedirect]
393
+ );
394
+ const logout = useCallback(() => {
395
+ tokenManager.clearTokens();
396
+ setAuthState({
397
+ isAuthenticated: false,
398
+ isLoading: false,
399
+ user: null,
400
+ error: null
401
+ });
402
+ }, [tokenManager]);
403
+ const getAccessToken = useCallback(() => {
404
+ return tokenManager.getAccessToken();
405
+ }, [tokenManager]);
406
+ const refresh = useCallback(() => {
407
+ checkAuth();
408
+ }, [checkAuth]);
409
+ const refreshUser = useCallback(async () => {
410
+ await fetchUserInfo();
411
+ }, [fetchUserInfo]);
412
+ useEffect(() => {
413
+ checkAuth();
414
+ }, [checkAuth]);
415
+ useEffect(() => {
416
+ const handleStorageChange = (event) => {
417
+ const config = tokenManager.getConfig();
418
+ if (event.key === config.tokenKeys.accessToken || event.key === config.tokenKeys.refreshToken) {
419
+ checkAuth();
420
+ }
421
+ };
422
+ window.addEventListener("storage", handleStorageChange);
423
+ return () => {
424
+ window.removeEventListener("storage", handleStorageChange);
425
+ };
426
+ }, [tokenManager, checkAuth]);
427
+ return useMemo(
428
+ () => ({
429
+ ...authState,
430
+ login,
431
+ logout,
432
+ getAccessToken,
433
+ refresh,
434
+ refreshUser
435
+ }),
436
+ [authState, login, logout, getAccessToken, refresh, refreshUser]
437
+ );
438
+ }
439
+ function useAccessToken() {
440
+ const { getAccessToken } = useAuth({ fetchUser: false });
441
+ return getAccessToken();
442
+ }
443
+
444
+ // src/react/auth-guard.tsx
445
+ import { useEffect as useEffect2 } from "react";
446
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
447
+ function DefaultLoading() {
448
+ return /* @__PURE__ */ jsxs("div", { style: {
449
+ display: "flex",
450
+ height: "50vh",
451
+ width: "100%",
452
+ alignItems: "center",
453
+ justifyContent: "center"
454
+ }, children: [
455
+ /* @__PURE__ */ jsx("div", { style: {
456
+ width: "32px",
457
+ height: "32px",
458
+ border: "3px solid #e5e7eb",
459
+ borderTopColor: "#3b82f6",
460
+ borderRadius: "50%",
461
+ animation: "spin 1s linear infinite"
462
+ } }),
463
+ /* @__PURE__ */ jsx("style", { children: `
464
+ @keyframes spin {
465
+ to { transform: rotate(360deg); }
466
+ }
467
+ ` })
468
+ ] });
469
+ }
470
+ function DefaultLoginPrompt({
471
+ onLogin,
472
+ title = "\u9700\u8981\u767B\u5F55",
473
+ description = "\u8BF7\u767B\u5F55\u4EE5\u7EE7\u7EED\u4F7F\u7528",
474
+ buttonText = "\u767B\u5F55"
475
+ }) {
476
+ return /* @__PURE__ */ jsxs("div", { style: {
477
+ display: "flex",
478
+ height: "50vh",
479
+ width: "100%",
480
+ flexDirection: "column",
481
+ alignItems: "center",
482
+ justifyContent: "center",
483
+ gap: "16px"
484
+ }, children: [
485
+ /* @__PURE__ */ jsxs("div", { style: { textAlign: "center" }, children: [
486
+ /* @__PURE__ */ jsx("h2", { style: {
487
+ fontSize: "1.5rem",
488
+ fontWeight: 600,
489
+ margin: 0
490
+ }, children: title }),
491
+ /* @__PURE__ */ jsx("p", { style: {
492
+ marginTop: "8px",
493
+ color: "#6b7280"
494
+ }, children: description })
495
+ ] }),
496
+ /* @__PURE__ */ jsx(
497
+ "button",
498
+ {
499
+ onClick: onLogin,
500
+ style: {
501
+ display: "inline-flex",
502
+ alignItems: "center",
503
+ justifyContent: "center",
504
+ padding: "10px 20px",
505
+ fontSize: "1rem",
506
+ fontWeight: 500,
507
+ backgroundColor: "#3b82f6",
508
+ color: "white",
509
+ border: "none",
510
+ borderRadius: "6px",
511
+ cursor: "pointer",
512
+ transition: "background-color 0.2s"
513
+ },
514
+ onMouseOver: (e) => e.currentTarget.style.backgroundColor = "#2563eb",
515
+ onMouseOut: (e) => e.currentTarget.style.backgroundColor = "#3b82f6",
516
+ children: buttonText
517
+ }
518
+ )
519
+ ] });
520
+ }
521
+ function AuthGuard({
522
+ children,
523
+ fallback = "prompt",
524
+ returnPath,
525
+ loadingContent,
526
+ promptContent,
527
+ promptTitle,
528
+ promptDescription,
529
+ loginButtonText,
530
+ authOptions
531
+ }) {
532
+ const { isAuthenticated, isLoading, login } = useAuth(authOptions);
533
+ useEffect2(() => {
534
+ if (!isLoading && !isAuthenticated && fallback === "redirect") {
535
+ login(returnPath);
536
+ }
537
+ }, [isLoading, isAuthenticated, fallback, login, returnPath]);
538
+ if (isLoading) {
539
+ return /* @__PURE__ */ jsx(Fragment, { children: loadingContent || /* @__PURE__ */ jsx(DefaultLoading, {}) });
540
+ }
541
+ if (!isAuthenticated) {
542
+ if (fallback === "redirect") {
543
+ return /* @__PURE__ */ jsx(Fragment, { children: loadingContent || /* @__PURE__ */ jsx(DefaultLoading, {}) });
544
+ }
545
+ return /* @__PURE__ */ jsx(Fragment, { children: promptContent || /* @__PURE__ */ jsx(
546
+ DefaultLoginPrompt,
547
+ {
548
+ onLogin: () => login(returnPath),
549
+ title: promptTitle,
550
+ description: promptDescription,
551
+ buttonText: loginButtonText
552
+ }
553
+ ) });
554
+ }
555
+ return /* @__PURE__ */ jsx(Fragment, { children });
556
+ }
557
+ function withAuthGuard(Component, guardProps) {
558
+ return function WrappedComponent(props) {
559
+ return /* @__PURE__ */ jsx(AuthGuard, { ...guardProps, children: /* @__PURE__ */ jsx(Component, { ...props }) });
560
+ };
561
+ }
562
+
563
+ // src/react/callback-handler.tsx
564
+ import { useEffect as useEffect3, useState as useState2 } from "react";
565
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
566
+ function DefaultLoading2() {
567
+ return /* @__PURE__ */ jsxs2("div", { style: {
568
+ display: "flex",
569
+ height: "100vh",
570
+ width: "100%",
571
+ alignItems: "center",
572
+ justifyContent: "center",
573
+ flexDirection: "column",
574
+ gap: "16px"
575
+ }, children: [
576
+ /* @__PURE__ */ jsx2("div", { style: {
577
+ width: "40px",
578
+ height: "40px",
579
+ border: "3px solid #e5e7eb",
580
+ borderTopColor: "#3b82f6",
581
+ borderRadius: "50%",
582
+ animation: "spin 1s linear infinite"
583
+ } }),
584
+ /* @__PURE__ */ jsx2("p", { style: { color: "#6b7280" }, children: "\u6B63\u5728\u5904\u7406\u767B\u5F55..." }),
585
+ /* @__PURE__ */ jsx2("style", { children: `
586
+ @keyframes spin {
587
+ to { transform: rotate(360deg); }
588
+ }
589
+ ` })
590
+ ] });
591
+ }
592
+ function DefaultError({ error, onRetry }) {
593
+ return /* @__PURE__ */ jsxs2("div", { style: {
594
+ display: "flex",
595
+ height: "100vh",
596
+ width: "100%",
597
+ alignItems: "center",
598
+ justifyContent: "center",
599
+ flexDirection: "column",
600
+ gap: "16px"
601
+ }, children: [
602
+ /* @__PURE__ */ jsx2("div", { style: {
603
+ color: "#ef4444",
604
+ fontSize: "48px"
605
+ }, children: "\u26A0\uFE0F" }),
606
+ /* @__PURE__ */ jsx2("h2", { style: { margin: 0 }, children: "\u767B\u5F55\u5931\u8D25" }),
607
+ /* @__PURE__ */ jsx2("p", { style: { color: "#6b7280", margin: 0 }, children: error }),
608
+ /* @__PURE__ */ jsx2(
609
+ "button",
610
+ {
611
+ onClick: onRetry,
612
+ style: {
613
+ padding: "10px 20px",
614
+ fontSize: "1rem",
615
+ backgroundColor: "#3b82f6",
616
+ color: "white",
617
+ border: "none",
618
+ borderRadius: "6px",
619
+ cursor: "pointer"
620
+ },
621
+ children: "\u91CD\u8BD5"
622
+ }
623
+ )
624
+ ] });
625
+ }
626
+ function CallbackHandler({
627
+ defaultRedirectPath = "/",
628
+ loadingContent,
629
+ errorContent,
630
+ config,
631
+ onSuccess,
632
+ onError
633
+ }) {
634
+ const [error, setError] = useState2(null);
635
+ useEffect3(() => {
636
+ const handleCallback = () => {
637
+ const tokenManager = getTokenManager(config);
638
+ const authRedirect = getAuthRedirect(config);
639
+ const tokens = authRedirect.parseTokensFromUrl();
640
+ if (!tokens || !tokens.accessToken || !tokens.refreshToken) {
641
+ const errorMsg = "\u672A\u627E\u5230\u8BA4\u8BC1\u4FE1\u606F";
642
+ setError(errorMsg);
643
+ onError?.(errorMsg);
644
+ return;
645
+ }
646
+ tokenManager.setTokens(
647
+ tokens.accessToken,
648
+ tokens.refreshToken,
649
+ tokens.expiresIn || 3600
650
+ );
651
+ authRedirect.clearTokensFromUrl();
652
+ onSuccess?.();
653
+ const redirectPath = tokens.returnPath || defaultRedirectPath;
654
+ window.location.href = redirectPath;
655
+ };
656
+ handleCallback();
657
+ }, [defaultRedirectPath, config, onSuccess, onError]);
658
+ const handleRetry = () => {
659
+ const authRedirect = getAuthRedirect(config);
660
+ authRedirect.redirectToLogin(defaultRedirectPath);
661
+ };
662
+ if (error) {
663
+ if (typeof errorContent === "function") {
664
+ return /* @__PURE__ */ jsx2(Fragment2, { children: errorContent(error) });
665
+ }
666
+ return /* @__PURE__ */ jsx2(Fragment2, { children: errorContent || /* @__PURE__ */ jsx2(DefaultError, { error, onRetry: handleRetry }) });
667
+ }
668
+ return /* @__PURE__ */ jsx2(Fragment2, { children: loadingContent || /* @__PURE__ */ jsx2(DefaultLoading2, {}) });
669
+ }
670
+ export {
671
+ AuthGuard,
672
+ CallbackHandler,
673
+ useAccessToken,
674
+ useAuth,
675
+ withAuthGuard
676
+ };
677
+ //# sourceMappingURL=index.mjs.map