@bagelink/auth 1.7.72 → 1.7.76
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/README.md +332 -244
- package/dist/index.cjs +307 -74
- package/dist/index.d.ts +3 -0
- package/dist/index.mjs +307 -74
- package/dist/redirect.d.ts +21 -0
- package/dist/router.d.ts +36 -0
- package/dist/types/redirect.d.ts +70 -0
- package/dist/useAuth.d.ts +57 -0
- package/package.json +1 -1
- package/src/index.ts +10 -2
- package/src/redirect.ts +95 -0
- package/src/router.ts +129 -0
- package/src/types/redirect.ts +96 -0
- package/src/useAuth.ts +128 -1
package/dist/index.mjs
CHANGED
|
@@ -1077,7 +1077,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|
|
1077
1077
|
const authResponse = ref(null);
|
|
1078
1078
|
const { sso: sso2, user, accountInfo: accountInfo2 } = useAuth();
|
|
1079
1079
|
const route = useRoute();
|
|
1080
|
-
const
|
|
1080
|
+
const router2 = useRouter();
|
|
1081
1081
|
const providerInfo = computed(() => {
|
|
1082
1082
|
if (provider.value === null) return null;
|
|
1083
1083
|
return providers[provider.value];
|
|
@@ -1087,7 +1087,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|
|
1087
1087
|
try {
|
|
1088
1088
|
await sso2.handleLinkCallback();
|
|
1089
1089
|
success.value = true;
|
|
1090
|
-
setTimeout(() =>
|
|
1090
|
+
setTimeout(() => router2.push("/"), timeout);
|
|
1091
1091
|
} catch (err) {
|
|
1092
1092
|
const errorMessage = err instanceof Error ? err.message : "Failed to link account";
|
|
1093
1093
|
error.value = errorMessage;
|
|
@@ -1106,7 +1106,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
|
|
|
1106
1106
|
} else {
|
|
1107
1107
|
authResponse.value = response;
|
|
1108
1108
|
success.value = true;
|
|
1109
|
-
setTimeout(() =>
|
|
1109
|
+
setTimeout(() => router2.push("/"), timeout);
|
|
1110
1110
|
}
|
|
1111
1111
|
} catch (err) {
|
|
1112
1112
|
const errorMessage = err instanceof Error ? err.message : "Authentication failed";
|
|
@@ -1237,10 +1237,10 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
|
|
|
1237
1237
|
cardShadow: { type: Boolean, default: true }
|
|
1238
1238
|
},
|
|
1239
1239
|
setup(__props) {
|
|
1240
|
-
const
|
|
1240
|
+
const router2 = useRouter();
|
|
1241
1241
|
function switchForm(form) {
|
|
1242
1242
|
if (form === "login") {
|
|
1243
|
-
|
|
1243
|
+
router2.push("/login");
|
|
1244
1244
|
}
|
|
1245
1245
|
}
|
|
1246
1246
|
return (_ctx, _cache) => {
|
|
@@ -1281,12 +1281,12 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|
|
1281
1281
|
cardShadow: { type: Boolean, default: true }
|
|
1282
1282
|
},
|
|
1283
1283
|
setup(__props) {
|
|
1284
|
-
const
|
|
1284
|
+
const router2 = useRouter();
|
|
1285
1285
|
function switchForm(form) {
|
|
1286
1286
|
if (form === "signup") {
|
|
1287
|
-
|
|
1287
|
+
router2.push("/signup");
|
|
1288
1288
|
} else if (form === "forgot-password") {
|
|
1289
|
-
|
|
1289
|
+
router2.push("/forgot-password");
|
|
1290
1290
|
}
|
|
1291
1291
|
}
|
|
1292
1292
|
return (_ctx, _cache) => {
|
|
@@ -1327,12 +1327,12 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
|
|
|
1327
1327
|
cardShadow: { type: Boolean, default: true }
|
|
1328
1328
|
},
|
|
1329
1329
|
setup(__props) {
|
|
1330
|
-
const
|
|
1330
|
+
const router2 = useRouter();
|
|
1331
1331
|
const route = useRoute();
|
|
1332
1332
|
const token = computed(() => route.query.token);
|
|
1333
1333
|
function switchForm(form) {
|
|
1334
1334
|
if (form === "login") {
|
|
1335
|
-
|
|
1335
|
+
router2.push("/login");
|
|
1336
1336
|
}
|
|
1337
1337
|
}
|
|
1338
1338
|
return (_ctx, _cache) => {
|
|
@@ -1364,10 +1364,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1364
1364
|
cardShadow: { type: Boolean, default: true }
|
|
1365
1365
|
},
|
|
1366
1366
|
setup(__props) {
|
|
1367
|
-
const
|
|
1367
|
+
const router2 = useRouter();
|
|
1368
1368
|
function switchForm(form) {
|
|
1369
1369
|
if (form === "login") {
|
|
1370
|
-
|
|
1370
|
+
router2.push("/login");
|
|
1371
1371
|
}
|
|
1372
1372
|
}
|
|
1373
1373
|
return (_ctx, _cache) => {
|
|
@@ -1389,70 +1389,56 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1389
1389
|
};
|
|
1390
1390
|
}
|
|
1391
1391
|
});
|
|
1392
|
-
function
|
|
1393
|
-
const
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
const createRouteName = (name) => namePrefix ? `${namePrefix}${name}` : name;
|
|
1400
|
-
const routes = [
|
|
1401
|
-
{
|
|
1402
|
-
path: `${basePath}/login`,
|
|
1403
|
-
name: routeNames.login || createRouteName("Login"),
|
|
1404
|
-
component: () => import("./LoginPage-klj1NV4J.js"),
|
|
1405
|
-
meta: { requiresAuth: false }
|
|
1406
|
-
},
|
|
1407
|
-
{
|
|
1408
|
-
path: `${basePath}/signup`,
|
|
1409
|
-
name: routeNames.signup || createRouteName("Signup"),
|
|
1410
|
-
component: () => import("./SignupPage-oUFYApYW.js"),
|
|
1411
|
-
meta: { requiresAuth: false }
|
|
1412
|
-
},
|
|
1413
|
-
{
|
|
1414
|
-
path: `${basePath}/forgot-password`,
|
|
1415
|
-
name: routeNames.forgotPassword || createRouteName("ForgotPassword"),
|
|
1416
|
-
component: () => import("./ForgotPasswordPage-DvttMGb0.js"),
|
|
1417
|
-
meta: { requiresAuth: false }
|
|
1418
|
-
},
|
|
1419
|
-
{
|
|
1420
|
-
path: `${basePath}/reset-password`,
|
|
1421
|
-
name: routeNames.resetPassword || createRouteName("ResetPassword"),
|
|
1422
|
-
component: () => import("./ResetPasswordPage-nvQ4uupb.js"),
|
|
1423
|
-
meta: { requiresAuth: false }
|
|
1424
|
-
},
|
|
1425
|
-
{
|
|
1426
|
-
path: `${basePath}/callback`,
|
|
1427
|
-
name: routeNames.callback || createRouteName("AuthCallback"),
|
|
1428
|
-
component: () => import("./Callback-C-XghN_z.js"),
|
|
1429
|
-
meta: { requiresAuth: false }
|
|
1430
|
-
}
|
|
1431
|
-
];
|
|
1432
|
-
if (layout) {
|
|
1433
|
-
return [{
|
|
1434
|
-
path: basePath,
|
|
1435
|
-
component: layout,
|
|
1436
|
-
children: routes.map((route) => ({
|
|
1437
|
-
...route,
|
|
1438
|
-
path: route.path.replace(basePath, "")
|
|
1439
|
-
}))
|
|
1440
|
-
}];
|
|
1392
|
+
function getRedirectUrl(router2, config) {
|
|
1393
|
+
const redirect2 = router2.currentRoute.value.query[config.queryKey];
|
|
1394
|
+
return redirect2 || config.fallback;
|
|
1395
|
+
}
|
|
1396
|
+
function isValidRedirect(redirectUrl, allowedPaths) {
|
|
1397
|
+
if (!redirectUrl) {
|
|
1398
|
+
return false;
|
|
1441
1399
|
}
|
|
1442
|
-
|
|
1400
|
+
if (redirectUrl.startsWith("http://") || redirectUrl.startsWith("https://")) {
|
|
1401
|
+
return false;
|
|
1402
|
+
}
|
|
1403
|
+
if (redirectUrl.startsWith("//")) {
|
|
1404
|
+
return false;
|
|
1405
|
+
}
|
|
1406
|
+
if (redirectUrl.startsWith("javascript:") || redirectUrl.startsWith("data:")) {
|
|
1407
|
+
return false;
|
|
1408
|
+
}
|
|
1409
|
+
if (!redirectUrl.startsWith("/")) {
|
|
1410
|
+
return false;
|
|
1411
|
+
}
|
|
1412
|
+
if (allowedPaths && allowedPaths.length > 0) {
|
|
1413
|
+
return allowedPaths.some((pattern) => pattern.test(redirectUrl));
|
|
1414
|
+
}
|
|
1415
|
+
return true;
|
|
1443
1416
|
}
|
|
1444
|
-
function
|
|
1445
|
-
const
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
next();
|
|
1453
|
-
}
|
|
1454
|
-
};
|
|
1417
|
+
async function performRedirect(router2, config) {
|
|
1418
|
+
const redirect2 = getRedirectUrl(router2, config);
|
|
1419
|
+
if (redirect2 !== config.fallback && !isValidRedirect(redirect2, config.allowedPaths)) {
|
|
1420
|
+
console.warn("[Auth] Invalid redirect URL detected, using fallback:", redirect2);
|
|
1421
|
+
await router2.push(config.fallback);
|
|
1422
|
+
return;
|
|
1423
|
+
}
|
|
1424
|
+
await router2.push(redirect2);
|
|
1455
1425
|
}
|
|
1426
|
+
function buildLoginQuery(currentPath, config) {
|
|
1427
|
+
if (!config.preserveRedirect) {
|
|
1428
|
+
return {};
|
|
1429
|
+
}
|
|
1430
|
+
if (isValidRedirect(currentPath, config.allowedPaths)) {
|
|
1431
|
+
return { [config.queryKey]: currentPath };
|
|
1432
|
+
}
|
|
1433
|
+
return {};
|
|
1434
|
+
}
|
|
1435
|
+
const redirect = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1436
|
+
__proto__: null,
|
|
1437
|
+
buildLoginQuery,
|
|
1438
|
+
getRedirectUrl,
|
|
1439
|
+
isValidRedirect,
|
|
1440
|
+
performRedirect
|
|
1441
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
1456
1442
|
let authApiRef = null;
|
|
1457
1443
|
function setAuthContext(authApi2) {
|
|
1458
1444
|
authApiRef = authApi2;
|
|
@@ -1900,9 +1886,34 @@ function accountToUser(account) {
|
|
|
1900
1886
|
lastLogin: account.last_login
|
|
1901
1887
|
};
|
|
1902
1888
|
}
|
|
1889
|
+
const DEFAULT_REDIRECT_CONFIG = {
|
|
1890
|
+
queryKey: "redirect",
|
|
1891
|
+
fallback: "/",
|
|
1892
|
+
noAuthRoutes: ["Login", "Signup", "ForgotPassword", "ResetPassword", "Callback"],
|
|
1893
|
+
authenticatedRedirect: "/",
|
|
1894
|
+
loginRoute: "Login",
|
|
1895
|
+
authMetaKey: "auth",
|
|
1896
|
+
autoRedirect: true,
|
|
1897
|
+
preserveRedirect: true
|
|
1898
|
+
};
|
|
1899
|
+
function normalizeRedirectConfig(config) {
|
|
1900
|
+
return {
|
|
1901
|
+
...DEFAULT_REDIRECT_CONFIG,
|
|
1902
|
+
...config
|
|
1903
|
+
};
|
|
1904
|
+
}
|
|
1903
1905
|
let authApi = null;
|
|
1904
1906
|
let eventEmitter = null;
|
|
1907
|
+
let redirectConfig = null;
|
|
1908
|
+
let autoRedirectRouter = null;
|
|
1909
|
+
let cachedAuthGuard = null;
|
|
1905
1910
|
const accountInfo = ref(null);
|
|
1911
|
+
function getRedirectConfig() {
|
|
1912
|
+
if (!redirectConfig) {
|
|
1913
|
+
throw new Error("Redirect config not initialized. Did you call createAuth with redirect config?");
|
|
1914
|
+
}
|
|
1915
|
+
return redirectConfig;
|
|
1916
|
+
}
|
|
1906
1917
|
function createAuth(params) {
|
|
1907
1918
|
if (authApi === null) {
|
|
1908
1919
|
authApi = new AuthApi(params.baseURL);
|
|
@@ -1910,7 +1921,13 @@ function createAuth(params) {
|
|
|
1910
1921
|
if (eventEmitter === null) {
|
|
1911
1922
|
eventEmitter = new EventEmitter();
|
|
1912
1923
|
}
|
|
1913
|
-
|
|
1924
|
+
if (params.redirect) {
|
|
1925
|
+
redirectConfig = normalizeRedirectConfig(params.redirect);
|
|
1926
|
+
}
|
|
1927
|
+
if (redirectConfig == null ? void 0 : redirectConfig.autoRedirect) {
|
|
1928
|
+
setupAutoRedirect();
|
|
1929
|
+
}
|
|
1930
|
+
const authInstance = {
|
|
1914
1931
|
// Event listener methods
|
|
1915
1932
|
on(event, handler) {
|
|
1916
1933
|
if (eventEmitter) {
|
|
@@ -1927,10 +1944,89 @@ function createAuth(params) {
|
|
|
1927
1944
|
eventEmitter.removeAllListeners(event);
|
|
1928
1945
|
}
|
|
1929
1946
|
},
|
|
1947
|
+
/**
|
|
1948
|
+
* Connect external dependencies like Vue Router
|
|
1949
|
+
* Automatically sets up router guard when router is provided
|
|
1950
|
+
* @param dependency - Vue Router instance or other plugins
|
|
1951
|
+
* @param options - Configuration options
|
|
1952
|
+
* @param options.guard - Whether to automatically set up auth guard (default: true)
|
|
1953
|
+
* @example
|
|
1954
|
+
* ```ts
|
|
1955
|
+
* // Auto setup (default)
|
|
1956
|
+
* auth.use(router)
|
|
1957
|
+
*
|
|
1958
|
+
* // Manual guard control (for custom composition)
|
|
1959
|
+
* auth.use(router, { guard: false })
|
|
1960
|
+
* router.beforeEach(async (to, from, next) => {
|
|
1961
|
+
* // Custom logic first
|
|
1962
|
+
* if (!hasOrgAccess(to)) return next('/no-access')
|
|
1963
|
+
* // Then run auth guard
|
|
1964
|
+
* return auth.routerGuard()(to, from, next)
|
|
1965
|
+
* })
|
|
1966
|
+
* ```
|
|
1967
|
+
*/
|
|
1968
|
+
use(dependency, options = {}) {
|
|
1969
|
+
const { guard = true } = options;
|
|
1970
|
+
if (dependency && (dependency.beforeEach || dependency.push || dependency.currentRoute)) {
|
|
1971
|
+
autoRedirectRouter = dependency;
|
|
1972
|
+
if (guard) {
|
|
1973
|
+
dependency.beforeEach(authInstance.routerGuard());
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1976
|
+
return authInstance;
|
|
1977
|
+
},
|
|
1978
|
+
/**
|
|
1979
|
+
* Create a Vue Router navigation guard for authentication
|
|
1980
|
+
* Protects routes requiring authentication and handles redirect logic
|
|
1981
|
+
* Note: Automatically called by auth.use(router), only use directly for custom setups
|
|
1982
|
+
* @example
|
|
1983
|
+
* ```ts
|
|
1984
|
+
* // Automatic (recommended)
|
|
1985
|
+
* auth.use(router)
|
|
1986
|
+
*
|
|
1987
|
+
* // Manual (for custom setups)
|
|
1988
|
+
* router.beforeEach(auth.routerGuard())
|
|
1989
|
+
* ```
|
|
1990
|
+
*/
|
|
1991
|
+
routerGuard() {
|
|
1992
|
+
if (cachedAuthGuard === null) {
|
|
1993
|
+
cachedAuthGuard = async (to, from, next) => {
|
|
1994
|
+
const { authGuard: authGuard2 } = await Promise.resolve().then(() => router);
|
|
1995
|
+
const guard = authGuard2();
|
|
1996
|
+
cachedAuthGuard = guard;
|
|
1997
|
+
return guard(to, from, next);
|
|
1998
|
+
};
|
|
1999
|
+
}
|
|
2000
|
+
return cachedAuthGuard;
|
|
2001
|
+
},
|
|
2002
|
+
/**
|
|
2003
|
+
* Vue plugin install method
|
|
2004
|
+
* Makes auth available globally as $auth
|
|
2005
|
+
* @example
|
|
2006
|
+
* ```ts
|
|
2007
|
+
* app.use(auth)
|
|
2008
|
+
* ```
|
|
2009
|
+
*/
|
|
1930
2010
|
install(app) {
|
|
1931
2011
|
app.config.globalProperties.$auth = useAuth();
|
|
1932
2012
|
}
|
|
1933
2013
|
};
|
|
2014
|
+
return authInstance;
|
|
2015
|
+
}
|
|
2016
|
+
function setupAutoRedirect() {
|
|
2017
|
+
if (!eventEmitter || !redirectConfig) return;
|
|
2018
|
+
eventEmitter.on(AuthState.LOGIN, async () => {
|
|
2019
|
+
if (!autoRedirectRouter) {
|
|
2020
|
+
console.warn("[Auth] Auto-redirect enabled but router not set. Call setAuthRouter(router) in your app setup.");
|
|
2021
|
+
return;
|
|
2022
|
+
}
|
|
2023
|
+
const { performRedirect: performRedirect2 } = await Promise.resolve().then(() => redirect);
|
|
2024
|
+
try {
|
|
2025
|
+
await performRedirect2(autoRedirectRouter, redirectConfig);
|
|
2026
|
+
} catch (error) {
|
|
2027
|
+
console.error("[Auth] Auto-redirect error:", error);
|
|
2028
|
+
}
|
|
2029
|
+
});
|
|
1934
2030
|
}
|
|
1935
2031
|
function useAuth() {
|
|
1936
2032
|
if (authApi === null) {
|
|
@@ -2180,13 +2276,141 @@ function useAuth() {
|
|
|
2180
2276
|
const useAuth$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2181
2277
|
__proto__: null,
|
|
2182
2278
|
createAuth,
|
|
2279
|
+
getRedirectConfig,
|
|
2183
2280
|
useAuth
|
|
2184
2281
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2282
|
+
let authInitialized = false;
|
|
2283
|
+
function resetAuthState() {
|
|
2284
|
+
authInitialized = false;
|
|
2285
|
+
}
|
|
2286
|
+
function authGuard() {
|
|
2287
|
+
return async function guard(to, _from, next) {
|
|
2288
|
+
const auth = useAuth();
|
|
2289
|
+
const config = getRedirectConfig();
|
|
2290
|
+
const requiresAuth = to.meta[config.authMetaKey];
|
|
2291
|
+
const requiresNoAuth = config.noAuthRoutes.includes(to.name);
|
|
2292
|
+
try {
|
|
2293
|
+
if (!authInitialized) {
|
|
2294
|
+
await auth.checkAuth();
|
|
2295
|
+
authInitialized = true;
|
|
2296
|
+
}
|
|
2297
|
+
const isAuthenticated = !!auth.user.value;
|
|
2298
|
+
if (isAuthenticated && requiresNoAuth) {
|
|
2299
|
+
next(config.authenticatedRedirect);
|
|
2300
|
+
return;
|
|
2301
|
+
}
|
|
2302
|
+
if (!isAuthenticated && requiresAuth) {
|
|
2303
|
+
const query = buildLoginQuery(to.fullPath, config);
|
|
2304
|
+
next({
|
|
2305
|
+
name: config.loginRoute,
|
|
2306
|
+
query
|
|
2307
|
+
});
|
|
2308
|
+
return;
|
|
2309
|
+
}
|
|
2310
|
+
next();
|
|
2311
|
+
} catch (error) {
|
|
2312
|
+
console.error("[Auth Guard] Error:", error);
|
|
2313
|
+
next();
|
|
2314
|
+
}
|
|
2315
|
+
};
|
|
2316
|
+
}
|
|
2317
|
+
function composeGuards(guards) {
|
|
2318
|
+
return async (to, from, next) => {
|
|
2319
|
+
let guardIndex = 0;
|
|
2320
|
+
const runNextGuard = async () => {
|
|
2321
|
+
if (guardIndex >= guards.length) {
|
|
2322
|
+
next();
|
|
2323
|
+
return;
|
|
2324
|
+
}
|
|
2325
|
+
const guard = guards[guardIndex];
|
|
2326
|
+
guardIndex++;
|
|
2327
|
+
await guard(to, from, (result) => {
|
|
2328
|
+
if (result !== void 0) {
|
|
2329
|
+
next(result);
|
|
2330
|
+
} else {
|
|
2331
|
+
runNextGuard();
|
|
2332
|
+
}
|
|
2333
|
+
});
|
|
2334
|
+
};
|
|
2335
|
+
await runNextGuard();
|
|
2336
|
+
};
|
|
2337
|
+
}
|
|
2338
|
+
const router = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2339
|
+
__proto__: null,
|
|
2340
|
+
authGuard,
|
|
2341
|
+
composeGuards,
|
|
2342
|
+
resetAuthState
|
|
2343
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
2344
|
+
function createAuthRoutes(config = {}) {
|
|
2345
|
+
const {
|
|
2346
|
+
basePath = "",
|
|
2347
|
+
namePrefix = "",
|
|
2348
|
+
routeNames = {},
|
|
2349
|
+
layout
|
|
2350
|
+
} = config;
|
|
2351
|
+
const createRouteName = (name) => namePrefix ? `${namePrefix}${name}` : name;
|
|
2352
|
+
const routes = [
|
|
2353
|
+
{
|
|
2354
|
+
path: `${basePath}/login`,
|
|
2355
|
+
name: routeNames.login || createRouteName("Login"),
|
|
2356
|
+
component: () => import("./LoginPage-klj1NV4J.js"),
|
|
2357
|
+
meta: { requiresAuth: false }
|
|
2358
|
+
},
|
|
2359
|
+
{
|
|
2360
|
+
path: `${basePath}/signup`,
|
|
2361
|
+
name: routeNames.signup || createRouteName("Signup"),
|
|
2362
|
+
component: () => import("./SignupPage-oUFYApYW.js"),
|
|
2363
|
+
meta: { requiresAuth: false }
|
|
2364
|
+
},
|
|
2365
|
+
{
|
|
2366
|
+
path: `${basePath}/forgot-password`,
|
|
2367
|
+
name: routeNames.forgotPassword || createRouteName("ForgotPassword"),
|
|
2368
|
+
component: () => import("./ForgotPasswordPage-DvttMGb0.js"),
|
|
2369
|
+
meta: { requiresAuth: false }
|
|
2370
|
+
},
|
|
2371
|
+
{
|
|
2372
|
+
path: `${basePath}/reset-password`,
|
|
2373
|
+
name: routeNames.resetPassword || createRouteName("ResetPassword"),
|
|
2374
|
+
component: () => import("./ResetPasswordPage-nvQ4uupb.js"),
|
|
2375
|
+
meta: { requiresAuth: false }
|
|
2376
|
+
},
|
|
2377
|
+
{
|
|
2378
|
+
path: `${basePath}/callback`,
|
|
2379
|
+
name: routeNames.callback || createRouteName("AuthCallback"),
|
|
2380
|
+
component: () => import("./Callback-C-XghN_z.js"),
|
|
2381
|
+
meta: { requiresAuth: false }
|
|
2382
|
+
}
|
|
2383
|
+
];
|
|
2384
|
+
if (layout) {
|
|
2385
|
+
return [{
|
|
2386
|
+
path: basePath,
|
|
2387
|
+
component: layout,
|
|
2388
|
+
children: routes.map((route) => ({
|
|
2389
|
+
...route,
|
|
2390
|
+
path: route.path.replace(basePath, "")
|
|
2391
|
+
}))
|
|
2392
|
+
}];
|
|
2393
|
+
}
|
|
2394
|
+
return routes;
|
|
2395
|
+
}
|
|
2396
|
+
function createAuthGuard(config = {}) {
|
|
2397
|
+
const { redirectTo = "/" } = config;
|
|
2398
|
+
return async (to, _from, next) => {
|
|
2399
|
+
const { useAuth: useAuth2 } = await Promise.resolve().then(() => useAuth$1);
|
|
2400
|
+
const { user } = useAuth2();
|
|
2401
|
+
if (to.meta.requiresAuth === false && user.value) {
|
|
2402
|
+
next(redirectTo);
|
|
2403
|
+
} else {
|
|
2404
|
+
next();
|
|
2405
|
+
}
|
|
2406
|
+
};
|
|
2407
|
+
}
|
|
2185
2408
|
export {
|
|
2186
2409
|
AuthApi,
|
|
2187
2410
|
AuthState,
|
|
2188
2411
|
_sfc_main$4 as Callback,
|
|
2189
2412
|
DEFAULT_AGENT_ID,
|
|
2413
|
+
DEFAULT_REDIRECT_CONFIG,
|
|
2190
2414
|
_sfc_main$8 as ForgotPasswordForm,
|
|
2191
2415
|
_sfc_main$3 as ForgotPasswordPage,
|
|
2192
2416
|
INTAKE_WORKFLOW_ID,
|
|
@@ -2202,13 +2426,22 @@ export {
|
|
|
2202
2426
|
_sfc_main as SignupPage,
|
|
2203
2427
|
StateMismatchError,
|
|
2204
2428
|
accountToUser,
|
|
2429
|
+
authGuard,
|
|
2430
|
+
buildLoginQuery,
|
|
2431
|
+
composeGuards,
|
|
2205
2432
|
createAuth,
|
|
2206
2433
|
createAuthGuard,
|
|
2207
2434
|
createAuthRoutes,
|
|
2208
2435
|
getAllSSOProviders,
|
|
2436
|
+
getRedirectConfig,
|
|
2437
|
+
getRedirectUrl,
|
|
2209
2438
|
getSSOProvider,
|
|
2210
2439
|
isSupportedProvider,
|
|
2440
|
+
isValidRedirect,
|
|
2441
|
+
normalizeRedirectConfig,
|
|
2442
|
+
performRedirect,
|
|
2211
2443
|
providers,
|
|
2444
|
+
resetAuthState,
|
|
2212
2445
|
setAuthContext,
|
|
2213
2446
|
sso,
|
|
2214
2447
|
ssoProvidersList,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Router } from 'vue-router';
|
|
2
|
+
import { NormalizedRedirectConfig } from './types/redirect';
|
|
3
|
+
/**
|
|
4
|
+
* Redirect utilities for handling post-authentication navigation
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Get redirect URL from current route query params
|
|
8
|
+
*/
|
|
9
|
+
export declare function getRedirectUrl(router: Router, config: NormalizedRedirectConfig): string;
|
|
10
|
+
/**
|
|
11
|
+
* Validate redirect URL is safe (prevents open redirect attacks)
|
|
12
|
+
*/
|
|
13
|
+
export declare function isValidRedirect(redirectUrl: string, allowedPaths?: RegExp[]): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Perform redirect after login with security validation
|
|
16
|
+
*/
|
|
17
|
+
export declare function performRedirect(router: Router, config: NormalizedRedirectConfig): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Build query params for redirect to login
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildLoginQuery(currentPath: string, config: NormalizedRedirectConfig): Record<string, string>;
|
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { NavigationGuard, NavigationGuardNext, RouteLocationNormalized } from 'vue-router';
|
|
2
|
+
/**
|
|
3
|
+
* Reset auth initialization state
|
|
4
|
+
* Useful for testing or app reload scenarios
|
|
5
|
+
*/
|
|
6
|
+
export declare function resetAuthState(): void;
|
|
7
|
+
/**
|
|
8
|
+
* Auth guard for Vue Router
|
|
9
|
+
*
|
|
10
|
+
* Protects routes requiring authentication and handles redirect logic.
|
|
11
|
+
* Reads configuration from the auth instance created via createAuth().
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* const auth = createAuth({
|
|
16
|
+
* baseURL: 'https://api.example.com',
|
|
17
|
+
* redirect: { ... }
|
|
18
|
+
* })
|
|
19
|
+
* router.beforeEach(authGuard())
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare function authGuard(): (to: RouteLocationNormalized, _from: RouteLocationNormalized, next: NavigationGuardNext) => Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Compose multiple navigation guards into one
|
|
25
|
+
* Guards are executed in order, stopping at the first one that calls next with a value
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* router.beforeEach(composeGuards([
|
|
30
|
+
* authGuard(),
|
|
31
|
+
* orgAccessGuard(),
|
|
32
|
+
* featureFlagGuard(),
|
|
33
|
+
* ]))
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function composeGuards(guards: NavigationGuard[]): NavigationGuard;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redirect configuration types for auth library
|
|
3
|
+
*/
|
|
4
|
+
export interface RedirectConfig {
|
|
5
|
+
/**
|
|
6
|
+
* Query parameter key used to store the redirect URL
|
|
7
|
+
* After login, read this param to redirect users back to their intended destination
|
|
8
|
+
* @default 'redirect'
|
|
9
|
+
*/
|
|
10
|
+
queryKey?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Default fallback URL when no redirect is specified
|
|
13
|
+
* @default '/'
|
|
14
|
+
*/
|
|
15
|
+
fallback?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Routes that require NO authentication (login, signup, forgot password, etc)
|
|
18
|
+
* Authenticated users will be automatically redirected away from these pages
|
|
19
|
+
* @default ['Login', 'Signup', 'ForgotPassword', 'ResetPassword', 'Callback']
|
|
20
|
+
*/
|
|
21
|
+
noAuthRoutes?: string[];
|
|
22
|
+
/**
|
|
23
|
+
* Route name to redirect to when authenticated users try to access auth-only pages
|
|
24
|
+
* @default '/'
|
|
25
|
+
*/
|
|
26
|
+
authenticatedRedirect?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Route name to redirect to when unauthenticated users try to access protected pages
|
|
29
|
+
* @default 'Login'
|
|
30
|
+
*/
|
|
31
|
+
loginRoute?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Meta key used to check if a route requires authentication
|
|
34
|
+
* @default 'auth'
|
|
35
|
+
* @example In your route: `meta: { auth: true }`
|
|
36
|
+
*/
|
|
37
|
+
authMetaKey?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Enable automatic redirect handling after login
|
|
40
|
+
* When true, the library automatically redirects users after successful login
|
|
41
|
+
* @default true
|
|
42
|
+
*/
|
|
43
|
+
autoRedirect?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Enable redirect preservation for protected routes
|
|
46
|
+
* When enabled, the original URL is preserved as a query param after redirecting to login
|
|
47
|
+
* @default true
|
|
48
|
+
*/
|
|
49
|
+
preserveRedirect?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Optional allowed redirect path patterns for security validation
|
|
52
|
+
* If specified, only URLs matching these patterns will be allowed
|
|
53
|
+
* @default undefined (allows all internal paths)
|
|
54
|
+
*/
|
|
55
|
+
allowedPaths?: RegExp[];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Normalized redirect configuration with all defaults applied
|
|
59
|
+
*/
|
|
60
|
+
export interface NormalizedRedirectConfig extends Required<Omit<RedirectConfig, 'allowedPaths'>> {
|
|
61
|
+
allowedPaths?: RegExp[];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Default redirect configuration
|
|
65
|
+
*/
|
|
66
|
+
export declare const DEFAULT_REDIRECT_CONFIG: NormalizedRedirectConfig;
|
|
67
|
+
/**
|
|
68
|
+
* Normalize redirect configuration by applying defaults
|
|
69
|
+
*/
|
|
70
|
+
export declare function normalizeRedirectConfig(config?: RedirectConfig): NormalizedRedirectConfig;
|
package/dist/useAuth.d.ts
CHANGED
|
@@ -1,12 +1,69 @@
|
|
|
1
1
|
import { App } from 'vue';
|
|
2
2
|
import { AccountInfo, User, NewUser, UpdatePasswordForm, UpdateAccountRequest, AuthEventMap, SSOProvider, SSOInitiateRequest, SSOCallbackRequest, SSOLinkRequest, AuthState } from './types';
|
|
3
|
+
import { RedirectConfig, NormalizedRedirectConfig } from './types/redirect';
|
|
3
4
|
interface InitParams {
|
|
4
5
|
baseURL: string;
|
|
6
|
+
/**
|
|
7
|
+
* Redirect configuration for authentication flows
|
|
8
|
+
* @see RedirectConfig
|
|
9
|
+
*/
|
|
10
|
+
redirect?: RedirectConfig;
|
|
5
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Get the current redirect configuration
|
|
14
|
+
* Used internally by router guard
|
|
15
|
+
*/
|
|
16
|
+
export declare function getRedirectConfig(): NormalizedRedirectConfig;
|
|
6
17
|
export declare function createAuth(params: InitParams): {
|
|
7
18
|
on<K extends AuthState>(event: K, handler: AuthEventMap[K]): void;
|
|
8
19
|
off<K extends AuthState>(event: K, handler: AuthEventMap[K]): void;
|
|
9
20
|
removeAllListeners<K extends AuthState>(event?: K): void;
|
|
21
|
+
/**
|
|
22
|
+
* Connect external dependencies like Vue Router
|
|
23
|
+
* Automatically sets up router guard when router is provided
|
|
24
|
+
* @param dependency - Vue Router instance or other plugins
|
|
25
|
+
* @param options - Configuration options
|
|
26
|
+
* @param options.guard - Whether to automatically set up auth guard (default: true)
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* // Auto setup (default)
|
|
30
|
+
* auth.use(router)
|
|
31
|
+
*
|
|
32
|
+
* // Manual guard control (for custom composition)
|
|
33
|
+
* auth.use(router, { guard: false })
|
|
34
|
+
* router.beforeEach(async (to, from, next) => {
|
|
35
|
+
* // Custom logic first
|
|
36
|
+
* if (!hasOrgAccess(to)) return next('/no-access')
|
|
37
|
+
* // Then run auth guard
|
|
38
|
+
* return auth.routerGuard()(to, from, next)
|
|
39
|
+
* })
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
use(dependency: any, options?: {
|
|
43
|
+
guard?: boolean;
|
|
44
|
+
}): /*elided*/ any;
|
|
45
|
+
/**
|
|
46
|
+
* Create a Vue Router navigation guard for authentication
|
|
47
|
+
* Protects routes requiring authentication and handles redirect logic
|
|
48
|
+
* Note: Automatically called by auth.use(router), only use directly for custom setups
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* // Automatic (recommended)
|
|
52
|
+
* auth.use(router)
|
|
53
|
+
*
|
|
54
|
+
* // Manual (for custom setups)
|
|
55
|
+
* router.beforeEach(auth.routerGuard())
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
routerGuard(): any;
|
|
59
|
+
/**
|
|
60
|
+
* Vue plugin install method
|
|
61
|
+
* Makes auth available globally as $auth
|
|
62
|
+
* @example
|
|
63
|
+
* ```ts
|
|
64
|
+
* app.use(auth)
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
10
67
|
install(app: App): void;
|
|
11
68
|
};
|
|
12
69
|
export declare function useAuth(): {
|