@seamless-auth/express 0.0.2-beta.1 → 0.0.2-beta.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 (37) hide show
  1. package/dist/index.js +564 -5
  2. package/package.json +3 -2
  3. package/dist/createServer.d.ts +0 -48
  4. package/dist/createServer.d.ts.map +0 -1
  5. package/dist/createServer.js +0 -164
  6. package/dist/index.d.ts +0 -7
  7. package/dist/index.d.ts.map +0 -1
  8. package/dist/internal/authFetch.d.ts +0 -9
  9. package/dist/internal/authFetch.d.ts.map +0 -1
  10. package/dist/internal/authFetch.js +0 -37
  11. package/dist/internal/cookie.d.ts +0 -11
  12. package/dist/internal/cookie.d.ts.map +0 -1
  13. package/dist/internal/cookie.js +0 -28
  14. package/dist/internal/getSeamlessUser.d.ts +0 -51
  15. package/dist/internal/getSeamlessUser.d.ts.map +0 -1
  16. package/dist/internal/getSeamlessUser.js +0 -72
  17. package/dist/internal/refreshAccessToken.d.ts +0 -10
  18. package/dist/internal/refreshAccessToken.d.ts.map +0 -1
  19. package/dist/internal/refreshAccessToken.js +0 -44
  20. package/dist/internal/verifyCookieJwt.d.ts +0 -2
  21. package/dist/internal/verifyCookieJwt.d.ts.map +0 -1
  22. package/dist/internal/verifyCookieJwt.js +0 -13
  23. package/dist/internal/verifySignedAuthResponse.d.ts +0 -6
  24. package/dist/internal/verifySignedAuthResponse.d.ts.map +0 -1
  25. package/dist/internal/verifySignedAuthResponse.js +0 -23
  26. package/dist/middleware/ensureCookies.d.ts +0 -8
  27. package/dist/middleware/ensureCookies.d.ts.map +0 -1
  28. package/dist/middleware/ensureCookies.js +0 -78
  29. package/dist/middleware/requireAuth.d.ts +0 -53
  30. package/dist/middleware/requireAuth.d.ts.map +0 -1
  31. package/dist/middleware/requireAuth.js +0 -118
  32. package/dist/middleware/requireRole.d.ts +0 -49
  33. package/dist/middleware/requireRole.d.ts.map +0 -1
  34. package/dist/middleware/requireRole.js +0 -77
  35. package/dist/types.d.ts +0 -9
  36. package/dist/types.d.ts.map +0 -1
  37. package/dist/types.js +0 -1
