@sylphx/sdk 0.10.6 → 0.10.7
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/nextjs/index.d.ts +4 -0
- package/dist/nextjs/index.mjs +112 -16
- package/dist/nextjs/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/nextjs/index.d.ts
CHANGED
|
@@ -64,14 +64,18 @@ interface SylphxMiddlewareConfig {
|
|
|
64
64
|
afterSignInUrl?: string;
|
|
65
65
|
/**
|
|
66
66
|
* Auth routes prefix. Routes are mounted at:
|
|
67
|
+
* - {prefix}/register — email/password registration handler
|
|
67
68
|
* - {prefix}/login — credentials login handler
|
|
69
|
+
* - {prefix}/verify-email — email verification handler
|
|
68
70
|
* - {prefix}/oauth-providers — enabled social login providers
|
|
69
71
|
* - {prefix}/oauth/authorize — social login start handler
|
|
70
72
|
* - {prefix}/callback — OAuth callback handler
|
|
71
73
|
* - {prefix}/passkey/options — passkey login challenge handler
|
|
72
74
|
* - {prefix}/passkey/authenticate — passkey login verification handler
|
|
75
|
+
* - {prefix}/verify-2fa — TOTP/backup-code verification handler
|
|
73
76
|
* - {prefix}/forgot-password — password reset email handler
|
|
74
77
|
* - {prefix}/reset-password — password reset verification handler
|
|
78
|
+
* - {prefix}/session — safe session metadata handler
|
|
75
79
|
* - {prefix}/signout — Sign out handler
|
|
76
80
|
*
|
|
77
81
|
* @default '/auth'
|
package/dist/nextjs/index.mjs
CHANGED
|
@@ -634,12 +634,30 @@ function isTwoFactorLoginResponse(data) {
|
|
|
634
634
|
function isOAuthAuthorizeResponse(data) {
|
|
635
635
|
return typeof data === "object" && data !== null && typeof data.authorization_url === "string";
|
|
636
636
|
}
|
|
637
|
+
function authCookieJsonResponse(ctx, data) {
|
|
638
|
+
const response = NextResponse.json({ success: true, user: data.user });
|
|
639
|
+
setAuthCookiesMiddleware(response, ctx.namespace, data);
|
|
640
|
+
return response;
|
|
641
|
+
}
|
|
637
642
|
function headersForPlatformAuth(ctx) {
|
|
638
643
|
return {
|
|
639
644
|
"Content-Type": "application/json",
|
|
640
645
|
"x-app-secret": ctx.secretKey
|
|
641
646
|
};
|
|
642
647
|
}
|
|
648
|
+
async function handleRegister(request, ctx) {
|
|
649
|
+
if (request.method !== "POST") {
|
|
650
|
+
return NextResponse.json({ error: "Method not allowed" }, { status: 405 });
|
|
651
|
+
}
|
|
652
|
+
const body = await parseJsonObject(request);
|
|
653
|
+
const res = await fetch(`${ctx.platformUrl}/v1/auth/register`, {
|
|
654
|
+
method: "POST",
|
|
655
|
+
headers: headersForPlatformAuth(ctx),
|
|
656
|
+
body: JSON.stringify(body ?? {})
|
|
657
|
+
});
|
|
658
|
+
const data = await res.json().catch(() => ({}));
|
|
659
|
+
return NextResponse.json(data, { status: res.status });
|
|
660
|
+
}
|
|
643
661
|
async function handleLogin(request, ctx) {
|
|
644
662
|
if (request.method !== "POST") {
|
|
645
663
|
return NextResponse.json({ error: "Method not allowed" }, { status: 405 });
|
|
@@ -665,9 +683,78 @@ async function handleLogin(request, ctx) {
|
|
|
665
683
|
if (!isTokenResponse(data)) {
|
|
666
684
|
return NextResponse.json({ error: "invalid_response" }, { status: 502 });
|
|
667
685
|
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
686
|
+
return authCookieJsonResponse(ctx, data);
|
|
687
|
+
}
|
|
688
|
+
async function handleVerifyEmail(request, ctx) {
|
|
689
|
+
if (request.method !== "POST") {
|
|
690
|
+
return NextResponse.json({ error: "Method not allowed" }, { status: 405 });
|
|
691
|
+
}
|
|
692
|
+
const body = await parseJsonObject(request);
|
|
693
|
+
const token = typeof body?.token === "string" ? body.token : null;
|
|
694
|
+
if (!token) {
|
|
695
|
+
return NextResponse.json({ error: "token is required" }, { status: 400 });
|
|
696
|
+
}
|
|
697
|
+
const res = await fetch(`${ctx.platformUrl}/v1/auth/verify-email`, {
|
|
698
|
+
method: "POST",
|
|
699
|
+
headers: headersForPlatformAuth(ctx),
|
|
700
|
+
body: JSON.stringify({ token })
|
|
701
|
+
});
|
|
702
|
+
const data = await res.json().catch(() => ({}));
|
|
703
|
+
return NextResponse.json(data, { status: res.status });
|
|
704
|
+
}
|
|
705
|
+
async function handleVerifyTwoFactor(request, ctx) {
|
|
706
|
+
if (request.method !== "POST") {
|
|
707
|
+
return NextResponse.json({ error: "Method not allowed" }, { status: 405 });
|
|
708
|
+
}
|
|
709
|
+
const body = await parseJsonObject(request);
|
|
710
|
+
const userId = typeof body?.userId === "string" ? body.userId : null;
|
|
711
|
+
const code = typeof body?.code === "string" ? body.code : null;
|
|
712
|
+
if (!userId || !code) {
|
|
713
|
+
return NextResponse.json({ error: "userId and code are required" }, { status: 400 });
|
|
714
|
+
}
|
|
715
|
+
const res = await fetch(`${ctx.platformUrl}/v1/auth/verify-2fa`, {
|
|
716
|
+
method: "POST",
|
|
717
|
+
headers: headersForPlatformAuth(ctx),
|
|
718
|
+
body: JSON.stringify({ userId, code })
|
|
719
|
+
});
|
|
720
|
+
const data = await res.json().catch(() => ({}));
|
|
721
|
+
if (!res.ok) {
|
|
722
|
+
return NextResponse.json(data, { status: res.status });
|
|
723
|
+
}
|
|
724
|
+
if (!isTokenResponse(data)) {
|
|
725
|
+
return NextResponse.json({ error: "invalid_response" }, { status: 502 });
|
|
726
|
+
}
|
|
727
|
+
return authCookieJsonResponse(ctx, data);
|
|
728
|
+
}
|
|
729
|
+
function handleSession(request, ctx) {
|
|
730
|
+
if (request.method !== "GET") {
|
|
731
|
+
return NextResponse.json({ error: "Method not allowed" }, { status: 405 });
|
|
732
|
+
}
|
|
733
|
+
const sessionToken = request.cookies.get(ctx.cookieNames.SESSION)?.value;
|
|
734
|
+
const userCookieValue = request.cookies.get(ctx.cookieNames.USER)?.value;
|
|
735
|
+
let userCookie = userCookieValue ? parseUserCookie2(userCookieValue) : null;
|
|
736
|
+
if (!userCookie && userCookieValue) {
|
|
737
|
+
try {
|
|
738
|
+
userCookie = parseUserCookie2(decodeURIComponent(userCookieValue));
|
|
739
|
+
} catch {
|
|
740
|
+
userCookie = null;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
if (!sessionToken || isTokenExpired(sessionToken) || !userCookie?.user) {
|
|
744
|
+
return NextResponse.json({ success: true, session: null, user: null });
|
|
745
|
+
}
|
|
746
|
+
const payload = decodeJwtPayload(sessionToken);
|
|
747
|
+
const userId = payload?.sub ?? userCookie.user.id;
|
|
748
|
+
const expiresAt = typeof payload?.exp === "number" ? new Date(payload.exp * 1e3).toISOString() : new Date(userCookie.expiresAt).toISOString();
|
|
749
|
+
return NextResponse.json({
|
|
750
|
+
success: true,
|
|
751
|
+
session: {
|
|
752
|
+
id: `platform:${userId}`,
|
|
753
|
+
userId,
|
|
754
|
+
expiresAt
|
|
755
|
+
},
|
|
756
|
+
user: userCookie.user
|
|
757
|
+
});
|
|
671
758
|
}
|
|
672
759
|
async function handleOAuthProviders(ctx) {
|
|
673
760
|
const res = await fetch(`${ctx.platformUrl}/v1/auth/oauth-providers`, {
|
|
@@ -747,9 +834,7 @@ async function handlePasskeyAuthenticate(request, ctx) {
|
|
|
747
834
|
if (!isTokenResponse(data)) {
|
|
748
835
|
return NextResponse.json({ error: "invalid_response" }, { status: 502 });
|
|
749
836
|
}
|
|
750
|
-
|
|
751
|
-
setAuthCookiesMiddleware(response, ctx.namespace, data);
|
|
752
|
-
return response;
|
|
837
|
+
return authCookieJsonResponse(ctx, data);
|
|
753
838
|
}
|
|
754
839
|
async function handleForgotPassword(request, ctx) {
|
|
755
840
|
if (request.method !== "POST") {
|
|
@@ -1091,12 +1176,15 @@ async function handleSwitchOrg(request, ctx) {
|
|
|
1091
1176
|
}
|
|
1092
1177
|
const expiresIn = resolveOrgScopedTokenExpiresIn(data);
|
|
1093
1178
|
const expiresAt = Date.now() + expiresIn * 1e3;
|
|
1179
|
+
const payload = decodeJwtPayload(accessToken);
|
|
1180
|
+
const activeOrganization = {
|
|
1181
|
+
id: payload?.org_id ?? orgId,
|
|
1182
|
+
slug: payload?.org_slug ?? requestedOrgSlug
|
|
1183
|
+
};
|
|
1094
1184
|
const response = NextResponse.json({
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
tokenType: resolveOrgScopedTokenType(data),
|
|
1099
|
-
user: data.user ?? null
|
|
1185
|
+
success: true,
|
|
1186
|
+
user: data.user ?? null,
|
|
1187
|
+
organization: activeOrganization
|
|
1100
1188
|
});
|
|
1101
1189
|
response.cookies.set(ctx.cookieNames.SESSION, accessToken, {
|
|
1102
1190
|
...SECURE_COOKIE_OPTIONS,
|
|
@@ -1117,11 +1205,7 @@ async function handleSwitchOrg(request, ctx) {
|
|
|
1117
1205
|
}
|
|
1118
1206
|
);
|
|
1119
1207
|
}
|
|
1120
|
-
|
|
1121
|
-
setActiveOrganizationCookies(response, ctx, {
|
|
1122
|
-
id: payload?.org_id ?? orgId,
|
|
1123
|
-
slug: payload?.org_slug ?? requestedOrgSlug
|
|
1124
|
-
});
|
|
1208
|
+
setActiveOrganizationCookies(response, ctx, activeOrganization);
|
|
1125
1209
|
ctx.log("Switch org success", { orgId });
|
|
1126
1210
|
return response;
|
|
1127
1211
|
} catch (err) {
|
|
@@ -1267,12 +1351,18 @@ function createSylphxMiddleware(userConfig = {}) {
|
|
|
1267
1351
|
if (pathname.includes(".") || pathname.startsWith("/_next")) {
|
|
1268
1352
|
return NextResponse.next();
|
|
1269
1353
|
}
|
|
1354
|
+
if (pathname === `${config.authPrefix}/register`) {
|
|
1355
|
+
return handleRegister(request, ctx);
|
|
1356
|
+
}
|
|
1270
1357
|
if (pathname === `${config.authPrefix}/callback`) {
|
|
1271
1358
|
return handleCallback(request, ctx);
|
|
1272
1359
|
}
|
|
1273
1360
|
if (pathname === `${config.authPrefix}/login`) {
|
|
1274
1361
|
return handleLogin(request, ctx);
|
|
1275
1362
|
}
|
|
1363
|
+
if (pathname === `${config.authPrefix}/verify-email`) {
|
|
1364
|
+
return handleVerifyEmail(request, ctx);
|
|
1365
|
+
}
|
|
1276
1366
|
if (pathname === `${config.authPrefix}/oauth-providers`) {
|
|
1277
1367
|
return handleOAuthProviders(ctx);
|
|
1278
1368
|
}
|
|
@@ -1285,12 +1375,18 @@ function createSylphxMiddleware(userConfig = {}) {
|
|
|
1285
1375
|
if (pathname === `${config.authPrefix}/passkey/authenticate`) {
|
|
1286
1376
|
return handlePasskeyAuthenticate(request, ctx);
|
|
1287
1377
|
}
|
|
1378
|
+
if (pathname === `${config.authPrefix}/verify-2fa`) {
|
|
1379
|
+
return handleVerifyTwoFactor(request, ctx);
|
|
1380
|
+
}
|
|
1288
1381
|
if (pathname === `${config.authPrefix}/forgot-password`) {
|
|
1289
1382
|
return handleForgotPassword(request, ctx);
|
|
1290
1383
|
}
|
|
1291
1384
|
if (pathname === `${config.authPrefix}/reset-password`) {
|
|
1292
1385
|
return handleResetPassword(request, ctx);
|
|
1293
1386
|
}
|
|
1387
|
+
if (pathname === `${config.authPrefix}/session`) {
|
|
1388
|
+
return handleSession(request, ctx);
|
|
1389
|
+
}
|
|
1294
1390
|
if (pathname === `${config.authPrefix}/signout`) {
|
|
1295
1391
|
return handleSignOut(request, ctx);
|
|
1296
1392
|
}
|