@vilio/auth-passkey-module 0.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.
Files changed (48) hide show
  1. package/dist/actions/settings.d.ts +10 -0
  2. package/dist/actions/settings.d.ts.map +1 -0
  3. package/dist/actions/settings.js +17 -0
  4. package/dist/actions/settings.js.map +1 -0
  5. package/dist/client.d.ts +1 -0
  6. package/dist/client.d.ts.map +1 -0
  7. package/dist/client.js +3 -0
  8. package/dist/client.js.map +1 -0
  9. package/dist/index.d.ts +4 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +118 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/routes.d.ts +5 -0
  14. package/dist/routes.d.ts.map +1 -0
  15. package/dist/routes.js +195 -0
  16. package/dist/routes.js.map +1 -0
  17. package/dist/schema.d.ts +415 -0
  18. package/dist/schema.d.ts.map +1 -0
  19. package/dist/schema.js +28 -0
  20. package/dist/schema.js.map +1 -0
  21. package/dist/server/passkey.d.ts +8 -0
  22. package/dist/server/passkey.d.ts.map +1 -0
  23. package/dist/server/passkey.js +126 -0
  24. package/dist/server/passkey.js.map +1 -0
  25. package/dist/ui/passkey-button.d.ts +2 -0
  26. package/dist/ui/passkey-button.d.ts.map +1 -0
  27. package/dist/ui/passkey-button.js +56 -0
  28. package/dist/ui/passkey-button.js.map +1 -0
  29. package/dist/ui/session-badge.d.ts +5 -0
  30. package/dist/ui/session-badge.d.ts.map +1 -0
  31. package/dist/ui/session-badge.js +16 -0
  32. package/dist/ui/session-badge.js.map +1 -0
  33. package/dist/ui/settings-auth-passkey.d.ts +2 -0
  34. package/dist/ui/settings-auth-passkey.d.ts.map +1 -0
  35. package/dist/ui/settings-auth-passkey.js +32 -0
  36. package/dist/ui/settings-auth-passkey.js.map +1 -0
  37. package/dist/ui/settings-passkey.d.ts +2 -0
  38. package/dist/ui/settings-passkey.d.ts.map +1 -0
  39. package/dist/ui/settings-passkey.js +110 -0
  40. package/dist/ui/settings-passkey.js.map +1 -0
  41. package/dist/ui/verify-page.d.ts +2 -0
  42. package/dist/ui/verify-page.d.ts.map +1 -0
  43. package/dist/ui/verify-page.js +45 -0
  44. package/dist/ui/verify-page.js.map +1 -0
  45. package/locales/en/global.json +52 -0
  46. package/locales/pl/global.json +52 -0
  47. package/manifest.json +11 -0
  48. package/package.json +45 -0
