@meistrari/auth-nuxt 3.0.0 → 3.0.2
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/module.json +1 -1
- package/dist/runtime/composables/application-auth.d.ts +3 -15
- package/dist/runtime/composables/application-auth.js +5 -0
- package/dist/runtime/composables/state.d.ts +15 -83
- package/dist/runtime/plugins/application-token-refresh.js +7 -6
- package/dist/runtime/plugins/auth-guard.js +19 -16
- package/dist/runtime/server/routes/auth/callback.js +7 -0
- package/dist/runtime/server/routes/auth/organizations.d.ts +1 -1
- package/dist/runtime/server/routes/auth/refresh.d.ts +2 -16
- package/dist/runtime/server/routes/auth/switch-organization.d.ts +2 -16
- package/dist/runtime/server/routes/auth/whoami.d.ts +2 -16
- package/dist/runtime/server/utils/require-auth.js +0 -4
- package/dist/runtime/types/page-meta.d.ts +1 -4
- package/package.json +7 -7
package/dist/module.json
CHANGED
|
@@ -41,7 +41,7 @@ export declare function useTelaApplicationAuth(): {
|
|
|
41
41
|
switchOrganization: (organizationId: string) => Promise<void>;
|
|
42
42
|
refreshToken: () => Promise<void>;
|
|
43
43
|
getToken: () => Promise<string | null | undefined>;
|
|
44
|
-
user: import("vue").Ref<{
|
|
44
|
+
user: import("vue").Ref<import("better-auth").StripEmptyObjects<{
|
|
45
45
|
id: string;
|
|
46
46
|
createdAt: Date;
|
|
47
47
|
updatedAt: Date;
|
|
@@ -49,13 +49,7 @@ export declare function useTelaApplicationAuth(): {
|
|
|
49
49
|
emailVerified: boolean;
|
|
50
50
|
name: string;
|
|
51
51
|
image?: string | null | undefined;
|
|
52
|
-
|
|
53
|
-
banned: boolean | null | undefined;
|
|
54
|
-
role?: string | null | undefined;
|
|
55
|
-
banReason?: string | null | undefined;
|
|
56
|
-
banExpires?: Date | null | undefined;
|
|
57
|
-
lastActiveAt?: Date | null | undefined;
|
|
58
|
-
} | null, {
|
|
52
|
+
}> | null, import("better-auth").StripEmptyObjects<{
|
|
59
53
|
id: string;
|
|
60
54
|
createdAt: Date;
|
|
61
55
|
updatedAt: Date;
|
|
@@ -63,12 +57,6 @@ export declare function useTelaApplicationAuth(): {
|
|
|
63
57
|
emailVerified: boolean;
|
|
64
58
|
name: string;
|
|
65
59
|
image?: string | null | undefined;
|
|
66
|
-
|
|
67
|
-
banned: boolean | null | undefined;
|
|
68
|
-
role?: string | null | undefined;
|
|
69
|
-
banReason?: string | null | undefined;
|
|
70
|
-
banExpires?: Date | null | undefined;
|
|
71
|
-
lastActiveAt?: Date | null | undefined;
|
|
72
|
-
} | null>;
|
|
60
|
+
}> | null>;
|
|
73
61
|
activeOrganization: import("vue").Ref<FullOrganization | null, FullOrganization | null>;
|
|
74
62
|
};
|
|
@@ -33,6 +33,11 @@ export function useTelaApplicationAuth() {
|
|
|
33
33
|
throw new AuthorizationFlowError("The login function can only be called on the client side.");
|
|
34
34
|
}
|
|
35
35
|
const { state: stateKey, challenge: codeChallenge } = await $fetch("/auth/login", { method: "POST" });
|
|
36
|
+
const returnTo = new URL(window.location.href).searchParams.get("returnTo");
|
|
37
|
+
if (returnTo && returnTo.startsWith("/") && !returnTo.startsWith("//")) {
|
|
38
|
+
const returnUrlCookie = useCookie("tela-return-url", { sameSite: "lax", path: "/" });
|
|
39
|
+
returnUrlCookie.value = returnTo;
|
|
40
|
+
}
|
|
36
41
|
const url = new URL("/applications/login", appConfig.application?.dashboardUrl);
|
|
37
42
|
url.searchParams.set("application_id", applicationId);
|
|
38
43
|
url.searchParams.set("code_challenge", codeChallenge);
|
|
@@ -4,7 +4,7 @@ import type { FullOrganization } from '@meistrari/auth-core';
|
|
|
4
4
|
* This module provides access to session-related state without creating circular dependencies.
|
|
5
5
|
*/
|
|
6
6
|
export declare function useSessionState(): {
|
|
7
|
-
user: import("vue").Ref<{
|
|
7
|
+
user: import("vue").Ref<import("better-auth").StripEmptyObjects<{
|
|
8
8
|
id: string;
|
|
9
9
|
createdAt: Date;
|
|
10
10
|
updatedAt: Date;
|
|
@@ -12,13 +12,7 @@ export declare function useSessionState(): {
|
|
|
12
12
|
emailVerified: boolean;
|
|
13
13
|
name: string;
|
|
14
14
|
image?: string | null | undefined;
|
|
15
|
-
|
|
16
|
-
banned: boolean | null | undefined;
|
|
17
|
-
role?: string | null | undefined;
|
|
18
|
-
banReason?: string | null | undefined;
|
|
19
|
-
banExpires?: Date | null | undefined;
|
|
20
|
-
lastActiveAt?: Date | null | undefined;
|
|
21
|
-
} | null, {
|
|
15
|
+
}> | null, import("better-auth").StripEmptyObjects<{
|
|
22
16
|
id: string;
|
|
23
17
|
createdAt: Date;
|
|
24
18
|
updatedAt: Date;
|
|
@@ -26,15 +20,9 @@ export declare function useSessionState(): {
|
|
|
26
20
|
emailVerified: boolean;
|
|
27
21
|
name: string;
|
|
28
22
|
image?: string | null | undefined;
|
|
29
|
-
|
|
30
|
-
banned: boolean | null | undefined;
|
|
31
|
-
role?: string | null | undefined;
|
|
32
|
-
banReason?: string | null | undefined;
|
|
33
|
-
banExpires?: Date | null | undefined;
|
|
34
|
-
lastActiveAt?: Date | null | undefined;
|
|
35
|
-
} | null>;
|
|
23
|
+
}> | null>;
|
|
36
24
|
session: import("vue").Ref<{
|
|
37
|
-
user: {
|
|
25
|
+
user: import("better-auth").StripEmptyObjects<{
|
|
38
26
|
id: string;
|
|
39
27
|
createdAt: Date;
|
|
40
28
|
updatedAt: Date;
|
|
@@ -42,14 +30,8 @@ export declare function useSessionState(): {
|
|
|
42
30
|
emailVerified: boolean;
|
|
43
31
|
name: string;
|
|
44
32
|
image?: string | null | undefined;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
role?: string | null | undefined;
|
|
48
|
-
banReason?: string | null | undefined;
|
|
49
|
-
banExpires?: Date | null | undefined;
|
|
50
|
-
lastActiveAt?: Date | null | undefined;
|
|
51
|
-
};
|
|
52
|
-
session: {
|
|
33
|
+
}>;
|
|
34
|
+
session: import("better-auth").StripEmptyObjects<{
|
|
53
35
|
id: string;
|
|
54
36
|
createdAt: Date;
|
|
55
37
|
updatedAt: Date;
|
|
@@ -58,12 +40,9 @@ export declare function useSessionState(): {
|
|
|
58
40
|
token: string;
|
|
59
41
|
ipAddress?: string | null | undefined;
|
|
60
42
|
userAgent?: string | null | undefined;
|
|
61
|
-
|
|
62
|
-
activeTeamId?: string | null | undefined;
|
|
63
|
-
impersonatedBy?: string | null | undefined;
|
|
64
|
-
};
|
|
43
|
+
}>;
|
|
65
44
|
} | null, {
|
|
66
|
-
user: {
|
|
45
|
+
user: import("better-auth").StripEmptyObjects<{
|
|
67
46
|
id: string;
|
|
68
47
|
createdAt: Date;
|
|
69
48
|
updatedAt: Date;
|
|
@@ -71,14 +50,8 @@ export declare function useSessionState(): {
|
|
|
71
50
|
emailVerified: boolean;
|
|
72
51
|
name: string;
|
|
73
52
|
image?: string | null | undefined;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
role?: string | null | undefined;
|
|
77
|
-
banReason?: string | null | undefined;
|
|
78
|
-
banExpires?: Date | null | undefined;
|
|
79
|
-
lastActiveAt?: Date | null | undefined;
|
|
80
|
-
};
|
|
81
|
-
session: {
|
|
53
|
+
}>;
|
|
54
|
+
session: import("better-auth").StripEmptyObjects<{
|
|
82
55
|
id: string;
|
|
83
56
|
createdAt: Date;
|
|
84
57
|
updatedAt: Date;
|
|
@@ -87,10 +60,7 @@ export declare function useSessionState(): {
|
|
|
87
60
|
token: string;
|
|
88
61
|
ipAddress?: string | null | undefined;
|
|
89
62
|
userAgent?: string | null | undefined;
|
|
90
|
-
|
|
91
|
-
activeTeamId?: string | null | undefined;
|
|
92
|
-
impersonatedBy?: string | null | undefined;
|
|
93
|
-
};
|
|
63
|
+
}>;
|
|
94
64
|
} | null>;
|
|
95
65
|
};
|
|
96
66
|
/**
|
|
@@ -99,36 +69,10 @@ export declare function useSessionState(): {
|
|
|
99
69
|
*/
|
|
100
70
|
export declare function useOrganizationState(): {
|
|
101
71
|
activeOrganization: import("vue").Ref<FullOrganization | null, FullOrganization | null>;
|
|
102
|
-
activeMember: import("vue").Ref<
|
|
103
|
-
id: string;
|
|
104
|
-
organizationId: string;
|
|
105
|
-
role: "org:admin" | "org:member" | "org:reviewer";
|
|
106
|
-
createdAt: Date;
|
|
107
|
-
userId: string;
|
|
108
|
-
teamId?: string | undefined | undefined | undefined;
|
|
109
|
-
user: {
|
|
110
|
-
id: string;
|
|
111
|
-
email: string;
|
|
112
|
-
name: string;
|
|
113
|
-
image?: string | undefined;
|
|
114
|
-
};
|
|
115
|
-
} | null, {
|
|
116
|
-
id: string;
|
|
117
|
-
organizationId: string;
|
|
118
|
-
role: "org:admin" | "org:member" | "org:reviewer";
|
|
119
|
-
createdAt: Date;
|
|
120
|
-
userId: string;
|
|
121
|
-
teamId?: string | undefined | undefined | undefined;
|
|
122
|
-
user: {
|
|
123
|
-
id: string;
|
|
124
|
-
email: string;
|
|
125
|
-
name: string;
|
|
126
|
-
image?: string | undefined;
|
|
127
|
-
};
|
|
128
|
-
} | null>;
|
|
72
|
+
activeMember: import("vue").Ref<any, any>;
|
|
129
73
|
};
|
|
130
74
|
export declare function useApplicationSessionState(): {
|
|
131
|
-
user: import("vue").Ref<{
|
|
75
|
+
user: import("vue").Ref<import("better-auth").StripEmptyObjects<{
|
|
132
76
|
id: string;
|
|
133
77
|
createdAt: Date;
|
|
134
78
|
updatedAt: Date;
|
|
@@ -136,13 +80,7 @@ export declare function useApplicationSessionState(): {
|
|
|
136
80
|
emailVerified: boolean;
|
|
137
81
|
name: string;
|
|
138
82
|
image?: string | null | undefined;
|
|
139
|
-
|
|
140
|
-
banned: boolean | null | undefined;
|
|
141
|
-
role?: string | null | undefined;
|
|
142
|
-
banReason?: string | null | undefined;
|
|
143
|
-
banExpires?: Date | null | undefined;
|
|
144
|
-
lastActiveAt?: Date | null | undefined;
|
|
145
|
-
} | null, {
|
|
83
|
+
}> | null, import("better-auth").StripEmptyObjects<{
|
|
146
84
|
id: string;
|
|
147
85
|
createdAt: Date;
|
|
148
86
|
updatedAt: Date;
|
|
@@ -150,12 +88,6 @@ export declare function useApplicationSessionState(): {
|
|
|
150
88
|
emailVerified: boolean;
|
|
151
89
|
name: string;
|
|
152
90
|
image?: string | null | undefined;
|
|
153
|
-
|
|
154
|
-
banned: boolean | null | undefined;
|
|
155
|
-
role?: string | null | undefined;
|
|
156
|
-
banReason?: string | null | undefined;
|
|
157
|
-
banExpires?: Date | null | undefined;
|
|
158
|
-
lastActiveAt?: Date | null | undefined;
|
|
159
|
-
} | null>;
|
|
91
|
+
}> | null>;
|
|
160
92
|
activeOrganization: import("vue").Ref<FullOrganization | null, FullOrganization | null>;
|
|
161
93
|
};
|
|
@@ -43,13 +43,14 @@ export default defineNuxtPlugin({
|
|
|
43
43
|
refreshTokenCookie.value = refreshToken2;
|
|
44
44
|
state.user.value = user2;
|
|
45
45
|
state.activeOrganization.value = organization2;
|
|
46
|
-
return;
|
|
46
|
+
return true;
|
|
47
47
|
}
|
|
48
48
|
const { user, organization } = await $fetch("/auth/refresh", {
|
|
49
49
|
method: "POST"
|
|
50
50
|
});
|
|
51
51
|
state.user.value = user;
|
|
52
52
|
state.activeOrganization.value = organization;
|
|
53
|
+
return true;
|
|
53
54
|
} catch {
|
|
54
55
|
await sdkLogout();
|
|
55
56
|
if (import.meta.client) {
|
|
@@ -69,11 +70,11 @@ export default defineNuxtPlugin({
|
|
|
69
70
|
clearTimeout(tokenRefreshInterval);
|
|
70
71
|
tokenRefreshInterval = null;
|
|
71
72
|
}
|
|
72
|
-
if (!accessTokenCookie.value) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
if (!accessTokenCookie.value || isTokenExpired(accessTokenCookie.value, TWO_MINUTES)) {
|
|
74
|
+
const result = await refreshToken();
|
|
75
|
+
if (!result) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
77
78
|
}
|
|
78
79
|
const expiry = parseTokenExpiry(accessTokenCookie.value);
|
|
79
80
|
if (!expiry) {
|
|
@@ -5,35 +5,38 @@ export default defineNuxtPlugin(() => {
|
|
|
5
5
|
const authConfig = config.public.telaAuth;
|
|
6
6
|
const loginPath = authConfig.application?.loginPath ?? "/login";
|
|
7
7
|
const unauthorizedPath = authConfig.application?.unauthorizedPath ?? "/unauthorized";
|
|
8
|
+
const exemptPaths = [loginPath, unauthorizedPath];
|
|
8
9
|
addRouteMiddleware("auth-guard", async (to) => {
|
|
9
10
|
const authMeta = to.meta?.auth;
|
|
10
|
-
|
|
11
|
+
const path = decodeURI(to.path);
|
|
12
|
+
if (authMeta === false || exemptPaths.includes(path)) {
|
|
11
13
|
return;
|
|
12
14
|
}
|
|
13
15
|
const token = useCookie("tela-access-token");
|
|
14
16
|
if (!token.value) {
|
|
15
17
|
return await navigateTo({
|
|
16
18
|
path: loginPath,
|
|
17
|
-
query: {
|
|
19
|
+
query: { returnTo: to.fullPath }
|
|
18
20
|
});
|
|
19
21
|
}
|
|
20
|
-
if (authMeta
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
query: { redirect: to.fullPath }
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
} catch (error) {
|
|
31
|
-
console.error("Failed to decode token:", error);
|
|
22
|
+
if (!authMeta?.roles?.length) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
const payload = decodeJwt(token.value);
|
|
27
|
+
const userRole = payload.user?.role;
|
|
28
|
+
if (!userRole || !authMeta.roles.includes(userRole)) {
|
|
32
29
|
return await navigateTo({
|
|
33
|
-
path:
|
|
34
|
-
query: {
|
|
30
|
+
path: unauthorizedPath,
|
|
31
|
+
query: { returnTo: to.fullPath }
|
|
35
32
|
});
|
|
36
33
|
}
|
|
34
|
+
} catch (error) {
|
|
35
|
+
console.error("Failed to decode token:", error);
|
|
36
|
+
return await navigateTo({
|
|
37
|
+
path: loginPath,
|
|
38
|
+
query: { returnTo: to.fullPath }
|
|
39
|
+
});
|
|
37
40
|
}
|
|
38
41
|
}, { global: true });
|
|
39
42
|
});
|
|
@@ -40,6 +40,13 @@ export default defineEventHandler(async (event) => {
|
|
|
40
40
|
path: "/"
|
|
41
41
|
});
|
|
42
42
|
deleteCookie(event, `tela-verifier-${state}`, { path: "/" });
|
|
43
|
+
const returnUrlCookie = getCookie(event, "tela-return-url");
|
|
44
|
+
if (returnUrlCookie) {
|
|
45
|
+
deleteCookie(event, "tela-return-url", { path: "/" });
|
|
46
|
+
if (returnUrlCookie.startsWith("/") && !returnUrlCookie.startsWith("//")) {
|
|
47
|
+
return await sendRedirect(event, returnUrlCookie);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
43
50
|
return await sendRedirect(event, "/");
|
|
44
51
|
} catch (error) {
|
|
45
52
|
console.error("[Auth Callback] OAuth flow error:", error);
|
|
@@ -11,21 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
|
|
13
13
|
success: boolean;
|
|
14
|
-
user:
|
|
15
|
-
|
|
16
|
-
createdAt: Date;
|
|
17
|
-
updatedAt: Date;
|
|
18
|
-
email: string;
|
|
19
|
-
emailVerified: boolean;
|
|
20
|
-
name: string;
|
|
21
|
-
image?: string | null | undefined;
|
|
22
|
-
twoFactorEnabled: boolean | null | undefined;
|
|
23
|
-
banned: boolean | null | undefined;
|
|
24
|
-
role?: string | null | undefined;
|
|
25
|
-
banReason?: string | null | undefined;
|
|
26
|
-
banExpires?: Date | null | undefined;
|
|
27
|
-
lastActiveAt?: Date | null | undefined;
|
|
28
|
-
};
|
|
29
|
-
organization: import("@meistrari/auth-core").FullOrganization;
|
|
14
|
+
user: any;
|
|
15
|
+
organization: any;
|
|
30
16
|
}>>;
|
|
31
17
|
export default _default;
|
|
@@ -12,21 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
|
|
14
14
|
success: boolean;
|
|
15
|
-
user:
|
|
16
|
-
|
|
17
|
-
createdAt: Date;
|
|
18
|
-
updatedAt: Date;
|
|
19
|
-
email: string;
|
|
20
|
-
emailVerified: boolean;
|
|
21
|
-
name: string;
|
|
22
|
-
image?: string | null | undefined;
|
|
23
|
-
twoFactorEnabled: boolean | null | undefined;
|
|
24
|
-
banned: boolean | null | undefined;
|
|
25
|
-
role?: string | null | undefined;
|
|
26
|
-
banReason?: string | null | undefined;
|
|
27
|
-
banExpires?: Date | null | undefined;
|
|
28
|
-
lastActiveAt?: Date | null | undefined;
|
|
29
|
-
};
|
|
30
|
-
organization: import("@meistrari/auth-core").FullOrganization;
|
|
15
|
+
user: any;
|
|
16
|
+
organization: any;
|
|
31
17
|
}>>;
|
|
32
18
|
export default _default;
|
|
@@ -1,20 +1,6 @@
|
|
|
1
1
|
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
|
|
2
2
|
success: boolean;
|
|
3
|
-
user:
|
|
4
|
-
|
|
5
|
-
createdAt: Date;
|
|
6
|
-
updatedAt: Date;
|
|
7
|
-
email: string;
|
|
8
|
-
emailVerified: boolean;
|
|
9
|
-
name: string;
|
|
10
|
-
image?: string | null | undefined;
|
|
11
|
-
twoFactorEnabled: boolean | null | undefined;
|
|
12
|
-
banned: boolean | null | undefined;
|
|
13
|
-
role?: string | null | undefined;
|
|
14
|
-
banReason?: string | null | undefined;
|
|
15
|
-
banExpires?: Date | null | undefined;
|
|
16
|
-
lastActiveAt?: Date | null | undefined;
|
|
17
|
-
};
|
|
18
|
-
organization: import("@meistrari/auth-core").FullOrganization;
|
|
3
|
+
user: any;
|
|
4
|
+
organization: any;
|
|
19
5
|
}>>;
|
|
20
6
|
export default _default;
|
|
@@ -3,10 +3,6 @@ import { createRemoteJWKSet, jwtVerify } from "jose";
|
|
|
3
3
|
import { useRuntimeConfig } from "nitropack/runtime";
|
|
4
4
|
export function requireAuth(handler, options) {
|
|
5
5
|
return defineEventHandler(async (event) => {
|
|
6
|
-
const moduleOptions = useRuntimeConfig(event).public.telaAuth;
|
|
7
|
-
if (!moduleOptions.skipServerMiddleware && !options?.roles && import.meta.dev) {
|
|
8
|
-
console.warn("You have enabled the global server middleware, meaning you only need to use requireAuth() on routes that require specific roles.", `Triggered at ${event.path}`);
|
|
9
|
-
}
|
|
10
6
|
if (event.context.auth?.user && event.context.auth?.token) {
|
|
11
7
|
if (import.meta.dev) {
|
|
12
8
|
console.debug("Using existing auth context from global server middleware");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meistrari/auth-nuxt",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -27,9 +27,12 @@
|
|
|
27
27
|
"files": [
|
|
28
28
|
"dist"
|
|
29
29
|
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxt-module-build build"
|
|
32
|
+
},
|
|
30
33
|
"dependencies": {
|
|
31
|
-
"
|
|
32
|
-
"
|
|
34
|
+
"@meistrari/auth-core": "1.11.4",
|
|
35
|
+
"jose": "6.1.3"
|
|
33
36
|
},
|
|
34
37
|
"peerDependencies": {
|
|
35
38
|
"nuxt": "^3.0.0 || ^4.0.0",
|
|
@@ -49,8 +52,5 @@
|
|
|
49
52
|
"unbuild": "3.6.1",
|
|
50
53
|
"vitest": "3.2.4",
|
|
51
54
|
"vue-tsc": "3.0.6"
|
|
52
|
-
},
|
|
53
|
-
"scripts": {
|
|
54
|
-
"build": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxt-module-build build"
|
|
55
55
|
}
|
|
56
|
-
}
|
|
56
|
+
}
|