@soulcraft/sdk 2.6.1 → 3.0.0
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/modules/auth/backchannel.d.ts +13 -39
- package/dist/modules/auth/backchannel.d.ts.map +1 -1
- package/dist/modules/auth/backchannel.js +12 -144
- package/dist/modules/auth/backchannel.js.map +1 -1
- package/dist/modules/auth/middleware.d.ts +45 -157
- package/dist/modules/auth/middleware.d.ts.map +1 -1
- package/dist/modules/auth/middleware.js +40 -322
- package/dist/modules/auth/middleware.js.map +1 -1
- package/dist/modules/auth/products.d.ts +1 -1
- package/dist/modules/auth/products.js +1 -1
- package/dist/modules/auth/request-backchannel.d.ts +94 -0
- package/dist/modules/auth/request-backchannel.d.ts.map +1 -0
- package/dist/modules/auth/request-backchannel.js +206 -0
- package/dist/modules/auth/request-backchannel.js.map +1 -0
- package/dist/modules/auth/request-middleware.d.ts +438 -0
- package/dist/modules/auth/request-middleware.d.ts.map +1 -0
- package/dist/modules/auth/request-middleware.js +650 -0
- package/dist/modules/auth/request-middleware.js.map +1 -0
- package/dist/modules/auth/service-token.d.ts +8 -7
- package/dist/modules/auth/service-token.d.ts.map +1 -1
- package/dist/modules/auth/service-token.js +8 -7
- package/dist/modules/auth/service-token.js.map +1 -1
- package/dist/modules/auth/sveltekit.d.ts +1 -1
- package/dist/modules/auth/sveltekit.d.ts.map +1 -1
- package/dist/modules/auth/sveltekit.js +1 -1
- package/dist/modules/auth/sveltekit.js.map +1 -1
- package/dist/namespaces.d.ts +1 -1
- package/dist/server/handlers/export.js +1 -1
- package/dist/server/handlers/export.js.map +1 -1
- package/dist/server/handlers/workspace.d.ts +1 -1
- package/dist/server/handlers/workspace.d.ts.map +1 -1
- package/dist/server/handlers/workspace.js +3 -4
- package/dist/server/handlers/workspace.js.map +1 -1
- package/dist/server/index.d.ts +5 -12
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +4 -9
- package/dist/server/index.js.map +1 -1
- package/dist/server/instance-pool.d.ts.map +1 -1
- package/dist/server/instance-pool.js +1 -0
- package/dist/server/instance-pool.js.map +1 -1
- package/dist/server/namespace-router.d.ts +1 -1
- package/dist/server/namespace-router.js +1 -1
- package/dist/server/rpc-handler.d.ts +2 -9
- package/dist/server/rpc-handler.d.ts.map +1 -1
- package/dist/server/rpc-handler.js +2 -9
- package/dist/server/rpc-handler.js.map +1 -1
- package/docs/ADR-001-sdk-design.md +3 -3
- package/docs/ADR-004-product-registry.md +1 -1
- package/docs/ADR-005-hall-integration.md +1 -1
- package/docs/ADR-006-rpc-cache.md +2 -2
- package/docs/IMPLEMENTATION-PLAN.md +7 -7
- package/docs/KIT-APP-GUIDE.md +100 -99
- package/docs/USAGE.md +30 -40
- package/docs/kit-sdk-guide.md +59 -60
- package/package.json +2 -7
- package/dist/server/hono-router.d.ts +0 -70
- package/dist/server/hono-router.d.ts.map +0 -1
- package/dist/server/hono-router.js +0 -167
- package/dist/server/hono-router.js.map +0 -1
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module modules/auth/middleware
|
|
3
|
-
* @description
|
|
4
|
-
*
|
|
3
|
+
* @description Session verification factories and shared auth types for Soulcraft
|
|
4
|
+
* product backends.
|
|
5
5
|
*
|
|
6
6
|
* ## Session verification strategies
|
|
7
7
|
*
|
|
8
|
-
* All products
|
|
9
|
-
* selects the right session verifier for its deployment context:
|
|
8
|
+
* All products select the right session verifier for their deployment context:
|
|
10
9
|
*
|
|
11
10
|
* ```
|
|
12
11
|
* Production (all products):
|
|
@@ -14,57 +13,45 @@
|
|
|
14
13
|
*
|
|
15
14
|
* Development (all products):
|
|
16
15
|
* createDevSessionVerifier({ role: 'owner' }) // auto-login, no OAuth needed
|
|
17
|
-
*
|
|
18
|
-
* Workshop standalone (legacy / local OAuth):
|
|
19
|
-
* createAuthMiddleware(betterAuthInstance) // BetterAuthLike overload
|
|
20
16
|
* ```
|
|
21
17
|
*
|
|
22
|
-
* ## Dev and guest
|
|
18
|
+
* ## Dev and guest cookie verifiers
|
|
19
|
+
*
|
|
20
|
+
* - `createDevCookieVerifier` — reads the dev session cookie issued by
|
|
21
|
+
* `createRequestDevLoginHandler` (from `request-middleware.ts`).
|
|
22
|
+
* - `createGuestCookieVerifier` — reads the guest session cookie issued by
|
|
23
|
+
* `createRequestGuestSessionHandler` (from `request-middleware.ts`).
|
|
24
|
+
*
|
|
25
|
+
* ## Framework-agnostic middleware
|
|
23
26
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* visitors can obtain a guest session (platformRole `'guest'`) for anonymous
|
|
28
|
-
* browse and booking flows, before they create an account.
|
|
27
|
+
* Use `createRequestAuthMiddleware` from `request-middleware.ts` for the
|
|
28
|
+
* framework-agnostic middleware that works with any Web Standard Request/Response
|
|
29
|
+
* server (SvelteKit, Bun, Deno, Cloudflare Workers, etc.).
|
|
29
30
|
*
|
|
30
31
|
* @example Production setup (Venue / Academy)
|
|
31
32
|
* ```typescript
|
|
32
|
-
* import {
|
|
33
|
+
* import {
|
|
34
|
+
* createRequestAuthMiddleware,
|
|
35
|
+
* createRemoteSessionVerifier,
|
|
36
|
+
* getUser,
|
|
37
|
+
* } from '@soulcraft/sdk/server'
|
|
33
38
|
*
|
|
34
39
|
* const verifySession = createRemoteSessionVerifier({ idpUrl: process.env.SOULCRAFT_IDP_URL! })
|
|
35
|
-
* const { requireAuth
|
|
40
|
+
* const { requireAuth } = createRequestAuthMiddleware(verifySession)
|
|
36
41
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
42
|
+
* // SvelteKit hooks:
|
|
43
|
+
* export const handle = async ({ event, resolve }) => {
|
|
44
|
+
* const response = await requireAuth(event.request, () => resolve(event))
|
|
45
|
+
* event.locals.user = getUser(event.request)
|
|
46
|
+
* return response
|
|
47
|
+
* }
|
|
40
48
|
* ```
|
|
41
49
|
*/
|
|
42
50
|
import { LRUCache } from 'lru-cache';
|
|
43
51
|
import { computeEmailHash } from './config.js';
|
|
44
52
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
45
|
-
// Types
|
|
46
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
47
|
-
/** The Hono context variable key where the resolved user is stored. */
|
|
48
|
-
export const AUTH_USER_KEY = 'user';
|
|
49
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
50
53
|
// Shared internal helpers
|
|
51
54
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
52
|
-
/** Resolve a raw user record from a better-auth session into a `SoulcraftSessionUser`. */
|
|
53
|
-
function _resolveUser(raw) {
|
|
54
|
-
const email = String(raw['email'] ?? '');
|
|
55
|
-
const emailHash = raw['emailHash']
|
|
56
|
-
? String(raw['emailHash'])
|
|
57
|
-
: computeEmailHash(email);
|
|
58
|
-
return {
|
|
59
|
-
id: String(raw['id'] ?? ''),
|
|
60
|
-
email,
|
|
61
|
-
name: String(raw['name'] ?? ''),
|
|
62
|
-
image: raw['image'] ?? null,
|
|
63
|
-
platformRole: raw['platformRole'] ?? 'creator',
|
|
64
|
-
emailHash,
|
|
65
|
-
...(raw['handle'] ? { handle: String(raw['handle']) } : {}),
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
55
|
/** Parse a simple `name=value` cookie from a raw cookie header string. */
|
|
69
56
|
function _parseCookie(cookieHeader, name) {
|
|
70
57
|
for (const part of cookieHeader.split(';')) {
|
|
@@ -74,10 +61,6 @@ function _parseCookie(cookieHeader, name) {
|
|
|
74
61
|
}
|
|
75
62
|
return undefined;
|
|
76
63
|
}
|
|
77
|
-
/** Encode a dev/guest session payload as a compact JSON+base64url string (unsigned). */
|
|
78
|
-
function _encodeSessionCookie(session) {
|
|
79
|
-
return Buffer.from(JSON.stringify(session)).toString('base64url');
|
|
80
|
-
}
|
|
81
64
|
/** Decode a session payload encoded by `_encodeSessionCookie`. Returns null on any error. */
|
|
82
65
|
function _decodeSessionCookie(value) {
|
|
83
66
|
try {
|
|
@@ -93,108 +76,6 @@ function _decodeSessionCookie(value) {
|
|
|
93
76
|
}
|
|
94
77
|
}
|
|
95
78
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
96
|
-
// createAuthMiddleware
|
|
97
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
98
|
-
/**
|
|
99
|
-
* Creates Hono auth middleware from a `SessionVerifier` function or a `BetterAuthLike`
|
|
100
|
-
* instance.
|
|
101
|
-
*
|
|
102
|
-
* **Preferred form (all products in OIDC-client mode):**
|
|
103
|
-
* Pass a `SessionVerifier` returned by `createRemoteSessionVerifier` or
|
|
104
|
-
* `createDevSessionVerifier`. The middleware reads the request cookie header and
|
|
105
|
-
* passes it to the verifier.
|
|
106
|
-
*
|
|
107
|
-
* **Legacy form (Workshop standalone mode):**
|
|
108
|
-
* Pass a `better-auth` instance directly. The middleware calls `auth.api.getSession`.
|
|
109
|
-
* In non-production environments and when `devAutoLogin` is enabled, a synthetic dev
|
|
110
|
-
* user is injected on failed lookups so local dev works without OAuth.
|
|
111
|
-
*
|
|
112
|
-
* Both forms return identical `{ requireAuth, optionalAuth }` middleware.
|
|
113
|
-
*
|
|
114
|
-
* @param authOrVerifier - A `better-auth` instance or a `SessionVerifier` function.
|
|
115
|
-
* @param options - Optional middleware configuration (only applies to `BetterAuthLike` form).
|
|
116
|
-
* @returns Middleware pair: `{ requireAuth, optionalAuth }`.
|
|
117
|
-
*
|
|
118
|
-
* @example Verifier form (Venue / Academy / Workshop in OIDC mode)
|
|
119
|
-
* ```typescript
|
|
120
|
-
* const verifySession = createRemoteSessionVerifier({ idpUrl: process.env.SOULCRAFT_IDP_URL! })
|
|
121
|
-
* const { requireAuth } = createAuthMiddleware(verifySession)
|
|
122
|
-
* ```
|
|
123
|
-
*
|
|
124
|
-
* @example BetterAuth form (Workshop dev standalone)
|
|
125
|
-
* ```typescript
|
|
126
|
-
* import { auth } from './better-auth.js'
|
|
127
|
-
* const { requireAuth } = createAuthMiddleware(auth)
|
|
128
|
-
* ```
|
|
129
|
-
*/
|
|
130
|
-
export function createAuthMiddleware(authOrVerifier, options = {}) {
|
|
131
|
-
const isVerifier = typeof authOrVerifier === 'function';
|
|
132
|
-
if (isVerifier) {
|
|
133
|
-
const verify = authOrVerifier;
|
|
134
|
-
const requireAuth = async (c, next) => {
|
|
135
|
-
const cookieHeader = c.req.header('cookie') ?? '';
|
|
136
|
-
const session = await verify(cookieHeader);
|
|
137
|
-
if (!session)
|
|
138
|
-
return c.json({ error: 'Authentication required' }, 401);
|
|
139
|
-
c.set(AUTH_USER_KEY, session.user);
|
|
140
|
-
await next();
|
|
141
|
-
return;
|
|
142
|
-
};
|
|
143
|
-
const optionalAuth = async (c, next) => {
|
|
144
|
-
const cookieHeader = c.req.header('cookie') ?? '';
|
|
145
|
-
const session = await verify(cookieHeader);
|
|
146
|
-
c.set(AUTH_USER_KEY, session?.user ?? null);
|
|
147
|
-
await next();
|
|
148
|
-
};
|
|
149
|
-
return { requireAuth, optionalAuth };
|
|
150
|
-
}
|
|
151
|
-
// BetterAuthLike form (Workshop standalone)
|
|
152
|
-
const auth = authOrVerifier;
|
|
153
|
-
const devAutoLogin = options.devAutoLogin ?? true;
|
|
154
|
-
const isDev = process.env['NODE_ENV'] !== 'production';
|
|
155
|
-
const DEV_USER = {
|
|
156
|
-
id: 'dev-user-001',
|
|
157
|
-
email: 'dev@localhost',
|
|
158
|
-
name: 'Dev User',
|
|
159
|
-
image: null,
|
|
160
|
-
emailHash: computeEmailHash('dev@localhost'),
|
|
161
|
-
platformRole: 'creator',
|
|
162
|
-
handle: 'dev',
|
|
163
|
-
};
|
|
164
|
-
const requireAuth = async (c, next) => {
|
|
165
|
-
if (isDev && devAutoLogin) {
|
|
166
|
-
if (!c.get(AUTH_USER_KEY))
|
|
167
|
-
c.set(AUTH_USER_KEY, DEV_USER);
|
|
168
|
-
await next();
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
const session = await auth.api.getSession({ headers: c.req.raw.headers });
|
|
172
|
-
if (!session?.user) {
|
|
173
|
-
return c.json({ error: 'Authentication required' }, 401);
|
|
174
|
-
}
|
|
175
|
-
c.set(AUTH_USER_KEY, _resolveUser(session.user));
|
|
176
|
-
await next();
|
|
177
|
-
return;
|
|
178
|
-
};
|
|
179
|
-
const optionalAuth = async (c, next) => {
|
|
180
|
-
if (isDev && devAutoLogin) {
|
|
181
|
-
if (!c.get(AUTH_USER_KEY))
|
|
182
|
-
c.set(AUTH_USER_KEY, DEV_USER);
|
|
183
|
-
await next();
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
const session = await auth.api.getSession({ headers: c.req.raw.headers });
|
|
187
|
-
if (session?.user) {
|
|
188
|
-
c.set(AUTH_USER_KEY, _resolveUser(session.user));
|
|
189
|
-
}
|
|
190
|
-
else {
|
|
191
|
-
c.set(AUTH_USER_KEY, null);
|
|
192
|
-
}
|
|
193
|
-
await next();
|
|
194
|
-
};
|
|
195
|
-
return { requireAuth, optionalAuth };
|
|
196
|
-
}
|
|
197
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
198
79
|
// createRemoteSessionVerifier
|
|
199
80
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
200
81
|
/**
|
|
@@ -208,10 +89,10 @@ export function createAuthMiddleware(authOrVerifier, options = {}) {
|
|
|
208
89
|
* The verifier sends the cookie header to the IdP's `/api/auth/get-session` endpoint
|
|
209
90
|
* and returns the resolved `SoulcraftSession` or `null` if the session is invalid.
|
|
210
91
|
*
|
|
211
|
-
* Pass the returned function
|
|
92
|
+
* Pass the returned function to `createRequestAuthMiddleware`:
|
|
212
93
|
* ```typescript
|
|
213
94
|
* const verifySession = createRemoteSessionVerifier({ idpUrl: process.env.SOULCRAFT_IDP_URL! })
|
|
214
|
-
* const { requireAuth } =
|
|
95
|
+
* const { requireAuth } = createRequestAuthMiddleware(verifySession)
|
|
215
96
|
* ```
|
|
216
97
|
*
|
|
217
98
|
* @param options - IdP URL, cache TTL, and max cache size.
|
|
@@ -224,8 +105,8 @@ export function createAuthMiddleware(authOrVerifier, options = {}) {
|
|
|
224
105
|
* cacheTtlMs: 30_000,
|
|
225
106
|
* })
|
|
226
107
|
*
|
|
227
|
-
* const session = await verifySession(
|
|
228
|
-
* if (!session) return
|
|
108
|
+
* const session = await verifySession(request.headers.get('cookie') ?? '')
|
|
109
|
+
* if (!session) return new Response('Unauthorized', { status: 401 })
|
|
229
110
|
* ```
|
|
230
111
|
*/
|
|
231
112
|
export function createRemoteSessionVerifier(options) {
|
|
@@ -306,7 +187,7 @@ export function createRemoteSessionVerifier(options) {
|
|
|
306
187
|
* ? createRemoteSessionVerifier({ idpUrl: process.env.SOULCRAFT_IDP_URL })
|
|
307
188
|
* : createDevSessionVerifier({ role: 'owner' })
|
|
308
189
|
*
|
|
309
|
-
* const { requireAuth } =
|
|
190
|
+
* const { requireAuth } = createRequestAuthMiddleware(verifySession)
|
|
310
191
|
* ```
|
|
311
192
|
*
|
|
312
193
|
* **Never use in production.** The verifier performs no validation whatsoever.
|
|
@@ -349,90 +230,12 @@ export function createDevSessionVerifier(options = {}) {
|
|
|
349
230
|
};
|
|
350
231
|
}
|
|
351
232
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
352
|
-
// createDevLoginHandler
|
|
353
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
354
|
-
/**
|
|
355
|
-
* Creates a Hono request handler for a dev login endpoint.
|
|
356
|
-
*
|
|
357
|
-
* Mount at `/api/dev/login` to get a role-switching endpoint for local
|
|
358
|
-
* development. Accepts `?role=<platformRole>` and optional `?email=` / `?name=`
|
|
359
|
-
* query params. Issues a signed base64url session cookie that `createAuthMiddleware`
|
|
360
|
-
* (when used with a `SessionVerifier` that reads dev cookies) can resolve.
|
|
361
|
-
*
|
|
362
|
-
* **Guards against production use:** the handler returns HTTP 404 when
|
|
363
|
-
* `NODE_ENV === 'production'` — it is safe to leave mounted in all environments.
|
|
364
|
-
*
|
|
365
|
-
* @param options - Allowed roles, cookie name, and max-age.
|
|
366
|
-
* @returns A Hono-compatible request handler `(c: Context) => Response`.
|
|
367
|
-
*
|
|
368
|
-
* @example
|
|
369
|
-
* ```typescript
|
|
370
|
-
* import { createDevLoginHandler } from '@soulcraft/sdk/server'
|
|
371
|
-
*
|
|
372
|
-
* // In your Hono server setup:
|
|
373
|
-
* app.get('/api/dev/login', createDevLoginHandler({ allowedRoles: ['owner', 'staff', 'customer'] }))
|
|
374
|
-
*
|
|
375
|
-
* // Usage: GET /api/dev/login?role=staff → sets cookie + redirects to /
|
|
376
|
-
* ```
|
|
377
|
-
*/
|
|
378
|
-
export function createDevLoginHandler(options = {}) {
|
|
379
|
-
const DEFAULT_ROLES = [
|
|
380
|
-
'creator', 'viewer', 'customer', 'staff', 'manager', 'owner', 'learner', 'instructor',
|
|
381
|
-
];
|
|
382
|
-
const allowedRoles = options.allowedRoles ?? DEFAULT_ROLES;
|
|
383
|
-
const cookieName = options.cookieName ?? 'soulcraft_dev_session';
|
|
384
|
-
const maxAgeSeconds = options.maxAgeSeconds ?? 86_400;
|
|
385
|
-
return function devLoginHandler(c) {
|
|
386
|
-
if (process.env['NODE_ENV'] === 'production') {
|
|
387
|
-
return c.json({ error: 'Not found' }, 404);
|
|
388
|
-
}
|
|
389
|
-
const role = c.req.query('role');
|
|
390
|
-
if (!role || !allowedRoles.includes(role)) {
|
|
391
|
-
return c.json({
|
|
392
|
-
error: `Invalid role. Allowed: ${allowedRoles.join(', ')}`,
|
|
393
|
-
allowedRoles,
|
|
394
|
-
}, 400);
|
|
395
|
-
}
|
|
396
|
-
const email = c.req.query('email') ?? `dev-${role}@soulcraft.com`;
|
|
397
|
-
const name = c.req.query('name') ?? `Dev ${role.charAt(0).toUpperCase() + role.slice(1)}`;
|
|
398
|
-
const redirect = c.req.query('redirect') ?? '/';
|
|
399
|
-
const session = {
|
|
400
|
-
user: {
|
|
401
|
-
id: `dev-user-${role}`,
|
|
402
|
-
email,
|
|
403
|
-
name,
|
|
404
|
-
image: null,
|
|
405
|
-
platformRole: role,
|
|
406
|
-
emailHash: computeEmailHash(email),
|
|
407
|
-
},
|
|
408
|
-
sessionId: `dev-session-${Date.now()}`,
|
|
409
|
-
expiresAt: Date.now() + maxAgeSeconds * 1000,
|
|
410
|
-
};
|
|
411
|
-
const cookieValue = _encodeSessionCookie(session);
|
|
412
|
-
const cookieHeader = [
|
|
413
|
-
`${cookieName}=${cookieValue}`,
|
|
414
|
-
`Path=/`,
|
|
415
|
-
`HttpOnly`,
|
|
416
|
-
`SameSite=Lax`,
|
|
417
|
-
`Max-Age=${maxAgeSeconds}`,
|
|
418
|
-
].join('; ');
|
|
419
|
-
const response = new Response(null, {
|
|
420
|
-
status: 302,
|
|
421
|
-
headers: {
|
|
422
|
-
Location: redirect,
|
|
423
|
-
'Set-Cookie': cookieHeader,
|
|
424
|
-
},
|
|
425
|
-
});
|
|
426
|
-
return response;
|
|
427
|
-
};
|
|
428
|
-
}
|
|
429
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
430
233
|
// createDevCookieVerifier
|
|
431
234
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
432
235
|
/**
|
|
433
|
-
* Creates a session verifier that reads the cookie issued by `
|
|
236
|
+
* Creates a session verifier that reads the cookie issued by `createRequestDevLoginHandler`.
|
|
434
237
|
*
|
|
435
|
-
* Use this together with `
|
|
238
|
+
* Use this together with `createRequestDevLoginHandler` when you want dev role-switching
|
|
436
239
|
* (e.g. clicking "Login as Staff" in a dev UI) rather than a fixed synthetic user.
|
|
437
240
|
*
|
|
438
241
|
* The verifier decodes the base64url cookie value and returns the embedded session.
|
|
@@ -445,12 +248,12 @@ export function createDevLoginHandler(options = {}) {
|
|
|
445
248
|
* const verifySession = createDevSessionVerifier({ role: 'owner' })
|
|
446
249
|
*
|
|
447
250
|
* // Option B: Role-switching dev login UI
|
|
448
|
-
*
|
|
251
|
+
* const loginHandler = createRequestDevLoginHandler({ allowedRoles: ['owner', 'staff', 'customer'] })
|
|
449
252
|
* const verifySession = createDevCookieVerifier()
|
|
450
253
|
* ```
|
|
451
254
|
*
|
|
452
|
-
* @param cookieName - Must match the `cookieName` passed to `
|
|
453
|
-
* @returns A `SessionVerifier` compatible with `
|
|
255
|
+
* @param cookieName - Must match the `cookieName` passed to `createRequestDevLoginHandler`. Default: `'soulcraft_dev_session'`.
|
|
256
|
+
* @returns A `SessionVerifier` compatible with `createRequestAuthMiddleware`.
|
|
454
257
|
*/
|
|
455
258
|
export function createDevCookieVerifier(cookieName = 'soulcraft_dev_session') {
|
|
456
259
|
return async function verifyDevCookie(cookieHeader) {
|
|
@@ -461,95 +264,10 @@ export function createDevCookieVerifier(cookieName = 'soulcraft_dev_session') {
|
|
|
461
264
|
};
|
|
462
265
|
}
|
|
463
266
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
464
|
-
// createGuestSessionHandler
|
|
465
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
466
|
-
/**
|
|
467
|
-
* Creates a Hono request handler that issues a guest session cookie.
|
|
468
|
-
*
|
|
469
|
-
* Venue visitors can browse and initiate bookings without creating an account.
|
|
470
|
-
* This handler mounts at e.g. `/api/guest/session` and issues a session cookie
|
|
471
|
-
* with `platformRole: 'guest'` and a unique guest ID on each call (if no valid
|
|
472
|
-
* guest session already exists).
|
|
473
|
-
*
|
|
474
|
-
* The guest session cookie can be verified using `createGuestCookieVerifier`,
|
|
475
|
-
* which returns a `SessionVerifier` compatible with `createAuthMiddleware`.
|
|
476
|
-
*
|
|
477
|
-
* @param options - Cookie name, max-age, and optional `onGuestCreated` callback.
|
|
478
|
-
* @returns A Hono-compatible request handler.
|
|
479
|
-
*
|
|
480
|
-
* @example
|
|
481
|
-
* ```typescript
|
|
482
|
-
* import { createGuestSessionHandler, createGuestCookieVerifier, createAuthMiddleware } from '@soulcraft/sdk/server'
|
|
483
|
-
*
|
|
484
|
-
* // Issue guest sessions
|
|
485
|
-
* app.post('/api/guest/session', createGuestSessionHandler({
|
|
486
|
-
* onGuestCreated: async (guestId) => {
|
|
487
|
-
* await db.guests.insert({ id: guestId, createdAt: new Date() })
|
|
488
|
-
* },
|
|
489
|
-
* }))
|
|
490
|
-
*
|
|
491
|
-
* // Verify guest sessions in optional auth (guests can browse)
|
|
492
|
-
* const verifyGuest = createGuestCookieVerifier()
|
|
493
|
-
* const verifySession = createRemoteSessionVerifier({ idpUrl: process.env.SOULCRAFT_IDP_URL! })
|
|
494
|
-
*
|
|
495
|
-
* // Compose: check real session first, fall back to guest
|
|
496
|
-
* const { optionalAuth } = createAuthMiddleware(async (cookie) =>
|
|
497
|
-
* await verifySession(cookie) ?? await verifyGuest(cookie)
|
|
498
|
-
* )
|
|
499
|
-
* ```
|
|
500
|
-
*/
|
|
501
|
-
export function createGuestSessionHandler(options = {}) {
|
|
502
|
-
const cookieName = options.cookieName ?? 'soulcraft_guest_session';
|
|
503
|
-
const maxAgeSeconds = options.maxAgeSeconds ?? 3_600;
|
|
504
|
-
const onGuestCreated = options.onGuestCreated;
|
|
505
|
-
return async function guestSessionHandler(c) {
|
|
506
|
-
// Return existing guest session if still valid
|
|
507
|
-
const cookieHeader = c.req.header('cookie') ?? '';
|
|
508
|
-
const existingValue = _parseCookie(cookieHeader, cookieName);
|
|
509
|
-
if (existingValue) {
|
|
510
|
-
const existing = _decodeSessionCookie(existingValue);
|
|
511
|
-
if (existing)
|
|
512
|
-
return c.json({ guestId: existing.user.id, existing: true });
|
|
513
|
-
}
|
|
514
|
-
// Create a new guest session
|
|
515
|
-
const guestId = `guest-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
516
|
-
const email = `${guestId}@guest.soulcraft.com`;
|
|
517
|
-
const session = {
|
|
518
|
-
user: {
|
|
519
|
-
id: guestId,
|
|
520
|
-
email,
|
|
521
|
-
name: 'Guest',
|
|
522
|
-
image: null,
|
|
523
|
-
platformRole: 'guest',
|
|
524
|
-
emailHash: computeEmailHash(email),
|
|
525
|
-
},
|
|
526
|
-
sessionId: `guest-session-${Date.now()}`,
|
|
527
|
-
expiresAt: Date.now() + maxAgeSeconds * 1000,
|
|
528
|
-
};
|
|
529
|
-
if (onGuestCreated)
|
|
530
|
-
await onGuestCreated(guestId);
|
|
531
|
-
const cookieValue = _encodeSessionCookie(session);
|
|
532
|
-
const cookieHeader2 = [
|
|
533
|
-
`${cookieName}=${cookieValue}`,
|
|
534
|
-
`Path=/`,
|
|
535
|
-
`HttpOnly`,
|
|
536
|
-
`SameSite=Lax`,
|
|
537
|
-
`Max-Age=${maxAgeSeconds}`,
|
|
538
|
-
].join('; ');
|
|
539
|
-
return new Response(JSON.stringify({ guestId, existing: false }), {
|
|
540
|
-
status: 200,
|
|
541
|
-
headers: {
|
|
542
|
-
'Content-Type': 'application/json',
|
|
543
|
-
'Set-Cookie': cookieHeader2,
|
|
544
|
-
},
|
|
545
|
-
});
|
|
546
|
-
};
|
|
547
|
-
}
|
|
548
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
549
267
|
// createGuestCookieVerifier
|
|
550
268
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
551
269
|
/**
|
|
552
|
-
* Creates a session verifier that reads the cookie issued by `
|
|
270
|
+
* Creates a session verifier that reads the cookie issued by `createRequestGuestSessionHandler`.
|
|
553
271
|
*
|
|
554
272
|
* Returns the guest `SoulcraftSession` or `null` if no valid guest cookie is present.
|
|
555
273
|
* Compose with `createRemoteSessionVerifier` to allow both authenticated and guest access:
|
|
@@ -558,13 +276,13 @@ export function createGuestSessionHandler(options = {}) {
|
|
|
558
276
|
* const verifyReal = createRemoteSessionVerifier({ idpUrl: process.env.SOULCRAFT_IDP_URL! })
|
|
559
277
|
* const verifyGuest = createGuestCookieVerifier()
|
|
560
278
|
*
|
|
561
|
-
* const { optionalAuth } =
|
|
279
|
+
* const { optionalAuth } = createRequestAuthMiddleware(async (cookie) =>
|
|
562
280
|
* await verifyReal(cookie) ?? await verifyGuest(cookie)
|
|
563
281
|
* )
|
|
564
282
|
* ```
|
|
565
283
|
*
|
|
566
|
-
* @param cookieName - Must match the `cookieName` passed to `
|
|
567
|
-
* @returns A `SessionVerifier` compatible with `
|
|
284
|
+
* @param cookieName - Must match the `cookieName` passed to `createRequestGuestSessionHandler`. Default: `'soulcraft_guest_session'`.
|
|
285
|
+
* @returns A `SessionVerifier` compatible with `createRequestAuthMiddleware`.
|
|
568
286
|
*/
|
|
569
287
|
export function createGuestCookieVerifier(cookieName = 'soulcraft_guest_session') {
|
|
570
288
|
return async function verifyGuestCookie(cookieHeader) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../src/modules/auth/middleware.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../src/modules/auth/middleware.ts"],"names":[],"mappings":"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"}
|
|
@@ -168,7 +168,7 @@ export type SoulcraftProduct = keyof typeof SOULCRAFT_PRODUCTS;
|
|
|
168
168
|
*
|
|
169
169
|
* Used by the auth server for:
|
|
170
170
|
* - `betterAuth({ trustedOrigins: deriveOrigins() })` — callback URL validation
|
|
171
|
-
* -
|
|
171
|
+
* - CORS origin allowlist for preflight validation
|
|
172
172
|
*
|
|
173
173
|
* @returns Deduplicated list of origin strings (scheme + host, no trailing slash).
|
|
174
174
|
*
|
|
@@ -114,7 +114,7 @@ export const SOULCRAFT_PRODUCTS = {
|
|
|
114
114
|
*
|
|
115
115
|
* Used by the auth server for:
|
|
116
116
|
* - `betterAuth({ trustedOrigins: deriveOrigins() })` — callback URL validation
|
|
117
|
-
* -
|
|
117
|
+
* - CORS origin allowlist for preflight validation
|
|
118
118
|
*
|
|
119
119
|
* @returns Deduplicated list of origin strings (scheme + host, no trailing slash).
|
|
120
120
|
*
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module modules/auth/request-backchannel
|
|
3
|
+
* @description Framework-agnostic OIDC back-channel logout handler using Web Standard
|
|
4
|
+
* Request/Response.
|
|
5
|
+
*
|
|
6
|
+
* Implements the OpenID Connect Back-Channel Logout 1.0 specification. When a user
|
|
7
|
+
* signs out of the central IdP (`auth.soulcraft.com`), the IdP POSTs a signed
|
|
8
|
+
* `logout_token` (HS256 JWT) to every registered product's back-channel logout
|
|
9
|
+
* endpoint. This handler verifies the token and deletes all active sessions for
|
|
10
|
+
* the identified user, ensuring immediate logout across all products.
|
|
11
|
+
*
|
|
12
|
+
* ## Protocol
|
|
13
|
+
*
|
|
14
|
+
* 1. IdP POSTs `application/x-www-form-urlencoded` body with `logout_token` field
|
|
15
|
+
* 2. Handler verifies HS256 JWT signature using the OIDC client secret
|
|
16
|
+
* 3. Handler validates standard claims: `iss`, `aud`, `events` (must contain
|
|
17
|
+
* `http://schemas.openid.net/event/backchannel-logout`)
|
|
18
|
+
* 4. Handler deletes all better-auth sessions for the `sub` (user ID) claim
|
|
19
|
+
* 5. Returns 200 on success, 400 for malformed tokens, 401 for bad signatures
|
|
20
|
+
*
|
|
21
|
+
* ## Mounting
|
|
22
|
+
*
|
|
23
|
+
* ```typescript
|
|
24
|
+
* import { createRequestBackchannelLogoutHandler } from '@soulcraft/sdk/server'
|
|
25
|
+
*
|
|
26
|
+
* const handleLogout = createRequestBackchannelLogoutHandler({
|
|
27
|
+
* auth,
|
|
28
|
+
* clientSecret: process.env.SOULCRAFT_OIDC_CLIENT_SECRET!,
|
|
29
|
+
* idpUrl: process.env.SOULCRAFT_IDP_URL!,
|
|
30
|
+
* clientId: process.env.SOULCRAFT_OIDC_CLIENT_ID!,
|
|
31
|
+
* })
|
|
32
|
+
*
|
|
33
|
+
* // SvelteKit: export const POST = ({ request }) => handleLogout(request)
|
|
34
|
+
* // Bun: if (url.pathname === '/api/auth/backchannel-logout') return handleLogout(req)
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
/** Minimal better-auth API surface needed for session deletion. */
|
|
38
|
+
export interface BackchannelAuthLike {
|
|
39
|
+
api: {
|
|
40
|
+
revokeUserSessions(opts: {
|
|
41
|
+
body: {
|
|
42
|
+
userId: string;
|
|
43
|
+
};
|
|
44
|
+
headers?: Headers;
|
|
45
|
+
}): Promise<unknown>;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* @description Configuration for `createRequestBackchannelLogoutHandler()`.
|
|
50
|
+
*/
|
|
51
|
+
export interface BackchannelLogoutConfig {
|
|
52
|
+
/** The product's better-auth instance (used to delete sessions). */
|
|
53
|
+
auth: BackchannelAuthLike;
|
|
54
|
+
/** This product's OIDC client secret — used to verify the logout_token signature. */
|
|
55
|
+
clientSecret: string;
|
|
56
|
+
/** The central IdP base URL — used to validate the `iss` claim. */
|
|
57
|
+
idpUrl: string;
|
|
58
|
+
/** This product's OIDC client ID — used to validate the `aud` claim. */
|
|
59
|
+
clientId: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* @description Creates a framework-agnostic request handler for the OIDC back-channel
|
|
63
|
+
* logout endpoint.
|
|
64
|
+
*
|
|
65
|
+
* The handler:
|
|
66
|
+
* 1. Parses the `logout_token` from the form-encoded or JSON body
|
|
67
|
+
* 2. Verifies the HS256 JWT signature using the OIDC client secret
|
|
68
|
+
* 3. Validates `iss` (must match idpUrl), `aud` (must match clientId),
|
|
69
|
+
* and `events` (must contain the back-channel logout event URI)
|
|
70
|
+
* 4. Calls `auth.api.revokeUserSessions({ body: { userId: sub } })` to
|
|
71
|
+
* immediately invalidate all sessions for the identified user
|
|
72
|
+
* 5. Returns 200 on success, 400 for malformed/missing token, 401 for
|
|
73
|
+
* invalid signature or failed claims validation
|
|
74
|
+
*
|
|
75
|
+
* @param config - Auth instance, client secret, IdP URL, and client ID.
|
|
76
|
+
* @returns An async request handler function `(req: Request) => Promise<Response>`.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* import { createRequestBackchannelLogoutHandler } from '@soulcraft/sdk/server'
|
|
81
|
+
*
|
|
82
|
+
* const handleLogout = createRequestBackchannelLogoutHandler({
|
|
83
|
+
* auth,
|
|
84
|
+
* clientSecret: process.env.SOULCRAFT_OIDC_CLIENT_SECRET!,
|
|
85
|
+
* idpUrl: process.env.SOULCRAFT_IDP_URL!,
|
|
86
|
+
* clientId: process.env.SOULCRAFT_OIDC_CLIENT_ID!,
|
|
87
|
+
* })
|
|
88
|
+
*
|
|
89
|
+
* // SvelteKit +server.ts:
|
|
90
|
+
* export const POST = ({ request }) => handleLogout(request)
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
export declare function createRequestBackchannelLogoutHandler(config: BackchannelLogoutConfig): (req: Request) => Promise<Response>;
|
|
94
|
+
//# sourceMappingURL=request-backchannel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-backchannel.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/request-backchannel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAMH,mEAAmE;AACnE,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE;QACH,kBAAkB,CAAC,IAAI,EAAE;YAAE,IAAI,EAAE;gBAAE,MAAM,EAAE,MAAM,CAAA;aAAE,CAAC;YAAC,OAAO,CAAC,EAAE,OAAO,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;KAC5F,CAAA;CACF;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,IAAI,EAAE,mBAAmB,CAAA;IACzB,qFAAqF;IACrF,YAAY,EAAE,MAAM,CAAA;IACpB,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAA;IACd,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAA;CACjB;AA0ED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,qCAAqC,CACnD,MAAM,EAAE,uBAAuB,GAC9B,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CA4FrC"}
|