@@ -0,0 +1,10 @@
1
+ export interface PasskeyConfig {
2
+ rpName: string;
3
+ rpId: string;
4
+ origin: string;
5
+ }
6
+ export declare function getPasskeyConfig(): Promise<PasskeyConfig>;
7
+ export declare function updatePasskeyConfig(config: PasskeyConfig): Promise<{
8
+ success: boolean;
9
+ }>;
10
+ //# sourceMappingURL=settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/actions/settings.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,aAAa,CAAC,CAS/D;AAED,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,aAAa;;GAI9D"}
@@ -0,0 +1,17 @@
1
+ "use server";
2
+ import { getModuleConfig, getVilioPathPrefix, updateModuleConfig, } from "@vilio/modules/server";
3
+ import { revalidatePath } from "next/cache";
4
+ export async function getPasskeyConfig() {
5
+ const config = await getModuleConfig("auth-passkey-module");
6
+ return (config ?? {
7
+ rpName: "Vilio Turbo",
8
+ rpId: "localhost",
9
+ origin: "http://localhost:3000",
10
+ });
11
+ }
12
+ export async function updatePasskeyConfig(config) {
13
+ await updateModuleConfig("auth-passkey-module", config);
14
+ revalidatePath(`${getVilioPathPrefix()}/auth-passkey/settings`);
15
+ return { success: true };
16
+ }
17
+ //# sourceMappingURL=settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/actions/settings.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAQ5C,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,MAAM,GAAG,MAAM,eAAe,CAAgB,qBAAqB,CAAC,CAAC;IAC3E,OAAO,CACL,MAAM,IAAI;QACR,MAAM,EAAE,aAAa;QACrB,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,uBAAuB;KAChC,CACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,MAAqB;IAC7D,MAAM,kBAAkB,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;IACxD,cAAc,CAAC,GAAG,kBAAkB,EAAE,wBAAwB,CAAC,CAAC;IAChE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC"}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":""}
package/dist/client.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ // Export client components here
3
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";AAAA,gCAAgC"}
@@ -0,0 +1,4 @@
1
+ import type { IModule } from "@vilio/modules";
2
+ declare const module: IModule;
3
+ export default module;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAkB9C,QAAA,MAAM,MAAM,EAAE,OAmHb,CAAC;AAEF,eAAe,MAAM,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,118 @@
1
+ import { i18n } from "@vilio/intl";
2
+ import { db, registerAuthValidator, registerSecurityRequirement, registerSessionAugmenter, } from "@vilio/core/server";
3
+ import { eq } from "drizzle-orm";
4
+ import localesEn from "../locales/en/global.json" with { type: "json" };
5
+ import localesPl from "../locales/pl/global.json" with { type: "json" };
6
+ import manifest from "../manifest.json";
7
+ import { apiRoutes, privateRoutes, publicRoutes } from "./routes";
8
+ import { authPasskeySchema, passkeySettingsTable } from "./schema";
9
+ import { PasskeyLoginButton } from "./ui/passkey-button";
10
+ import { PasskeySettings } from "./ui/settings-passkey";
11
+ import { Passkey2FAVerifiedBadge } from "./ui/session-badge";
12
+ const module = {
13
+ manifest,
14
+ schema: authPasskeySchema,
15
+ translations: {
16
+ en: localesEn,
17
+ pl: localesPl,
18
+ },
19
+ // onMigrate: async () => {
20
+ // console.log("[Module:auth-passkey-module] running migrations...");
21
+ // await pushModuleSchema(manifest.id);
22
+ // },
23
+ init: async () => {
24
+ // 1. Validator for initial login (email/password)
25
+ registerAuthValidator(async (userId) => {
26
+ const [settings] = await db
27
+ .select()
28
+ .from(passkeySettingsTable)
29
+ .where(eq(passkeySettingsTable.userId, userId));
30
+ if (settings?.twoFactorEnabled) {
31
+ return {
32
+ status: "CHALLENGE_REQUIRED",
33
+ type: "passkey_2fa",
34
+ userId,
35
+ redirect: `/auth/passkey/verify?userId=${userId}`,
36
+ };
37
+ }
38
+ return null;
39
+ });
40
+ // 2. Security requirement to block access if 2FA is needed but not done
41
+ registerSecurityRequirement(async (session, user) => {
42
+ const [settings] = await db
43
+ .select()
44
+ .from(passkeySettingsTable)
45
+ .where(eq(passkeySettingsTable.userId, user.id));
46
+ // Use the flag directly from session metadata (restored by core)
47
+ if (settings?.twoFactorEnabled && !session.passkey_verified) {
48
+ return {
49
+ satisfied: false,
50
+ redirect: `/auth/passkey/verify?userId=${user.id}`,
51
+ };
52
+ }
53
+ return { satisfied: true };
54
+ });
55
+ // 3. Register session augmenter to expose passkey_verified flag in types
56
+ registerSessionAugmenter(async (session) => {
57
+ return {
58
+ passkey_verified: session.passkey_verified ?? false,
59
+ "2faVerified": session.passkey_verified ?? false,
60
+ };
61
+ });
62
+ },
63
+ onEnable: async () => {
64
+ console.log("[Module:auth-passkey-module] enabled");
65
+ },
66
+ onDisable: async () => {
67
+ console.log("[Module:auth-passkey-module] disabled");
68
+ },
69
+ routes: {
70
+ public: publicRoutes,
71
+ private: privateRoutes,
72
+ api: apiRoutes,
73
+ },
74
+ extensions: [
75
+ {
76
+ id: "passkey-login-signin",
77
+ targetModule: "auth",
78
+ point: "signin:extra-buttons",
79
+ component: PasskeyLoginButton,
80
+ priority: 5,
81
+ },
82
+ {
83
+ id: "passkey-login-signup",
84
+ targetModule: "auth",
85
+ point: "signup:extra-buttons",
86
+ component: PasskeyLoginButton,
87
+ priority: 5,
88
+ },
89
+ {
90
+ id: "passkey-settings",
91
+ targetModule: "user-profile",
92
+ point: "settings:extra-sections",
93
+ component: PasskeySettings,
94
+ priority: 20,
95
+ },
96
+ {
97
+ id: "passkey-session-badge",
98
+ targetModule: "panel",
99
+ point: "session-item-badge",
100
+ component: Passkey2FAVerifiedBadge,
101
+ priority: 10,
102
+ },
103
+ ],
104
+ navigation: {
105
+ settings: {
106
+ [i18n("Security")]: [
107
+ {
108
+ id: "auth-passkey-settings",
109
+ title: i18n("Passkey Settings"),
110
+ url: "/settings/auth/passkey",
111
+ icon: "solar:key-bold-duotone",
112
+ },
113
+ ],
114
+ },
115
+ },
116
+ };
117
+ export default module;
118
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { ApiRouteDefinition, PrivateRouteDefinition, PublicRouteDefinition } from "@vilio/modules";
2
+ export declare const publicRoutes: PublicRouteDefinition[];
3
+ export declare const privateRoutes: PrivateRouteDefinition[];
4
+ export declare const apiRoutes: ApiRouteDefinition[];
5
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,EACtB,MAAM,gBAAgB,CAAC;AAcxB,eAAO,MAAM,YAAY,EAAE,qBAAqB,EAM/C,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,sBAAsB,EAOjD,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,kBAAkB,EA8LzC,CAAC"}
package/dist/routes.js ADDED
@@ -0,0 +1,195 @@
1
+ import { createSession, db, eventBus, finalizeLogin, generateSessionToken, getCurrentSession, getUserById, performFullUserAugmentation, setSessionTokenCookie, } from "@vilio/core/server";
2
+ import { and, eq } from "drizzle-orm";
3
+ import dynamic from "next/dynamic";
4
+ import { authenticatorTable, passkeySettingsTable } from "./schema";
5
+ import { getLoginOptions, getRegistrationOptions, verifyLogin, verifyRegistration, } from "./server/passkey";
6
+ const PasskeyVerifyPage = dynamic(() => import("./ui/verify-page"));
7
+ const PasskeySettingsPage = dynamic(() => import("./ui/settings-auth-passkey"));
8
+ export const publicRoutes = [
9
+ {
10
+ path: "/auth/passkey/verify",
11
+ component: PasskeyVerifyPage,
12
+ auth: false,
13
+ },
14
+ ];
15
+ export const privateRoutes = [
16
+ {
17
+ path: "/settings/auth/passkey",
18
+ component: PasskeySettingsPage,
19
+ auth: true,
20
+ roles: ["admin"],
21
+ },
22
+ ];
23
+ export const apiRoutes = [
24
+ {
25
+ path: "/api/auth/passkey/settings",
26
+ auth: true,
27
+ handler: async () => {
28
+ const { user } = await getCurrentSession();
29
+ if (!user)
30
+ return new Response("Unauthorized", { status: 401 });
31
+ const [settings] = await db
32
+ .select()
33
+ .from(passkeySettingsTable)
34
+ .where(eq(passkeySettingsTable.userId, user.id));
35
+ return Response.json(settings || { twoFactorEnabled: false });
36
+ },
37
+ },
38
+ {
39
+ path: "/api/auth/passkey/settings/update",
40
+ auth: true,
41
+ handler: async (request) => {
42
+ const { user } = await getCurrentSession();
43
+ if (!user)
44
+ return new Response("Unauthorized", { status: 401 });
45
+ const { enabled } = await request.json();
46
+ await db
47
+ .insert(passkeySettingsTable)
48
+ .values({ userId: user.id, twoFactorEnabled: enabled })
49
+ .onConflictDoUpdate({
50
+ target: passkeySettingsTable.userId,
51
+ set: { twoFactorEnabled: enabled, updatedAt: new Date() },
52
+ });
53
+ return Response.json({ success: true });
54
+ },
55
+ },
56
+ {
57
+ path: "/api/auth/passkey/list",
58
+ auth: true,
59
+ handler: async () => {
60
+ const { user } = await getCurrentSession();
61
+ if (!user)
62
+ return new Response("Unauthorized", { status: 401 });
63
+ const list = await db
64
+ .select({
65
+ id: authenticatorTable.id,
66
+ name: authenticatorTable.name,
67
+ createdAt: authenticatorTable.createdAt,
68
+ deviceType: authenticatorTable.credentialDeviceType,
69
+ })
70
+ .from(authenticatorTable)
71
+ .where(eq(authenticatorTable.userId, user.id));
72
+ return Response.json(list);
73
+ },
74
+ },
75
+ {
76
+ path: "/api/auth/passkey/rename",
77
+ auth: true,
78
+ handler: async (request) => {
79
+ const { user } = await getCurrentSession();
80
+ if (!user)
81
+ return new Response("Unauthorized", { status: 401 });
82
+ const { id, name } = await request.json();
83
+ await db
84
+ .update(authenticatorTable)
85
+ .set({ name })
86
+ .where(and(eq(authenticatorTable.id, id), eq(authenticatorTable.userId, user.id)));
87
+ return Response.json({ success: true });
88
+ },
89
+ },
90
+ {
91
+ path: "/api/auth/passkey/delete",
92
+ auth: true,
93
+ handler: async (request) => {
94
+ const { user } = await getCurrentSession();
95
+ if (!user)
96
+ return new Response("Unauthorized", { status: 401 });
97
+ const { id } = await request.json();
98
+ await db
99
+ .delete(authenticatorTable)
100
+ .where(and(eq(authenticatorTable.id, id), eq(authenticatorTable.userId, user.id)));
101
+ return Response.json({ success: true });
102
+ },
103
+ },
104
+ {
105
+ path: "/api/auth/passkey/register-options",
106
+ auth: true,
107
+ handler: async () => {
108
+ const { user } = await getCurrentSession();
109
+ if (!user)
110
+ return new Response("Unauthorized", { status: 401 });
111
+ const options = await getRegistrationOptions(user.id, user.email);
112
+ return Response.json(options);
113
+ },
114
+ },
115
+ {
116
+ path: "/api/auth/passkey/register-verify",
117
+ auth: true,
118
+ handler: async (request) => {
119
+ const { user } = await getCurrentSession();
120
+ if (!user)
121
+ return new Response("Unauthorized", { status: 401 });
122
+ const body = await request.json();
123
+ try {
124
+ const verification = await verifyRegistration(user.id, body);
125
+ return Response.json(verification);
126
+ }
127
+ catch (error) {
128
+ console.error("[PasskeyAuth] Registration verification error:", error);
129
+ return Response.json({ message: error.message }, { status: 400 });
130
+ }
131
+ },
132
+ },
133
+ {
134
+ path: "/api/auth/passkey/login-options",
135
+ handler: async () => {
136
+ const options = await getLoginOptions();
137
+ return Response.json(options);
138
+ },
139
+ },
140
+ {
141
+ path: "/api/auth/passkey/login-verify",
142
+ handler: async (request) => {
143
+ const body = await request.json();
144
+ try {
145
+ const { verification, userId } = await verifyLogin(body);
146
+ if (verification.verified) {
147
+ const user = await getUserById(userId);
148
+ if (!user)
149
+ throw new Error("User not found");
150
+ // Persistence is now automatic because 'createSession' saves 'flags' to 'metadata' jsonb column
151
+ const sessionToken = await generateSessionToken();
152
+ const session = await createSession(sessionToken, user.id, {
153
+ passkey_verified: true,
154
+ });
155
+ await setSessionTokenCookie(sessionToken, session.expiresAt);
156
+ const fullUser = await performFullUserAugmentation(user);
157
+ await eventBus.publish("auth:login", {
158
+ email: user.email,
159
+ userId: user.id,
160
+ });
161
+ await eventBus.publish("auth:session-created", {
162
+ session,
163
+ user: fullUser,
164
+ });
165
+ }
166
+ return Response.json(verification);
167
+ }
168
+ catch (error) {
169
+ console.error("[PasskeyAuth] Login verification error:", error);
170
+ return Response.json({ message: error.message }, { status: 400 });
171
+ }
172
+ },
173
+ },
174
+ {
175
+ path: "/api/auth/passkey/2fa-verify",
176
+ handler: async (request) => {
177
+ const body = await request.json();
178
+ try {
179
+ const { verification, userId } = await verifyLogin(body);
180
+ if (verification.verified) {
181
+ // Persistence is now automatic because 'finalizeLogin' uses 'createSession' which saves 'flags'
182
+ const result = await finalizeLogin(userId, {
183
+ passkey_verified: true,
184
+ });
185
+ return Response.json({ success: true, ...result });
186
+ }
187
+ return Response.json({ success: false, message: "Verification failed" }, { status: 400 });
188
+ }
189
+ catch (error) {
190
+ return Response.json({ message: error.message }, { status: 400 });
191
+ }
192
+ },
193
+ },
194
+ ];
195
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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"}