@originals/auth 1.5.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.
Files changed (59) hide show
  1. package/.turbo/turbo-build.log +1 -0
  2. package/dist/client/index.d.ts +22 -0
  3. package/dist/client/index.d.ts.map +1 -0
  4. package/dist/client/index.js +22 -0
  5. package/dist/client/index.js.map +1 -0
  6. package/dist/client/turnkey-client.d.ts +53 -0
  7. package/dist/client/turnkey-client.d.ts.map +1 -0
  8. package/dist/client/turnkey-client.js +268 -0
  9. package/dist/client/turnkey-client.js.map +1 -0
  10. package/dist/client/turnkey-did-signer.d.ts +54 -0
  11. package/dist/client/turnkey-did-signer.d.ts.map +1 -0
  12. package/dist/client/turnkey-did-signer.js +125 -0
  13. package/dist/client/turnkey-did-signer.js.map +1 -0
  14. package/dist/index.d.ts +23 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +27 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/server/email-auth.d.ts +42 -0
  19. package/dist/server/email-auth.d.ts.map +1 -0
  20. package/dist/server/email-auth.js +187 -0
  21. package/dist/server/email-auth.js.map +1 -0
  22. package/dist/server/index.d.ts +22 -0
  23. package/dist/server/index.d.ts.map +1 -0
  24. package/dist/server/index.js +22 -0
  25. package/dist/server/index.js.map +1 -0
  26. package/dist/server/jwt.d.ts +49 -0
  27. package/dist/server/jwt.d.ts.map +1 -0
  28. package/dist/server/jwt.js +113 -0
  29. package/dist/server/jwt.js.map +1 -0
  30. package/dist/server/middleware.d.ts +39 -0
  31. package/dist/server/middleware.d.ts.map +1 -0
  32. package/dist/server/middleware.js +110 -0
  33. package/dist/server/middleware.js.map +1 -0
  34. package/dist/server/turnkey-client.d.ts +24 -0
  35. package/dist/server/turnkey-client.d.ts.map +1 -0
  36. package/dist/server/turnkey-client.js +118 -0
  37. package/dist/server/turnkey-client.js.map +1 -0
  38. package/dist/server/turnkey-signer.d.ts +40 -0
  39. package/dist/server/turnkey-signer.d.ts.map +1 -0
  40. package/dist/server/turnkey-signer.js +121 -0
  41. package/dist/server/turnkey-signer.js.map +1 -0
  42. package/dist/types.d.ts +155 -0
  43. package/dist/types.d.ts.map +1 -0
  44. package/dist/types.js +5 -0
  45. package/dist/types.js.map +1 -0
  46. package/package.json +79 -0
  47. package/src/client/index.ts +37 -0
  48. package/src/client/turnkey-client.ts +340 -0
  49. package/src/client/turnkey-did-signer.ts +189 -0
  50. package/src/index.ts +32 -0
  51. package/src/server/email-auth.ts +258 -0
  52. package/src/server/index.ts +38 -0
  53. package/src/server/jwt.ts +154 -0
  54. package/src/server/middleware.ts +136 -0
  55. package/src/server/turnkey-client.ts +152 -0
  56. package/src/server/turnkey-signer.ts +170 -0
  57. package/src/types.ts +168 -0
  58. package/tests/index.test.ts +25 -0
  59. package/tsconfig.json +28 -0
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Turnkey Email Authentication Service
3
+ * Implements email-based authentication using Turnkey's OTP flow
4
+ */
5
+ import { Turnkey } from '@turnkey/sdk-server';
6
+ import type { EmailAuthSession, InitiateAuthResult, VerifyAuthResult } from '../types';
7
+ /**
8
+ * Session storage interface for pluggable session management
9
+ */
10
+ export interface SessionStorage {
11
+ get(sessionId: string): EmailAuthSession | undefined;
12
+ set(sessionId: string, session: EmailAuthSession): void;
13
+ delete(sessionId: string): void;
14
+ cleanup(): void;
15
+ }
16
+ /**
17
+ * Create an in-memory session storage
18
+ * For production, consider using Redis or a database
19
+ */
20
+ export declare function createInMemorySessionStorage(): SessionStorage;
21
+ /**
22
+ * Initiate email authentication using Turnkey OTP
23
+ * Sends a 6-digit OTP code to the user's email
24
+ */
25
+ export declare function initiateEmailAuth(email: string, turnkeyClient: Turnkey, sessionStorage?: SessionStorage): Promise<InitiateAuthResult>;
26
+ /**
27
+ * Verify email authentication code using Turnkey OTP
28
+ */
29
+ export declare function verifyEmailAuth(sessionId: string, code: string, turnkeyClient: Turnkey, sessionStorage?: SessionStorage): Promise<VerifyAuthResult>;
30
+ /**
31
+ * Check if a session is verified
32
+ */
33
+ export declare function isSessionVerified(sessionId: string, sessionStorage?: SessionStorage): boolean;
34
+ /**
35
+ * Clean up a session after successful login
36
+ */
37
+ export declare function cleanupSession(sessionId: string, sessionStorage?: SessionStorage): void;
38
+ /**
39
+ * Get session data
40
+ */
41
+ export declare function getSession(sessionId: string, sessionStorage?: SessionStorage): EmailAuthSession | undefined;
42
+ //# sourceMappingURL=email-auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email-auth.d.ts","sourceRoot":"","sources":["../../src/server/email-auth.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAG9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAMvF;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAAC;IACrD,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACxD,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,IAAI,cAAc,CA2B7D;AAmBD;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,OAAO,EACtB,cAAc,CAAC,EAAE,cAAc,GAC9B,OAAO,CAAC,kBAAkB,CAAC,CA2D7B;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,OAAO,EACtB,cAAc,CAAC,EAAE,cAAc,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAqD3B;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,cAAc,CAAC,EAAE,cAAc,GAC9B,OAAO,CAYT;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,cAAc,CAAC,EAAE,cAAc,GAC9B,IAAI,CAGN;AAED;;GAEG;AACH,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,EACjB,cAAc,CAAC,EAAE,cAAc,GAC9B,gBAAgB,GAAG,SAAS,CAa9B"}
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Turnkey Email Authentication Service
3
+ * Implements email-based authentication using Turnkey's OTP flow
4
+ */
5
+ import { sha256 } from '@noble/hashes/sha2.js';
6
+ import { bytesToHex } from '@noble/hashes/utils.js';
7
+ import { getOrCreateTurnkeySubOrg } from './turnkey-client';
8
+ // Session timeout (15 minutes to match Turnkey OTP)
9
+ const SESSION_TIMEOUT = 15 * 60 * 1000;
10
+ /**
11
+ * Create an in-memory session storage
12
+ * For production, consider using Redis or a database
13
+ */
14
+ export function createInMemorySessionStorage() {
15
+ const sessions = new Map();
16
+ // Start cleanup interval
17
+ const cleanupInterval = setInterval(() => {
18
+ const now = Date.now();
19
+ for (const [sessionId, session] of sessions.entries()) {
20
+ if (now - session.timestamp > SESSION_TIMEOUT) {
21
+ sessions.delete(sessionId);
22
+ }
23
+ }
24
+ }, 60 * 1000);
25
+ // Keep the interval from preventing process exit
26
+ if (cleanupInterval.unref) {
27
+ cleanupInterval.unref();
28
+ }
29
+ return {
30
+ get: (sessionId) => sessions.get(sessionId),
31
+ set: (sessionId, session) => sessions.set(sessionId, session),
32
+ delete: (sessionId) => sessions.delete(sessionId),
33
+ cleanup: () => {
34
+ clearInterval(cleanupInterval);
35
+ sessions.clear();
36
+ },
37
+ };
38
+ }
39
+ // Default session storage
40
+ let defaultSessionStorage = null;
41
+ function getDefaultSessionStorage() {
42
+ if (!defaultSessionStorage) {
43
+ defaultSessionStorage = createInMemorySessionStorage();
44
+ }
45
+ return defaultSessionStorage;
46
+ }
47
+ /**
48
+ * Generate a random session ID
49
+ */
50
+ function generateSessionId() {
51
+ return `session_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
52
+ }
53
+ /**
54
+ * Initiate email authentication using Turnkey OTP
55
+ * Sends a 6-digit OTP code to the user's email
56
+ */
57
+ export async function initiateEmailAuth(email, turnkeyClient, sessionStorage) {
58
+ const storage = sessionStorage ?? getDefaultSessionStorage();
59
+ // Validate email format
60
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
61
+ if (!emailRegex.test(email)) {
62
+ throw new Error('Invalid email format');
63
+ }
64
+ console.log(`\n🚀 Initiating email auth for: ${email}`);
65
+ // Step 1: Get or create Turnkey sub-organization
66
+ const subOrgId = await getOrCreateTurnkeySubOrg(email, turnkeyClient);
67
+ // Step 2: Send OTP via Turnkey
68
+ console.log(`📨 Sending OTP to ${email} via Turnkey...`);
69
+ // Generate a unique user identifier for rate limiting
70
+ const data = new TextEncoder().encode(email);
71
+ const hash = sha256(data);
72
+ const userIdentifier = bytesToHex(hash);
73
+ const otpResult = await turnkeyClient.apiClient().initOtp({
74
+ otpType: 'OTP_TYPE_EMAIL',
75
+ contact: email,
76
+ userIdentifier: userIdentifier,
77
+ appName: 'Originals',
78
+ otpLength: 6,
79
+ alphanumeric: false,
80
+ });
81
+ const otpId = otpResult.otpId;
82
+ if (!otpId) {
83
+ throw new Error('Failed to initiate OTP - no OTP ID returned');
84
+ }
85
+ console.log(`✅ OTP sent! OTP ID: ${otpId}`);
86
+ // Create auth session
87
+ const sessionId = generateSessionId();
88
+ storage.set(sessionId, {
89
+ email,
90
+ subOrgId,
91
+ otpId,
92
+ timestamp: Date.now(),
93
+ verified: false,
94
+ });
95
+ console.log('='.repeat(60));
96
+ console.log(`📧 Check ${email} for the verification code!`);
97
+ console.log(` Session ID: ${sessionId}`);
98
+ console.log(` Valid for: 15 minutes`);
99
+ console.log('='.repeat(60) + '\n');
100
+ return {
101
+ sessionId,
102
+ message: 'Verification code sent to your email. Check your inbox!',
103
+ };
104
+ }
105
+ /**
106
+ * Verify email authentication code using Turnkey OTP
107
+ */
108
+ export async function verifyEmailAuth(sessionId, code, turnkeyClient, sessionStorage) {
109
+ const storage = sessionStorage ?? getDefaultSessionStorage();
110
+ const session = storage.get(sessionId);
111
+ if (!session) {
112
+ throw new Error('Invalid or expired session');
113
+ }
114
+ // Check if session has expired
115
+ if (Date.now() - session.timestamp > SESSION_TIMEOUT) {
116
+ storage.delete(sessionId);
117
+ throw new Error('Session expired. Please request a new code.');
118
+ }
119
+ if (!session.otpId) {
120
+ throw new Error('OTP ID not found in session');
121
+ }
122
+ if (!session.subOrgId) {
123
+ throw new Error('Sub-organization ID not found');
124
+ }
125
+ console.log(`\n🔐 Verifying OTP for session ${sessionId}...`);
126
+ try {
127
+ // Verify the OTP code with Turnkey
128
+ const verifyResult = await turnkeyClient.apiClient().verifyOtp({
129
+ otpId: session.otpId,
130
+ otpCode: code,
131
+ expirationSeconds: '900', // 15 minutes
132
+ });
133
+ if (!verifyResult.verificationToken) {
134
+ throw new Error('OTP verification failed - no verification token returned');
135
+ }
136
+ console.log(`✅ OTP verified successfully!`);
137
+ // Mark session as verified
138
+ session.verified = true;
139
+ storage.set(sessionId, session);
140
+ return {
141
+ verified: true,
142
+ email: session.email,
143
+ subOrgId: session.subOrgId,
144
+ };
145
+ }
146
+ catch (error) {
147
+ console.error('❌ OTP verification failed:', error);
148
+ throw new Error(`Invalid verification code: ${error instanceof Error ? error.message : String(error)}`);
149
+ }
150
+ }
151
+ /**
152
+ * Check if a session is verified
153
+ */
154
+ export function isSessionVerified(sessionId, sessionStorage) {
155
+ const storage = sessionStorage ?? getDefaultSessionStorage();
156
+ const session = storage.get(sessionId);
157
+ if (!session)
158
+ return false;
159
+ if (Date.now() - session.timestamp > SESSION_TIMEOUT) {
160
+ storage.delete(sessionId);
161
+ return false;
162
+ }
163
+ return session.verified;
164
+ }
165
+ /**
166
+ * Clean up a session after successful login
167
+ */
168
+ export function cleanupSession(sessionId, sessionStorage) {
169
+ const storage = sessionStorage ?? getDefaultSessionStorage();
170
+ storage.delete(sessionId);
171
+ }
172
+ /**
173
+ * Get session data
174
+ */
175
+ export function getSession(sessionId, sessionStorage) {
176
+ const storage = sessionStorage ?? getDefaultSessionStorage();
177
+ const session = storage.get(sessionId);
178
+ if (!session)
179
+ return undefined;
180
+ // Check if expired
181
+ if (Date.now() - session.timestamp > SESSION_TIMEOUT) {
182
+ storage.delete(sessionId);
183
+ return undefined;
184
+ }
185
+ return session;
186
+ }
187
+ //# sourceMappingURL=email-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email-auth.js","sourceRoot":"","sources":["../../src/server/email-auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Server-side authentication utilities
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * import {
7
+ * createAuthMiddleware,
8
+ * initiateEmailAuth,
9
+ * verifyEmailAuth,
10
+ * signToken,
11
+ * verifyToken,
12
+ * createTurnkeyClient,
13
+ * TurnkeyWebVHSigner
14
+ * } from '@originals/auth/server';
15
+ * ```
16
+ */
17
+ export { createTurnkeyClient, getOrCreateTurnkeySubOrg } from './turnkey-client';
18
+ export { initiateEmailAuth, verifyEmailAuth, isSessionVerified, cleanupSession, getSession, type SessionStorage, createInMemorySessionStorage, } from './email-auth';
19
+ export { signToken, verifyToken, getAuthCookieConfig, getClearAuthCookieConfig, } from './jwt';
20
+ export { createAuthMiddleware } from './middleware';
21
+ export { TurnkeyWebVHSigner, createTurnkeySigner } from './turnkey-signer';
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,UAAU,EACV,KAAK,cAAc,EACnB,4BAA4B,GAC7B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,SAAS,EACT,WAAW,EACX,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Server-side authentication utilities
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * import {
7
+ * createAuthMiddleware,
8
+ * initiateEmailAuth,
9
+ * verifyEmailAuth,
10
+ * signToken,
11
+ * verifyToken,
12
+ * createTurnkeyClient,
13
+ * TurnkeyWebVHSigner
14
+ * } from '@originals/auth/server';
15
+ * ```
16
+ */
17
+ export { createTurnkeyClient, getOrCreateTurnkeySubOrg } from './turnkey-client';
18
+ export { initiateEmailAuth, verifyEmailAuth, isSessionVerified, cleanupSession, getSession, createInMemorySessionStorage, } from './email-auth';
19
+ export { signToken, verifyToken, getAuthCookieConfig, getClearAuthCookieConfig, } from './jwt';
20
+ export { createAuthMiddleware } from './middleware';
21
+ export { TurnkeyWebVHSigner, createTurnkeySigner } from './turnkey-signer';
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,UAAU,EAEV,4BAA4B,GAC7B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,SAAS,EACT,WAAW,EACX,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * JWT Authentication Module
3
+ * Implements secure token issuance and validation with HTTP-only cookies
4
+ */
5
+ import type { TokenPayload, AuthCookieConfig } from '../types';
6
+ /**
7
+ * Sign a JWT token for a user
8
+ * @param subOrgId - Turnkey sub-organization ID (stable identifier)
9
+ * @param email - User email (metadata)
10
+ * @param sessionToken - Optional Turnkey session token for user authentication
11
+ * @param options - Additional options
12
+ * @returns Signed JWT token string
13
+ */
14
+ export declare function signToken(subOrgId: string, email: string, sessionToken?: string, options?: {
15
+ secret?: string;
16
+ expiresIn?: number;
17
+ issuer?: string;
18
+ audience?: string;
19
+ }): string;
20
+ /**
21
+ * Verify and decode a JWT token
22
+ * @param token - JWT token string
23
+ * @param options - Additional options
24
+ * @returns Decoded token payload
25
+ * @throws Error if token is invalid or expired
26
+ */
27
+ export declare function verifyToken(token: string, options?: {
28
+ secret?: string;
29
+ issuer?: string;
30
+ audience?: string;
31
+ }): TokenPayload;
32
+ /**
33
+ * Generate a secure cookie configuration for authentication tokens
34
+ * @param token - JWT token to set in cookie
35
+ * @param options - Cookie options
36
+ * @returns Cookie configuration object
37
+ */
38
+ export declare function getAuthCookieConfig(token: string, options?: {
39
+ cookieName?: string;
40
+ maxAge?: number;
41
+ secure?: boolean;
42
+ }): AuthCookieConfig;
43
+ /**
44
+ * Get cookie configuration for logout (clears the auth cookie)
45
+ * @param cookieName - Name of the cookie to clear
46
+ * @returns Cookie configuration for clearing
47
+ */
48
+ export declare function getClearAuthCookieConfig(cookieName?: string): AuthCookieConfig;
49
+ //# sourceMappingURL=jwt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/server/jwt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAgB/D;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACvB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE;IACR,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GACA,MAAM,CAuBR;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;IACR,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GACA,YAAY,CAuBd;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,GACA,gBAAgB,CAclB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAc9E"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * JWT Authentication Module
3
+ * Implements secure token issuance and validation with HTTP-only cookies
4
+ */
5
+ import jwt from 'jsonwebtoken';
6
+ // 7 days in seconds
7
+ const DEFAULT_JWT_EXPIRES_IN = 7 * 24 * 60 * 60;
8
+ /**
9
+ * Get JWT secret from config or environment
10
+ */
11
+ function getJwtSecret(configSecret) {
12
+ const secret = configSecret ?? process.env.JWT_SECRET;
13
+ if (!secret) {
14
+ throw new Error('JWT_SECRET environment variable is required');
15
+ }
16
+ return secret;
17
+ }
18
+ /**
19
+ * Sign a JWT token for a user
20
+ * @param subOrgId - Turnkey sub-organization ID (stable identifier)
21
+ * @param email - User email (metadata)
22
+ * @param sessionToken - Optional Turnkey session token for user authentication
23
+ * @param options - Additional options
24
+ * @returns Signed JWT token string
25
+ */
26
+ export function signToken(subOrgId, email, sessionToken, options) {
27
+ if (!subOrgId) {
28
+ throw new Error('Sub-organization ID is required for token signing');
29
+ }
30
+ const secret = getJwtSecret(options?.secret);
31
+ const payload = {
32
+ sub: subOrgId,
33
+ email,
34
+ };
35
+ if (sessionToken) {
36
+ payload.sessionToken = sessionToken;
37
+ }
38
+ const signOptions = {
39
+ expiresIn: options?.expiresIn ?? DEFAULT_JWT_EXPIRES_IN,
40
+ issuer: options?.issuer ?? 'originals-auth',
41
+ audience: options?.audience ?? 'originals-api',
42
+ };
43
+ return jwt.sign(payload, secret, signOptions);
44
+ }
45
+ /**
46
+ * Verify and decode a JWT token
47
+ * @param token - JWT token string
48
+ * @param options - Additional options
49
+ * @returns Decoded token payload
50
+ * @throws Error if token is invalid or expired
51
+ */
52
+ export function verifyToken(token, options) {
53
+ const secret = getJwtSecret(options?.secret);
54
+ try {
55
+ const payload = jwt.verify(token, secret, {
56
+ issuer: options?.issuer ?? 'originals-auth',
57
+ audience: options?.audience ?? 'originals-api',
58
+ });
59
+ if (!payload.sub) {
60
+ throw new Error('Token missing sub-organization ID');
61
+ }
62
+ return payload;
63
+ }
64
+ catch (error) {
65
+ if (error instanceof jwt.TokenExpiredError) {
66
+ throw new Error('Token has expired');
67
+ }
68
+ if (error instanceof jwt.JsonWebTokenError) {
69
+ throw new Error('Invalid token');
70
+ }
71
+ throw error;
72
+ }
73
+ }
74
+ /**
75
+ * Generate a secure cookie configuration for authentication tokens
76
+ * @param token - JWT token to set in cookie
77
+ * @param options - Cookie options
78
+ * @returns Cookie configuration object
79
+ */
80
+ export function getAuthCookieConfig(token, options) {
81
+ const isProduction = process.env.NODE_ENV === 'production';
82
+ return {
83
+ name: options?.cookieName ?? 'auth_token',
84
+ value: token,
85
+ options: {
86
+ httpOnly: true, // Cannot be accessed by JavaScript (XSS protection)
87
+ secure: options?.secure ?? isProduction, // HTTPS only in production
88
+ sameSite: 'strict', // CSRF protection
89
+ maxAge: options?.maxAge ?? 7 * 24 * 60 * 60 * 1000, // 7 days in milliseconds
90
+ path: '/', // Available for all routes
91
+ },
92
+ };
93
+ }
94
+ /**
95
+ * Get cookie configuration for logout (clears the auth cookie)
96
+ * @param cookieName - Name of the cookie to clear
97
+ * @returns Cookie configuration for clearing
98
+ */
99
+ export function getClearAuthCookieConfig(cookieName) {
100
+ const isProduction = process.env.NODE_ENV === 'production';
101
+ return {
102
+ name: cookieName ?? 'auth_token',
103
+ value: '',
104
+ options: {
105
+ httpOnly: true,
106
+ secure: isProduction,
107
+ sameSite: 'strict',
108
+ maxAge: 0, // Expire immediately
109
+ path: '/',
110
+ },
111
+ };
112
+ }
113
+ //# sourceMappingURL=jwt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/server/jwt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Express authentication middleware factory
3
+ */
4
+ import type { Request, Response, NextFunction } from 'express';
5
+ import type { AuthMiddlewareOptions } from '../types';
6
+ /**
7
+ * Create an authentication middleware for Express
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { createAuthMiddleware } from '@originals/auth/server';
12
+ *
13
+ * const authenticateUser = createAuthMiddleware({
14
+ * getUserByTurnkeyId: async (turnkeyId) => {
15
+ * return db.query.users.findFirst({
16
+ * where: eq(users.turnkeySubOrgId, turnkeyId)
17
+ * });
18
+ * },
19
+ * createUser: async (turnkeyId, email, temporaryDid) => {
20
+ * return db.insert(users).values({
21
+ * turnkeySubOrgId: turnkeyId,
22
+ * email,
23
+ * did: temporaryDid,
24
+ * }).returning().then(rows => rows[0]);
25
+ * }
26
+ * });
27
+ *
28
+ * app.get('/api/protected', authenticateUser, (req, res) => {
29
+ * res.json({ user: req.user });
30
+ * });
31
+ * ```
32
+ */
33
+ export declare function createAuthMiddleware(options: AuthMiddlewareOptions): (req: Request, res: Response, next: NextFunction) => Promise<void | Response>;
34
+ /**
35
+ * Optional authentication middleware - doesn't fail if not authenticated
36
+ * Attaches user to request if valid token exists, otherwise continues without user
37
+ */
38
+ export declare function createOptionalAuthMiddleware(options: AuthMiddlewareOptions): (req: Request, res: Response, next: NextFunction) => Promise<void>;
39
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/server/middleware.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE/D,OAAO,KAAK,EAAE,qBAAqB,EAAkC,MAAM,UAAU,CAAC;AAEtF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,qBAAqB,GAC7B,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,GAAG,QAAQ,CAAC,CAqD/E;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,qBAAqB,GAC7B,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAkCpE"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Express authentication middleware factory
3
+ */
4
+ import { verifyToken } from './jwt';
5
+ /**
6
+ * Create an authentication middleware for Express
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { createAuthMiddleware } from '@originals/auth/server';
11
+ *
12
+ * const authenticateUser = createAuthMiddleware({
13
+ * getUserByTurnkeyId: async (turnkeyId) => {
14
+ * return db.query.users.findFirst({
15
+ * where: eq(users.turnkeySubOrgId, turnkeyId)
16
+ * });
17
+ * },
18
+ * createUser: async (turnkeyId, email, temporaryDid) => {
19
+ * return db.insert(users).values({
20
+ * turnkeySubOrgId: turnkeyId,
21
+ * email,
22
+ * did: temporaryDid,
23
+ * }).returning().then(rows => rows[0]);
24
+ * }
25
+ * });
26
+ *
27
+ * app.get('/api/protected', authenticateUser, (req, res) => {
28
+ * res.json({ user: req.user });
29
+ * });
30
+ * ```
31
+ */
32
+ export function createAuthMiddleware(options) {
33
+ const cookieName = options.cookieName ?? 'auth_token';
34
+ return async (req, res, next) => {
35
+ try {
36
+ // Get JWT token from HTTP-only cookie
37
+ const token = req.cookies?.[cookieName];
38
+ if (!token) {
39
+ return res.status(401).json({ error: 'Not authenticated' });
40
+ }
41
+ // Verify JWT token
42
+ const payload = verifyToken(token, { secret: options.jwtSecret });
43
+ const turnkeySubOrgId = payload.sub;
44
+ const email = payload.email;
45
+ // Check if user already exists
46
+ let user = await options.getUserByTurnkeyId(turnkeySubOrgId);
47
+ // If user doesn't exist and createUser is provided, create user
48
+ if (!user && options.createUser) {
49
+ console.log(`Creating user record for ${email}...`);
50
+ // Use temporary DID as placeholder until user creates real DID
51
+ const temporaryDid = `temp:turnkey:${turnkeySubOrgId}`;
52
+ user = await options.createUser(turnkeySubOrgId, email, temporaryDid);
53
+ console.log(`✅ User created: ${email}`);
54
+ console.log(` Turnkey sub-org ID: ${turnkeySubOrgId}`);
55
+ console.log(` Temporary DID: ${temporaryDid}`);
56
+ }
57
+ if (!user) {
58
+ return res.status(401).json({ error: 'User not found' });
59
+ }
60
+ // Add user info to request
61
+ req.user = {
62
+ id: user.id,
63
+ turnkeySubOrgId,
64
+ email,
65
+ did: user.did,
66
+ sessionToken: payload.sessionToken,
67
+ };
68
+ next();
69
+ }
70
+ catch (error) {
71
+ console.error('Authentication error:', error);
72
+ return res.status(401).json({ error: 'Invalid or expired token' });
73
+ }
74
+ };
75
+ }
76
+ /**
77
+ * Optional authentication middleware - doesn't fail if not authenticated
78
+ * Attaches user to request if valid token exists, otherwise continues without user
79
+ */
80
+ export function createOptionalAuthMiddleware(options) {
81
+ const cookieName = options.cookieName ?? 'auth_token';
82
+ return async (req, res, next) => {
83
+ try {
84
+ const token = req.cookies?.[cookieName];
85
+ if (!token) {
86
+ next();
87
+ return;
88
+ }
89
+ const payload = verifyToken(token, { secret: options.jwtSecret });
90
+ const turnkeySubOrgId = payload.sub;
91
+ const email = payload.email;
92
+ const user = await options.getUserByTurnkeyId(turnkeySubOrgId);
93
+ if (user) {
94
+ req.user = {
95
+ id: user.id,
96
+ turnkeySubOrgId,
97
+ email,
98
+ did: user.did,
99
+ sessionToken: payload.sessionToken,
100
+ };
101
+ }
102
+ next();
103
+ }
104
+ catch {
105
+ // Token invalid or expired, continue without user
106
+ next();
107
+ }
108
+ };
109
+ }
110
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/server/middleware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Server-side Turnkey client utilities
3
+ */
4
+ import { Turnkey } from '@turnkey/sdk-server';
5
+ export interface TurnkeyClientConfig {
6
+ /** Turnkey API base URL (default: https://api.turnkey.com) */
7
+ apiBaseUrl?: string;
8
+ /** Turnkey API public key */
9
+ apiPublicKey: string;
10
+ /** Turnkey API private key */
11
+ apiPrivateKey: string;
12
+ /** Default organization ID */
13
+ organizationId: string;
14
+ }
15
+ /**
16
+ * Create a Turnkey server client
17
+ */
18
+ export declare function createTurnkeyClient(config?: Partial<TurnkeyClientConfig>): Turnkey;
19
+ /**
20
+ * Get or create a Turnkey sub-organization for a user
21
+ * Creates sub-org with email-only root user and required wallet accounts
22
+ */
23
+ export declare function getOrCreateTurnkeySubOrg(email: string, turnkeyClient: Turnkey): Promise<string>;
24
+ //# sourceMappingURL=turnkey-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turnkey-client.d.ts","sourceRoot":"","sources":["../../src/server/turnkey-client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE9C,MAAM,WAAW,mBAAmB;IAClC,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6BAA6B;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,8BAA8B;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,8BAA8B;IAC9B,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG,OAAO,CAqBlF;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,OAAO,GACrB,OAAO,CAAC,MAAM,CAAC,CAkGjB"}