@meistrari/auth-nuxt 2.2.2 → 2.3.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/module.json +1 -1
- package/dist/module.mjs +5 -0
- package/dist/runtime/composables/application-auth.d.ts +3 -11
- package/dist/runtime/composables/application-auth.js +2 -12
- package/dist/runtime/composables/state.d.ts +3 -5
- package/dist/runtime/plugins/application-token-refresh.js +14 -13
- package/dist/runtime/server/routes/auth/refresh.d.ts +1 -9
- package/dist/runtime/server/routes/auth/switch-organization.d.ts +1 -9
- package/dist/runtime/server/routes/auth/whoami.d.ts +20 -0
- package/dist/runtime/server/routes/auth/whoami.js +31 -0
- package/dist/runtime/server/utils/require-auth.js +7 -0
- package/package.json +2 -2
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -66,6 +66,11 @@ const module$1 = defineNuxtModule({
|
|
|
66
66
|
handler: resolver.resolve("./runtime/server/routes/auth/switch-organization"),
|
|
67
67
|
method: "post"
|
|
68
68
|
});
|
|
69
|
+
addServerHandler({
|
|
70
|
+
route: "/auth/whoami",
|
|
71
|
+
handler: resolver.resolve("./runtime/server/routes/auth/whoami"),
|
|
72
|
+
method: "get"
|
|
73
|
+
});
|
|
69
74
|
addPlugin(resolver.resolve("./runtime/plugins/application-token-refresh"));
|
|
70
75
|
addPlugin(resolver.resolve("./runtime/plugins/auth-guard"));
|
|
71
76
|
addPlugin(resolver.resolve("./runtime/plugins/directives"));
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
type
|
|
2
|
-
title: string;
|
|
3
|
-
id: string;
|
|
4
|
-
createdAt: Date;
|
|
5
|
-
avatarUrl: string | null;
|
|
6
|
-
metadata: string | null;
|
|
7
|
-
slug: string | null;
|
|
8
|
-
};
|
|
1
|
+
import type { FullOrganization } from '@meistrari/auth-core';
|
|
9
2
|
/**
|
|
10
3
|
* Composable for managing Tela application authentication with OAuth 2.0 PKCE flow
|
|
11
4
|
*
|
|
@@ -44,7 +37,7 @@ export declare function useTelaApplicationAuth(): {
|
|
|
44
37
|
login: () => Promise<void>;
|
|
45
38
|
logout: () => Promise<void>;
|
|
46
39
|
initSession: () => Promise<void>;
|
|
47
|
-
getAvailableOrganizations: () => Promise<
|
|
40
|
+
getAvailableOrganizations: () => Promise<FullOrganization[]>;
|
|
48
41
|
switchOrganization: (organizationId: string) => Promise<void>;
|
|
49
42
|
refreshToken: () => Promise<void>;
|
|
50
43
|
user: import("vue").Ref<{
|
|
@@ -76,6 +69,5 @@ export declare function useTelaApplicationAuth(): {
|
|
|
76
69
|
banExpires?: Date | null | undefined;
|
|
77
70
|
lastActiveAt?: Date | null | undefined;
|
|
78
71
|
} | null>;
|
|
79
|
-
activeOrganization: import("vue").Ref<
|
|
72
|
+
activeOrganization: import("vue").Ref<FullOrganization | null, FullOrganization | null>;
|
|
80
73
|
};
|
|
81
|
-
export {};
|
|
@@ -3,16 +3,6 @@ import { AuthorizationFlowError, isTokenExpired, RefreshTokenExpiredError, UserN
|
|
|
3
3
|
import { useApplicationSessionState } from "./state.js";
|
|
4
4
|
const FIFTEEN_MINUTES = 60 * 15;
|
|
5
5
|
const ONE_MINUTE = 60 * 1e3;
|
|
6
|
-
function mapOrganization(organization) {
|
|
7
|
-
return {
|
|
8
|
-
name: organization.title,
|
|
9
|
-
id: organization.id,
|
|
10
|
-
createdAt: organization.createdAt,
|
|
11
|
-
logo: organization.avatarUrl,
|
|
12
|
-
metadata: organization.metadata,
|
|
13
|
-
slug: organization.slug ?? ""
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
6
|
export function useTelaApplicationAuth() {
|
|
17
7
|
const appConfig = useRuntimeConfig().public.telaAuth;
|
|
18
8
|
const accessTokenCookie = useCookie("tela-access-token", {
|
|
@@ -60,7 +50,7 @@ export function useTelaApplicationAuth() {
|
|
|
60
50
|
method: "POST"
|
|
61
51
|
});
|
|
62
52
|
state.user.value = result.user;
|
|
63
|
-
state.activeOrganization.value =
|
|
53
|
+
state.activeOrganization.value = result.organization;
|
|
64
54
|
} catch (error) {
|
|
65
55
|
console.error("[Auth Refresh] Failed to refresh token:", error);
|
|
66
56
|
throw new RefreshTokenExpiredError();
|
|
@@ -91,7 +81,7 @@ export function useTelaApplicationAuth() {
|
|
|
91
81
|
body: { organizationId }
|
|
92
82
|
});
|
|
93
83
|
state.user.value = result.user;
|
|
94
|
-
state.activeOrganization.value =
|
|
84
|
+
state.activeOrganization.value = result.organization;
|
|
95
85
|
} catch (error) {
|
|
96
86
|
console.error("[Auth Switch Org] Failed to switch organization:", error);
|
|
97
87
|
throw error;
|
|
@@ -100,6 +100,7 @@ export declare function useSessionState(): {
|
|
|
100
100
|
export declare function useOrganizationState(): {
|
|
101
101
|
activeOrganization: import("vue").Ref<FullOrganization | null, FullOrganization | null>;
|
|
102
102
|
activeMember: import("vue").Ref<{
|
|
103
|
+
[x: string]: string | number | boolean | string[] | Record<string, any> | (string & Record<never, never>) | Date | number[] | undefined;
|
|
103
104
|
id: string;
|
|
104
105
|
organizationId: string;
|
|
105
106
|
role: "org:admin" | "org:member" | "org:reviewer";
|
|
@@ -112,9 +113,8 @@ export declare function useOrganizationState(): {
|
|
|
112
113
|
name: string;
|
|
113
114
|
image?: string | undefined;
|
|
114
115
|
};
|
|
115
|
-
deletedAt?: Date | undefined;
|
|
116
|
-
lastActiveAt?: Date | undefined;
|
|
117
116
|
} | null, {
|
|
117
|
+
[x: string]: string | number | boolean | string[] | Record<string, any> | (string & Record<never, never>) | Date | number[] | undefined;
|
|
118
118
|
id: string;
|
|
119
119
|
organizationId: string;
|
|
120
120
|
role: "org:admin" | "org:member" | "org:reviewer";
|
|
@@ -127,8 +127,6 @@ export declare function useOrganizationState(): {
|
|
|
127
127
|
name: string;
|
|
128
128
|
image?: string | undefined;
|
|
129
129
|
};
|
|
130
|
-
deletedAt?: Date | undefined;
|
|
131
|
-
lastActiveAt?: Date | undefined;
|
|
132
130
|
} | null>;
|
|
133
131
|
};
|
|
134
132
|
export declare function useApplicationSessionState(): {
|
|
@@ -161,5 +159,5 @@ export declare function useApplicationSessionState(): {
|
|
|
161
159
|
banExpires?: Date | null | undefined;
|
|
162
160
|
lastActiveAt?: Date | null | undefined;
|
|
163
161
|
} | null>;
|
|
164
|
-
activeOrganization: import("vue").Ref<
|
|
162
|
+
activeOrganization: import("vue").Ref<FullOrganization | null, FullOrganization | null>;
|
|
165
163
|
};
|
|
@@ -17,16 +17,6 @@ function parseTokenExpiry(token) {
|
|
|
17
17
|
return null;
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
-
function mapOrganization(organization) {
|
|
21
|
-
return {
|
|
22
|
-
name: organization.title,
|
|
23
|
-
id: organization.id,
|
|
24
|
-
createdAt: organization.createdAt,
|
|
25
|
-
logo: organization.avatarUrl,
|
|
26
|
-
metadata: organization.metadata,
|
|
27
|
-
slug: organization.slug ?? ""
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
20
|
export default defineNuxtPlugin({
|
|
31
21
|
name: "tela-application-token-refresh",
|
|
32
22
|
enforce: "post",
|
|
@@ -62,14 +52,14 @@ export default defineNuxtPlugin({
|
|
|
62
52
|
accessTokenCookie.value = accessToken;
|
|
63
53
|
refreshTokenCookie.value = refreshToken2;
|
|
64
54
|
state.user.value = user2;
|
|
65
|
-
state.activeOrganization.value =
|
|
55
|
+
state.activeOrganization.value = organization2;
|
|
66
56
|
return;
|
|
67
57
|
}
|
|
68
58
|
const { user, organization } = await $fetch("/auth/refresh", {
|
|
69
59
|
method: "POST"
|
|
70
60
|
});
|
|
71
61
|
state.user.value = user;
|
|
72
|
-
state.activeOrganization.value =
|
|
62
|
+
state.activeOrganization.value = organization;
|
|
73
63
|
} catch {
|
|
74
64
|
await sdkLogout();
|
|
75
65
|
if (import.meta.client) {
|
|
@@ -107,7 +97,7 @@ export default defineNuxtPlugin({
|
|
|
107
97
|
try {
|
|
108
98
|
const data = await authClient.application.whoAmI(accessTokenCookie.value);
|
|
109
99
|
state.user.value = data.user;
|
|
110
|
-
state.activeOrganization.value =
|
|
100
|
+
state.activeOrganization.value = data.organization;
|
|
111
101
|
} catch (error) {
|
|
112
102
|
console.error("[Tela Auth SDK] Failed to get user and organization:", error.message);
|
|
113
103
|
if (!refreshTokenCookie.value) {
|
|
@@ -135,6 +125,17 @@ export default defineNuxtPlugin({
|
|
|
135
125
|
return;
|
|
136
126
|
}
|
|
137
127
|
if (import.meta.client) {
|
|
128
|
+
if (!state.user.value && accessTokenCookie.value) {
|
|
129
|
+
try {
|
|
130
|
+
const { user, organization } = await $fetch("/auth/whoami", {
|
|
131
|
+
method: "GET"
|
|
132
|
+
});
|
|
133
|
+
state.user.value = user;
|
|
134
|
+
state.activeOrganization.value = organization;
|
|
135
|
+
} catch (error) {
|
|
136
|
+
console.error("[Tela Auth SDK] Failed to load user info on client startup:", error);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
138
139
|
void scheduleTokenRefresh();
|
|
139
140
|
}
|
|
140
141
|
}
|
|
@@ -26,14 +26,6 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
|
|
|
26
26
|
banExpires?: Date | null | undefined;
|
|
27
27
|
lastActiveAt?: Date | null | undefined;
|
|
28
28
|
};
|
|
29
|
-
organization:
|
|
30
|
-
id: string;
|
|
31
|
-
title: string;
|
|
32
|
-
slug: string | null;
|
|
33
|
-
avatarUrl: string | null;
|
|
34
|
-
createdAt: Date;
|
|
35
|
-
metadata: string | null;
|
|
36
|
-
settings: unknown;
|
|
37
|
-
};
|
|
29
|
+
organization: import("@meistrari/auth-core").FullOrganization;
|
|
38
30
|
}>>;
|
|
39
31
|
export default _default;
|
|
@@ -27,14 +27,6 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
|
|
|
27
27
|
banExpires?: Date | null | undefined;
|
|
28
28
|
lastActiveAt?: Date | null | undefined;
|
|
29
29
|
};
|
|
30
|
-
organization:
|
|
31
|
-
id: string;
|
|
32
|
-
title: string;
|
|
33
|
-
slug: string | null;
|
|
34
|
-
avatarUrl: string | null;
|
|
35
|
-
createdAt: Date;
|
|
36
|
-
metadata: string | null;
|
|
37
|
-
settings: unknown;
|
|
38
|
-
};
|
|
30
|
+
organization: import("@meistrari/auth-core").FullOrganization;
|
|
39
31
|
}>>;
|
|
40
32
|
export default _default;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
|
|
2
|
+
success: boolean;
|
|
3
|
+
user: {
|
|
4
|
+
id: string;
|
|
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;
|
|
19
|
+
}>>;
|
|
20
|
+
export default _default;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createError, useRuntimeConfig } from "#imports";
|
|
2
|
+
import { defineEventHandler, getCookie } from "h3";
|
|
3
|
+
import { createNuxtAuthClient } from "../../../shared.js";
|
|
4
|
+
export default defineEventHandler(async (event) => {
|
|
5
|
+
const config = useRuntimeConfig();
|
|
6
|
+
const authConfig = config.public.telaAuth;
|
|
7
|
+
const authClient = createNuxtAuthClient(authConfig.apiUrl, () => null, () => null);
|
|
8
|
+
const accessToken = getCookie(event, "tela-access-token");
|
|
9
|
+
if (!accessToken) {
|
|
10
|
+
throw createError({
|
|
11
|
+
statusCode: 401,
|
|
12
|
+
statusMessage: "Unauthorized",
|
|
13
|
+
message: "No access token found"
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const { user, organization } = await authClient.application.whoAmI(accessToken);
|
|
18
|
+
return {
|
|
19
|
+
success: true,
|
|
20
|
+
user,
|
|
21
|
+
organization
|
|
22
|
+
};
|
|
23
|
+
} catch (error) {
|
|
24
|
+
console.error("[Auth WhoAmI] Failed to get user and organization:", error);
|
|
25
|
+
throw createError({
|
|
26
|
+
statusCode: 401,
|
|
27
|
+
statusMessage: "Unauthorized",
|
|
28
|
+
message: "Failed to get user and organization"
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
});
|
|
@@ -3,7 +3,14 @@ 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
|
+
}
|
|
6
10
|
if (event.context.auth?.user && event.context.auth?.token) {
|
|
11
|
+
if (import.meta.dev) {
|
|
12
|
+
console.debug("Using existing auth context from global server middleware");
|
|
13
|
+
}
|
|
7
14
|
const user = event.context.auth.user;
|
|
8
15
|
if (options?.roles && !options.roles.includes(user.role ?? "")) {
|
|
9
16
|
throw createError({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meistrari/auth-nuxt",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"build": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxt-module-build build"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@meistrari/auth-core": "1.
|
|
34
|
+
"@meistrari/auth-core": "1.11.1",
|
|
35
35
|
"jose": "6.1.3"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|