Skip to content

Commit 243e01b

Browse files
committed
extracted duplicate code into helper for resolving user from jwt
1 parent 28b51b7 commit 243e01b

File tree

1 file changed

+61
-194
lines changed

1 file changed

+61
-194
lines changed

apps/sim/lib/auth/hybrid.ts

Lines changed: 61 additions & 194 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,63 @@ export interface AuthResult {
1616
error?: string
1717
}
1818

19+
/**
20+
* Resolves userId from a verified internal JWT token.
21+
* Extracts workflowId/userId from URL params or POST body, then looks up userId if needed.
22+
*/
23+
async function resolveUserFromJwt(
24+
request: NextRequest,
25+
verificationUserId: string | null,
26+
options: { requireWorkflowId?: boolean }
27+
): Promise<AuthResult> {
28+
let workflowId: string | null = null
29+
let userId: string | null = verificationUserId
30+
31+
const { searchParams } = new URL(request.url)
32+
workflowId = searchParams.get('workflowId')
33+
if (!userId) {
34+
userId = searchParams.get('userId')
35+
}
36+
37+
if (!workflowId && !userId && request.method === 'POST') {
38+
try {
39+
const clonedRequest = request.clone()
40+
const bodyText = await clonedRequest.text()
41+
if (bodyText) {
42+
const body = JSON.parse(bodyText)
43+
workflowId = body.workflowId || body._context?.workflowId
44+
userId = userId || body.userId || body._context?.userId
45+
}
46+
} catch {
47+
// Ignore JSON parse errors
48+
}
49+
}
50+
51+
if (userId) {
52+
return { success: true, userId, authType: 'internal_jwt' }
53+
}
54+
55+
if (workflowId) {
56+
const [workflowData] = await db
57+
.select({ userId: workflow.userId })
58+
.from(workflow)
59+
.where(eq(workflow.id, workflowId))
60+
.limit(1)
61+
62+
if (!workflowData) {
63+
return { success: false, error: 'Workflow not found' }
64+
}
65+
66+
return { success: true, userId: workflowData.userId, authType: 'internal_jwt' }
67+
}
68+
69+
if (options.requireWorkflowId !== false) {
70+
return { success: false, error: 'workflowId or userId required for internal JWT calls' }
71+
}
72+
73+
return { success: true, authType: 'internal_jwt' }
74+
}
75+
1976
/**
2077
* Check for internal JWT authentication only.
2178
* Use this for routes that should ONLY be accessible by the executor (server-to-server).
@@ -51,75 +108,10 @@ export async function checkInternalAuth(
51108
const verification = await verifyInternalToken(token)
52109

53110
if (!verification.valid) {
54-
return {
55-
success: false,
56-
error: 'Invalid internal token',
57-
}
58-
}
59-
60-
let workflowId: string | null = null
61-
let userId: string | null = verification.userId || null
62-
63-
const { searchParams } = new URL(request.url)
64-
workflowId = searchParams.get('workflowId')
65-
if (!userId) {
66-
userId = searchParams.get('userId')
67-
}
68-
69-
if (!workflowId && !userId && request.method === 'POST') {
70-
try {
71-
const clonedRequest = request.clone()
72-
const bodyText = await clonedRequest.text()
73-
if (bodyText) {
74-
const body = JSON.parse(bodyText)
75-
workflowId = body.workflowId || body._context?.workflowId
76-
userId = userId || body.userId || body._context?.userId
77-
}
78-
} catch {
79-
// Ignore JSON parse errors
80-
}
81-
}
82-
83-
if (userId) {
84-
return {
85-
success: true,
86-
userId,
87-
authType: 'internal_jwt',
88-
}
89-
}
90-
91-
if (workflowId) {
92-
const [workflowData] = await db
93-
.select({ userId: workflow.userId })
94-
.from(workflow)
95-
.where(eq(workflow.id, workflowId))
96-
.limit(1)
97-
98-
if (!workflowData) {
99-
return {
100-
success: false,
101-
error: 'Workflow not found',
102-
}
103-
}
104-
105-
return {
106-
success: true,
107-
userId: workflowData.userId,
108-
authType: 'internal_jwt',
109-
}
111+
return { success: false, error: 'Invalid internal token' }
110112
}
111113

112-
if (options.requireWorkflowId !== false) {
113-
return {
114-
success: false,
115-
error: 'workflowId or userId required for internal JWT calls',
116-
}
117-
}
118-
119-
return {
120-
success: true,
121-
authType: 'internal_jwt',
122-
}
114+
return resolveUserFromJwt(request, verification.userId || null, options)
123115
} catch (error) {
124116
logger.error('Error in internal authentication:', error)
125117
return {
@@ -159,69 +151,7 @@ export async function checkSessionOrInternalAuth(
159151
const verification = await verifyInternalToken(token)
160152

161153
if (verification.valid) {
162-
let workflowId: string | null = null
163-
let userId: string | null = verification.userId || null
164-
165-
const { searchParams } = new URL(request.url)
166-
workflowId = searchParams.get('workflowId')
167-
if (!userId) {
168-
userId = searchParams.get('userId')
169-
}
170-
171-
if (!workflowId && !userId && request.method === 'POST') {
172-
try {
173-
const clonedRequest = request.clone()
174-
const bodyText = await clonedRequest.text()
175-
if (bodyText) {
176-
const body = JSON.parse(bodyText)
177-
workflowId = body.workflowId || body._context?.workflowId
178-
userId = userId || body.userId || body._context?.userId
179-
}
180-
} catch {
181-
// Ignore JSON parse errors
182-
}
183-
}
184-
185-
if (userId) {
186-
return {
187-
success: true,
188-
userId,
189-
authType: 'internal_jwt',
190-
}
191-
}
192-
193-
if (workflowId) {
194-
const [workflowData] = await db
195-
.select({ userId: workflow.userId })
196-
.from(workflow)
197-
.where(eq(workflow.id, workflowId))
198-
.limit(1)
199-
200-
if (!workflowData) {
201-
return {
202-
success: false,
203-
error: 'Workflow not found',
204-
}
205-
}
206-
207-
return {
208-
success: true,
209-
userId: workflowData.userId,
210-
authType: 'internal_jwt',
211-
}
212-
}
213-
214-
if (options.requireWorkflowId !== false) {
215-
return {
216-
success: false,
217-
error: 'workflowId or userId required for internal JWT calls',
218-
}
219-
}
220-
221-
return {
222-
success: true,
223-
authType: 'internal_jwt',
224-
}
154+
return resolveUserFromJwt(request, verification.userId || null, options)
225155
}
226156
}
227157

@@ -268,70 +198,7 @@ export async function checkHybridAuth(
268198
const verification = await verifyInternalToken(token)
269199

270200
if (verification.valid) {
271-
let workflowId: string | null = null
272-
let userId: string | null = verification.userId || null
273-
274-
const { searchParams } = new URL(request.url)
275-
workflowId = searchParams.get('workflowId')
276-
if (!userId) {
277-
userId = searchParams.get('userId')
278-
}
279-
280-
if (!workflowId && !userId && request.method === 'POST') {
281-
try {
282-
// Clone the request to avoid consuming the original body
283-
const clonedRequest = request.clone()
284-
const bodyText = await clonedRequest.text()
285-
if (bodyText) {
286-
const body = JSON.parse(bodyText)
287-
workflowId = body.workflowId || body._context?.workflowId
288-
userId = userId || body.userId || body._context?.userId
289-
}
290-
} catch {
291-
// Ignore JSON parse errors
292-
}
293-
}
294-
295-
if (userId) {
296-
return {
297-
success: true,
298-
userId,
299-
authType: 'internal_jwt',
300-
}
301-
}
302-
303-
if (workflowId) {
304-
const [workflowData] = await db
305-
.select({ userId: workflow.userId })
306-
.from(workflow)
307-
.where(eq(workflow.id, workflowId))
308-
.limit(1)
309-
310-
if (!workflowData) {
311-
return {
312-
success: false,
313-
error: 'Workflow not found',
314-
}
315-
}
316-
317-
return {
318-
success: true,
319-
userId: workflowData.userId,
320-
authType: 'internal_jwt',
321-
}
322-
}
323-
324-
if (options.requireWorkflowId !== false) {
325-
return {
326-
success: false,
327-
error: 'workflowId or userId required for internal JWT calls',
328-
}
329-
}
330-
331-
return {
332-
success: true,
333-
authType: 'internal_jwt',
334-
}
201+
return resolveUserFromJwt(request, verification.userId || null, options)
335202
}
336203
}
337204

0 commit comments

Comments
 (0)