package/dist/index.js CHANGED
@@ -1,5 +1,564 @@
1
- import { createSeamlessAuthServer } from './createServer.js';
2
- export { requireAuth } from './middleware/requireAuth.js';
3
- export { requireRole } from './middleware/requireRole.js';
4
- export { getSeamlessUser } from './internal/getSeamlessUser.js';
5
- export default createSeamlessAuthServer;
1
+ // src/createServer.ts
2
+ import express from "express";
3
+ import cookieParser from "cookie-parser";
4
+
5
+ // src/internal/cookie.ts
6
+ import jwt from "jsonwebtoken";
7
+ function setSessionCookie(res, payload, domain, ttlSeconds = 300, name = "sa_session") {
8
+ const COOKIE_SECRET2 = process.env.SEAMLESS_COOKIE_SIGNING_KEY;
9
+ if (!COOKIE_SECRET2) {
10
+ console.warn("[SeamlessAuth] Missing SEAMLESS_COOKIE_SIGNING_KEY env var!");
11
+ throw new Error("Missing required env SEAMLESS_COOKIE_SIGNING_KEY");
12
+ }
13
+ const token = jwt.sign(payload, COOKIE_SECRET2, {
14
+ algorithm: "HS256",
15
+ expiresIn: `${ttlSeconds}s`
16
+ });
17
+ res.cookie(name, token, {
18
+ httpOnly: true,
19
+ secure: process.env.NODE_ENV === "production",
20
+ sameSite: process.env.NODE_ENV === "production" ? "none" : "lax",
21
+ path: "/",
22
+ domain,
23
+ maxAge: ttlSeconds * 1e3
24
+ });
25
+ }
26
+ function clearSessionCookie(res, domain, name = "sa_session") {
27
+ res.clearCookie(name, { domain, path: "/" });
28
+ }
29
+ function clearAllCookies(res, domain, accesscookieName, registrationCookieName, refreshCookieName) {
30
+ res.clearCookie(accesscookieName, { domain, path: "/" });
31
+ res.clearCookie(registrationCookieName, { domain, path: "/" });
32
+ res.clearCookie(refreshCookieName, { domain, path: "/" });
33
+ }
34
+
35
+ // src/internal/authFetch.ts
36
+ import jwt2 from "jsonwebtoken";
37
+ async function authFetch(req, url, { method = "POST", body, cookies, headers = {} } = {}) {
38
+ const serviceKey = process.env.SEAMLESS_SERVICE_TOKEN;
39
+ if (!serviceKey) {
40
+ throw new Error(
41
+ "Cannot sign service token. Missing SEAMLESS_SERVICE_TOKEN"
42
+ );
43
+ }
44
+ const token = jwt2.sign(
45
+ {
46
+ iss: process.env.FRONTEND_URL,
47
+ aud: process.env.AUTH_SERVER_URL,
48
+ sub: req.cookiePayload?.sub,
49
+ roles: req.cookiePayload?.roles ?? [],
50
+ iat: Math.floor(Date.now() / 1e3)
51
+ },
52
+ serviceKey,
53
+ {
54
+ expiresIn: "60s",
55
+ // Short-lived
56
+ algorithm: "HS256"
57
+ // HMAC-based
58
+ }
59
+ );
60
+ const finalHeaders = {
61
+ ...method !== "GET" && { "Content-Type": "application/json" },
62
+ ...cookies ? { Cookie: cookies.join("; ") } : {},
63
+ Authorization: `Bearer ${token}`,
64
+ ...headers
65
+ };
66
+ let finalUrl = url;
67
+ if (method === "GET" && body && typeof body === "object") {
68
+ const qs = new URLSearchParams(body).toString();
69
+ finalUrl += url.includes("?") ? `&${qs}` : `?${qs}`;
70
+ }
71
+ const res = await fetch(finalUrl, {
72
+ method,
73
+ headers: finalHeaders,
74
+ ...method !== "GET" && body ? { body: JSON.stringify(body) } : {}
75
+ });
76
+ return res;
77
+ }
78
+
79
+ // src/internal/verifyCookieJwt.ts
80
+ import jwt3 from "jsonwebtoken";
81
+ var COOKIE_SECRET = process.env.SEAMLESS_COOKIE_SIGNING_KEY;
82
+ function verifyCookieJwt(token) {
83
+ try {
84
+ return jwt3.verify(token, COOKIE_SECRET, {
85
+ algorithms: ["HS256"]
86
+ });
87
+ } catch (err) {
88
+ console.error("[SeamlessAuth] Cookie JWT verification failed:", err);
89
+ return null;
90
+ }
91
+ }
92
+
93
+ // src/internal/refreshAccessToken.ts
94
+ import jwt4 from "jsonwebtoken";
95
+ async function refreshAccessToken(req, authServerUrl, refreshToken) {
96
+ try {
97
+ const COOKIE_SECRET2 = process.env.SEAMLESS_COOKIE_SIGNING_KEY;
98
+ if (!COOKIE_SECRET2) {
99
+ console.warn(
100
+ "[SeamlessAuth] SEAMLESS_COOKIE_SIGNING_KEY missing \u2014 requireAuth will always fail."
101
+ );
102
+ throw new Error("Missing required env SEAMLESS_COOKIE_SIGNING_KEY");
103
+ }
104
+ const serviceKey = process.env.SEAMLESS_SERVICE_TOKEN;
105
+ if (!serviceKey) {
106
+ throw new Error(
107
+ "Cannot sign service token. Missing SEAMLESS_SERVICE_TOKEN"
108
+ );
109
+ }
110
+ const payload = jwt4.verify(refreshToken, COOKIE_SECRET2, {
111
+ algorithms: ["HS256"]
112
+ });
113
+ const token = jwt4.sign(
114
+ {
115
+ // Minimal, safe fields
116
+ iss: process.env.FRONTEND_URL,
117
+ aud: process.env.AUTH_SERVER_URL,
118
+ sub: payload.sub,
119
+ refreshToken: payload.refreshToken,
120
+ iat: Math.floor(Date.now() / 1e3)
121
+ },
122
+ serviceKey,
123
+ {
124
+ expiresIn: "60s",
125
+ // Short-lived = safer
126
+ algorithm: "HS256",
127
+ // HMAC-based
128
+ keyid: "dev-main"
129
+ // For future rotation
130
+ }
131
+ );
132
+ const response = await fetch(`${authServerUrl}/refresh`, {
133
+ method: "GET",
134
+ headers: { Authorization: `Bearer ${token}` }
135
+ });
136
+ if (!response.ok) {
137
+ console.error(
138
+ "[SeamlessAuth] Refresh token request failed:",
139
+ response.status
140
+ );
141
+ return null;
142
+ }
143
+ const data = await response.json();
144
+ return data;
145
+ } catch (err) {
146
+ console.error("[SeamlessAuth] refreshAccessToken error:", err);
147
+ return null;
148
+ }
149
+ }
150
+
151
+ // src/middleware/ensureCookies.ts
152
+ function createEnsureCookiesMiddleware(opts) {
153
+ const COOKIE_REQUIREMENTS = {
154
+ "/webAuthn/login/finish": { name: opts.preAuthCookieName, required: true },
155
+ "/webAuthn/login/start": { name: opts.preAuthCookieName, required: true },
156
+ "/webAuthn/register/start": {
157
+ name: opts.registrationCookieName,
158
+ required: true
159
+ },
160
+ "/webAuthn/register/finish": {
161
+ name: opts.registrationCookieName,
162
+ required: true
163
+ },
164
+ "/otp/verify-email-otp": {
165
+ name: opts.registrationCookieName,
166
+ required: true
167
+ },
168
+ "/otp/verify-phone-otp": {
169
+ name: opts.registrationCookieName,
170
+ required: true
171
+ },
172
+ "/logout": { name: opts.accesscookieName, required: true },
173
+ "/users/me": { name: opts.accesscookieName, required: true }
174
+ };
175
+ return async function ensureCookies(req, res, next, cookieDomain = "") {
176
+ const match = Object.entries(COOKIE_REQUIREMENTS).find(
177
+ ([path]) => req.path.startsWith(path)
178
+ );
179
+ if (!match) return next();
180
+ const [, { name, required }] = match;
181
+ const AUTH_SERVER_URL = process.env.AUTH_SERVER_URL;
182
+ const cookieValue = req.cookies?.[name];
183
+ const refreshCookieValue = req.cookies?.[opts.refreshCookieName];
184
+ if (required && !cookieValue) {
185
+ if (refreshCookieValue) {
186
+ console.log("[SeamlessAuth] Access token expired \u2014 attempting refresh");
187
+ const refreshed = await refreshAccessToken(
188
+ req,
189
+ AUTH_SERVER_URL,
190
+ refreshCookieValue
191
+ );
192
+ if (!refreshed?.token) {
193
+ clearAllCookies(
194
+ res,
195
+ cookieDomain,
196
+ name,
197
+ opts.registrationCookieName,
198
+ opts.refreshCookieName
199
+ );
200
+ res.status(401).json({ error: "Refresh failed" });
201
+ return;
202
+ }
203
+ setSessionCookie(
204
+ res,
205
+ {
206
+ sub: refreshed.sub,
207
+ token: refreshed.token,
208
+ roles: refreshed.roles
209
+ },
210
+ cookieDomain,
211
+ refreshed.ttl,
212
+ name
213
+ );
214
+ setSessionCookie(
215
+ res,
216
+ { sub: refreshed.sub, refreshToken: refreshed.refreshToken },
217
+ cookieDomain,
218
+ refreshed.refreshTtl,
219
+ opts.refreshCookieName
220
+ );
221
+ req.cookiePayload = {
222
+ sub: refreshed.sub,
223
+ roles: refreshed.roles
224
+ };
225
+ return next();
226
+ }
227
+ return res.status(400).json({
228
+ error: `Missing required cookie "${name}" for route ${req.path}`,
229
+ hint: "Did you forget to call /auth/login/start first?"
230
+ });
231
+ }
232
+ if (cookieValue) {
233
+ const payload = verifyCookieJwt(cookieValue);
234
+ if (!payload) {
235
+ return res.status(401).json({ error: `Invalid or expired ${name} cookie` });
236
+ }
237
+ req.cookiePayload = payload;
238
+ }
239
+ next();
240
+ };
241
+ }
242
+
243
+ // src/internal/verifySignedAuthResponse.ts
244
+ import { createRemoteJWKSet, jwtVerify } from "jose";
245
+ async function verifySignedAuthResponse(token, authServerUrl) {
246
+ try {
247
+ const jwksUrl = new URL("/.well-known/jwks.json", authServerUrl).toString();
248
+ const JWKS = createRemoteJWKSet(new URL(jwksUrl));
249
+ const { payload } = await jwtVerify(token, JWKS, {
250
+ algorithms: ["RS256"],
251
+ issuer: authServerUrl
252
+ });
253
+ return payload;
254
+ } catch (err) {
255
+ console.error("[SeamlessAuth] Failed to verify signed auth response:", err);
256
+ return null;
257
+ }
258
+ }
259
+
260
+ // src/createServer.ts
261
+ function createSeamlessAuthServer(opts) {
262
+ const r = express.Router();
263
+ r.use(express.json());
264
+ r.use(cookieParser());
265
+ const {
266
+ authServerUrl,
267
+ cookieDomain = "",
268
+ accesscookieName = "seamless-access",
269
+ registrationCookieName = "seamless-ephemeral",
270
+ refreshCookieName = "seamless-refresh",
271
+ preAuthCookieName = "seamless-ephemeral"
272
+ } = opts;
273
+ const proxy = (path, method = "POST") => async (req, res) => {
274
+ try {
275
+ const response = await authFetch(req, `${authServerUrl}/${path}`, {
276
+ method,
277
+ body: req.body
278
+ });
279
+ res.status(response.status).json(await response.json());
280
+ } catch (error) {
281
+ console.error(`Failed to proxy to route. Error: ${error}`);
282
+ }
283
+ };
284
+ r.use(
285
+ createEnsureCookiesMiddleware({
286
+ authServerUrl,
287
+ cookieDomain,
288
+ accesscookieName,
289
+ registrationCookieName,
290
+ refreshCookieName,
291
+ preAuthCookieName
292
+ })
293
+ );
294
+ r.post("/webAuthn/login/start", proxy("webAuthn/login/start"));
295
+ r.post("/webAuthn/login/finish", finishLogin);
296
+ r.get("/webAuthn/register/start", proxy("webAuthn/register/start", "GET"));
297
+ r.post("/webAuthn/register/finish", finishRegister);
298
+ r.post("/otp/verify-phone-otp", proxy("otp/verify-phone-otp"));
299
+ r.post("/otp/verify-email-otp", proxy("otp/verify-email-otp"));
300
+ r.post("/login", login);
301
+ r.post("/users/update", proxy("users/update"));
302
+ r.post("/registration/register", register);
303
+ r.get("/users/me", me);
304
+ r.get("/logout", logout);
305
+ return r;
306
+ async function login(req, res) {
307
+ const up = await authFetch(req, `${authServerUrl}/login`, {
308
+ method: "POST",
309
+ body: req.body
310
+ });
311
+ const data = await up.json();
312
+ if (!up.ok) return res.status(up.status).json(data);
313
+ const verified = await verifySignedAuthResponse(data.token, authServerUrl);
314
+ if (!verified) {
315
+ throw new Error("Invalid signed response from Auth Server");
316
+ }
317
+ if (verified.sub !== data.sub) {
318
+ throw new Error("Signature mismatch with data payload");
319
+ }
320
+ setSessionCookie(
321
+ res,
322
+ { sub: data.sub },
323
+ cookieDomain,
324
+ data.ttl,
325
+ preAuthCookieName
326
+ );
327
+ res.status(204).end();
328
+ }
329
+ async function register(req, res) {
330
+ const up = await authFetch(req, `${authServerUrl}/registration/register`, {
331
+ method: "POST",
332
+ body: req.body
333
+ });
334
+ const data = await up.json();
335
+ if (!up.ok) return res.status(up.status).json(data);
336
+ setSessionCookie(
337
+ res,
338
+ { sub: data.sub },
339
+ cookieDomain,
340
+ data.ttl,
341
+ registrationCookieName
342
+ );
343
+ res.status(200).json(data).end();
344
+ }
345
+ async function finishLogin(req, res) {
346
+ const up = await authFetch(req, `${authServerUrl}/webAuthn/login/finish`, {
347
+ method: "POST",
348
+ body: req.body
349
+ });
350
+ const data = await up.json();
351
+ if (!up.ok) return res.status(up.status).json(data);
352
+ const verifiedAccessToken = await verifySignedAuthResponse(
353
+ data.token,
354
+ authServerUrl
355
+ );
356
+ if (!verifiedAccessToken) {
357
+ throw new Error("Invalid signed response from Auth Server");
358
+ }
359
+ if (verifiedAccessToken.sub !== data.sub) {
360
+ throw new Error("Signature mismatch with data payload");
361
+ }
362
+ setSessionCookie(
363
+ res,
364
+ { sub: data.sub, roles: data.roles },
365
+ cookieDomain,
366
+ data.ttl,
367
+ accesscookieName
368
+ );
369
+ setSessionCookie(
370
+ res,
371
+ { sub: data.sub, refreshToken: data.refreshToken },
372
+ req.hostname,
373
+ data.refreshTtl,
374
+ refreshCookieName
375
+ );
376
+ res.status(200).json(data).end();
377
+ }
378
+ async function finishRegister(req, res) {
379
+ const up = await authFetch(
380
+ req,
381
+ `${authServerUrl}/webAuthn/register/finish`,
382
+ {
383
+ method: "POST",
384
+ body: req.body
385
+ }
386
+ );
387
+ const data = await up.json();
388
+ if (!up.ok) return res.status(up.status).json(data);
389
+ setSessionCookie(
390
+ res,
391
+ { sub: data.sub, roles: data.roles },
392
+ cookieDomain,
393
+ data.ttl,
394
+ accesscookieName
395
+ );
396
+ res.status(204).end();
397
+ }
398
+ async function logout(req, res) {
399
+ await authFetch(req, `${authServerUrl}/logout`, {
400
+ method: "GET"
401
+ });
402
+ clearAllCookies(
403
+ res,
404
+ cookieDomain,
405
+ accesscookieName,
406
+ registrationCookieName,
407
+ refreshCookieName
408
+ );
409
+ res.status(204).end();
410
+ }
411
+ async function me(req, res) {
412
+ const up = await authFetch(req, `${authServerUrl}/users/me`, {
413
+ method: "GET"
414
+ });
415
+ const data = await up.json();
416
+ clearSessionCookie(res, cookieDomain, preAuthCookieName);
417
+ if (!data.user) return res.status(401).json({ error: "unauthenticated" });
418
+ res.json({ user: data.user });
419
+ }
420
+ }
421
+
422
+ // src/middleware/requireAuth.ts
423
+ import jwt5 from "jsonwebtoken";
424
+ function requireAuth(cookieName = "seamless-access", refreshCookieName = "seamless-refresh", cookieDomain = "/") {
425
+ const COOKIE_SECRET2 = process.env.SEAMLESS_COOKIE_SIGNING_KEY;
426
+ if (!COOKIE_SECRET2) {
427
+ console.warn(
428
+ "[SeamlessAuth] SEAMLESS_COOKIE_SIGNING_KEY missing \u2014 requireAuth will always fail."
429
+ );
430
+ throw new Error("Missing required env SEAMLESS_COOKIE_SIGNING_KEY");
431
+ }
432
+ const AUTH_SERVER_URL = process.env.AUTH_SERVER_URL;
433
+ return async (req, res, next) => {
434
+ try {
435
+ if (!COOKIE_SECRET2) {
436
+ throw new Error("Missing required SEAMLESS_COOKIE_SIGNING_KEY env");
437
+ }
438
+ const token = req.cookies?.[cookieName];
439
+ if (!token) {
440
+ res.status(401).json({ error: "Missing access cookie" });
441
+ return;
442
+ }
443
+ try {
444
+ const payload = jwt5.verify(token, COOKIE_SECRET2, {
445
+ algorithms: ["HS256"]
446
+ });
447
+ req.user = payload;
448
+ return next();
449
+ } catch (err) {
450
+ if (err.name !== "TokenExpiredError") {
451
+ console.warn("[SeamlessAuth] Invalid token:", err.message);
452
+ res.status(401).json({ error: "Invalid token" });
453
+ return;
454
+ }
455
+ const refreshToken = req.cookies?.[refreshCookieName];
456
+ if (!refreshToken) {
457
+ res.status(401).json({ error: "Session expired; re-login required" });
458
+ return;
459
+ }
460
+ console.log("[SeamlessAuth] Access token expired \u2014 attempting refresh");
461
+ const refreshed = await refreshAccessToken(
462
+ req,
463
+ AUTH_SERVER_URL,
464
+ refreshToken
465
+ );
466
+ if (!refreshed?.token) {
467
+ res.status(401).json({ error: "Refresh failed" });
468
+ return;
469
+ }
470
+ setSessionCookie(
471
+ res,
472
+ {
473
+ sub: refreshed.sub,
474
+ token: refreshed.token,
475
+ roles: refreshed.roles
476
+ },
477
+ cookieDomain,
478
+ refreshed.ttl,
479
+ cookieName
480
+ );
481
+ setSessionCookie(
482
+ res,
483
+ { sub: refreshed.sub, refreshToken: refreshed.refreshToken },
484
+ req.hostname,
485
+ refreshed.refreshTtl,
486
+ refreshCookieName
487
+ );
488
+ const payload = jwt5.verify(refreshed.token, COOKIE_SECRET2, {
489
+ algorithms: ["HS256"]
490
+ });
491
+ req.user = payload;
492
+ next();
493
+ }
494
+ } catch (err) {
495
+ console.error("[SeamlessAuth] requireAuth error:", err.message);
496
+ res.status(401).json({ error: "Invalid or expired access cookie" });
497
+ return;
498
+ }
499
+ };
500
+ }
501
+
502
+ // src/middleware/requireRole.ts
503
+ import jwt6 from "jsonwebtoken";
504
+ function requireRole(role, cookieName = "seamless-access") {
505
+ return (req, res, next) => {
506
+ try {
507
+ const COOKIE_SECRET2 = process.env.SEAMLESS_COOKIE_SIGNING_KEY;
508
+ if (!COOKIE_SECRET2) {
509
+ console.warn(
510
+ "[SeamlessAuth] SEAMLESS_COOKIE_SIGNING_KEY missing \u2014 requireRole will always fail."
511
+ );
512
+ throw new Error("Missing required env SEAMLESS_COOKIE_SIGNING_KEY");
513
+ }
514
+ const token = req.cookies?.[cookieName];
515
+ if (!token) {
516
+ res.status(401).json({ error: "Missing access cookie" });
517
+ return;
518
+ }
519
+ const payload = jwt6.verify(token, COOKIE_SECRET2, {
520
+ algorithms: ["HS256"]
521
+ });
522
+ if (!payload.roles?.includes(role)) {
523
+ res.status(403).json({ error: `Forbidden: ${role} role required` });
524
+ return;
525
+ }
526
+ next();
527
+ } catch (err) {
528
+ console.error(`[RequireRole] requireRole(${role}) failed:`, err.message);
529
+ res.status(401).json({ error: "Invalid or expired access cookie" });
530
+ }
531
+ };
532
+ }
533
+
534
+ // src/internal/getSeamlessUser.ts
535
+ async function getSeamlessUser(req, authServerUrl, cookieName = "seamless-access") {
536
+ try {
537
+ const payload = verifyCookieJwt(req.cookies[cookieName]);
538
+ if (!payload) {
539
+ throw new Error("Missing cookie");
540
+ }
541
+ req.cookiePayload = payload;
542
+ const response = await authFetch(req, `${authServerUrl}/users/me`, {
543
+ method: "GET"
544
+ });
545
+ if (!response.ok) {
546
+ console.warn(`[SeamlessAuth] Auth server responded ${response.status}`);
547
+ return null;
548
+ }
549
+ const data = await response.json();
550
+ return data.user;
551
+ } catch (err) {
552
+ console.error("[SeamlessAuth] getSeamlessUser failed:", err);
553
+ return null;
554
+ }
555
+ }
556
+
557
+ // src/index.ts
558
+ var index_default = createSeamlessAuthServer;
559
+ export {
560
+ index_default as default,
561
+ getSeamlessUser,
562
+ requireAuth,
563
+ requireRole
564
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seamless-auth/express",
3
- "version": "0.0.2-beta.1",
3
+ "version": "0.0.2-beta.2",
4
4
  "description": "Express adapter for Seamless Auth passwordless authentication",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -8,7 +8,7 @@
8
8
  "types": "./dist/index.d.ts",
9
9
  "author": "Fells Code LLC",
10
10
  "scripts": {
11
- "build": "tsc -p tsconfig.json && node build.mjs",
11
+ "build": "tsup src/index.ts --format esm --out-dir dist --splitting",
12
12
  "dev": "tsc --watch"
13
13
  },
14
14
  "repository": {
@@ -32,6 +32,7 @@
32
32
  "devDependencies": {
33
33
  "@types/cookie-parser": "^1.4.10",
34
34
  "@types/jsonwebtoken": "^9.0.10",
35
+ "tsup": "^8.5.1",
35
36
  "typescript": "^5.5.0"
36
37
  },
37
38
  "publishConfig": {
@@ -1,48 +0,0 @@
1
- import { Router } from "express";
2
- import type { SeamlessAuthServerOptions } from "./types";
3
- /**
4
- * Creates an Express Router that proxies all authentication traffic to a Seamless Auth server.
5
- *
6
- * This helper wires your API backend to a Seamless Auth instance running in
7
- * "server mode." It automatically forwards login, registration, WebAuthn,
8
- * logout, token refresh, and session validation routes to the auth server
9
- * and handles all cookie management required for a seamless login flow.
10
- *
11
- * ### Responsibilities
12
- * - Proxies all `/auth/*` routes to the upstream Seamless Auth server
13
- * - Manages `access`, `registration`, `pre-auth`, and `refresh` cookies
14
- * - Normalizes cookie settings for cross-domain or same-domain deployments
15
- * - Ensures authentication routes behave consistently across environments
16
- * - Provides shared middleware for auth flows
17
- *
18
- * ### Cookie Types
19
- * - **accessCookie** – long-lived session cookie for authenticated API requests
20
- * - **registrationCookie** – ephemeral cookie used during registration and OTP/WebAuthn flows
21
- * - **preAuthCookie** – short-lived cookie used during login initiation
22
- * - **refreshCookie** – opaque refresh token cookie used to rotate session tokens
23
- *
24
- * All cookie names and their domains may be customized via the `opts` parameter.
25
- *
26
- * ### Example
27
- * ```ts
28
- * app.use("/auth", createSeamlessAuthServer({
29
- * authServerUrl: "https://identifier.seamlessauth.com",
30
- * cookieDomain: "mycompany.com",
31
- * accesscookieName: "sa_access",
32
- * registrationCookieName: "sa_registration",
33
- * refreshCookieName: "sa_refresh",
34
- * }));
35
- * ```
36
- *
37
- * @param opts - Configuration options for the Seamless Auth proxy:
38
- * - `authServerUrl` — Base URL of your Seamless Auth instance (required)
39
- * - `cookieDomain` — Domain attribute applied to all auth cookies
40
- * - `accesscookieName` — Name of the session access cookie
41
- * - `registrationCookieName` — Name of the ephemeral registration cookie
42
- * - `refreshCookieName` — Name of the refresh token cookie
43
- * - `preAuthCookieName` — Name of the cookie used during login initiation
44
- *
45
- * @returns An Express `Router` preconfigured with all Seamless Auth routes.
46
- */
47
- export declare function createSeamlessAuthServer(opts: SeamlessAuthServerOptions): Router;
48
- //# sourceMappingURL=createServer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createServer.d.ts","sourceRoot":"","sources":["../src/createServer.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAqB,MAAM,EAAE,MAAM,SAAS,CAAC;AAQ7D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAC;AAIzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,yBAAyB,GAC9B,MAAM,CA0LR"}