Skip to content

Commit daebe62

Browse files
fix(files): normalize allow-list emails to lowercase; genericize shared SSO denial message
1 parent 7578702 commit daebe62

5 files changed

Lines changed: 15 additions & 6 deletions

File tree

apps/sim/app/api/chat/utils.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ describe('Chat API Utils', () => {
408408
})
409409

410410
expect(result.authorized).toBe(false)
411-
expect(result.error).toBe('Your email is not authorized to access this chat')
411+
expect(result.error).toBe('Your email is not authorized to access this resource')
412412
})
413413
})
414414
})

apps/sim/app/api/files/public/[token]/otp/route.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ describe('POST /api/files/public/[token]/otp', () => {
104104
expect(mockStoreOTP).not.toHaveBeenCalled()
105105
})
106106

107+
it('lowercases the email for allow-list matching and OTP storage', async () => {
108+
await POST(post('User@ACME.com'), params())
109+
expect(mockIsEmailAllowed).toHaveBeenCalledWith('user@acme.com', expect.anything())
110+
expect(mockStoreOTP).toHaveBeenCalledWith('file', 'sh_1', 'user@acme.com', '123456')
111+
})
112+
107113
it('rejects a non-email share with 400', async () => {
108114
mockResolveActiveShareByToken.mockResolvedValueOnce({
109115
...emailShare,

apps/sim/app/api/files/public/[token]/otp/route.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ export const POST = withRouteHandler(
6969
const parsed = await parseRequest(requestPublicFileOtpContract, request, context)
7070
if (!parsed.success) return parsed.response
7171
const { token } = parsed.data.params
72-
const { email } = parsed.data.body
72+
// Normalize once so allow-list matching, OTP storage, and the verify lookup
73+
// all key off the same value (allow-list entries are stored lowercase).
74+
const email = parsed.data.body.email.trim().toLowerCase()
7375

7476
const resolved = await resolveActiveShareByToken(token)
7577
if (!resolved) {
@@ -87,7 +89,7 @@ export const POST = withRouteHandler(
8789
}
8890

8991
const emailRateLimit = await rateLimiter.checkRateLimitDirect(
90-
`file-otp:email:${resolved.share.id}:${email.toLowerCase()}`,
92+
`file-otp:email:${resolved.share.id}:${email}`,
9193
OTP_EMAIL_RATE_LIMIT
9294
)
9395
if (!emailRateLimit.allowed) {
@@ -130,7 +132,8 @@ export const PUT = withRouteHandler(
130132
const parsed = await parseRequest(verifyPublicFileOtpContract, request, context)
131133
if (!parsed.success) return parsed.response
132134
const { token } = parsed.data.params
133-
const { email, otp } = parsed.data.body
135+
const { otp } = parsed.data.body
136+
const email = parsed.data.body.email.trim().toLowerCase()
134137

135138
const resolved = await resolveActiveShareByToken(token)
136139
if (!resolved) {

apps/sim/app/api/files/public/[token]/sso/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export const POST = withRouteHandler(
5353
const parsed = await parseRequest(publicFileSSOContract, request, context)
5454
if (!parsed.success) return parsed.response
5555
const { token } = parsed.data.params
56-
const { email } = parsed.data.body
56+
const email = parsed.data.body.email.trim().toLowerCase()
5757

5858
const resolved = await resolveActiveShareByToken(token)
5959
if (!resolved) {

apps/sim/lib/core/security/deployment-auth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ export async function validateDeploymentAuth(
188188
return { authorized: true }
189189
}
190190

191-
return { authorized: false, error: 'Your email is not authorized to access this chat' }
191+
return { authorized: false, error: 'Your email is not authorized to access this resource' }
192192
} catch (error) {
193193
logger.error(`[${requestId}] Error validating SSO:`, error)
194194
return { authorized: false, error: 'SSO authentication error' }

0 commit comments

Comments
 (0)