2
0

🐛 Fix allowed origins when embedded in iframe

Closes #1518
This commit is contained in:
Baptiste Arnaud
2024-06-19 09:54:08 +02:00
parent 36c984643a
commit 67f37c02a4
9 changed files with 874 additions and 27 deletions

View File

@ -19078,6 +19078,144 @@
"action" "action"
] ]
}, },
{
"type": "object",
"properties": {
"baseUrl": {
"type": "string"
},
"apiVersion": {
"type": "string"
},
"credentialsId": {
"type": "string"
},
"action": {
"type": "string",
"enum": [
"Generate variables"
]
},
"model": {
"type": "string"
},
"prompt": {
"type": "string"
},
"variablesToExtract": {
"type": "array",
"items": {
"oneOf": [
{
"type": "object",
"properties": {}
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"string"
]
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"number"
]
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"boolean"
]
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"enum"
]
},
"values": {
"type": "array",
"items": {
"type": "string"
}
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
}
]
}
}
},
"required": [
"action"
]
},
{ {
"type": "object", "type": "object",
"properties": { "properties": {
@ -19680,6 +19818,138 @@
"required": [ "required": [
"action" "action"
] ]
},
{
"type": "object",
"properties": {
"credentialsId": {
"type": "string"
},
"action": {
"type": "string",
"enum": [
"Generate variables"
]
},
"model": {
"type": "string"
},
"prompt": {
"type": "string"
},
"variablesToExtract": {
"type": "array",
"items": {
"oneOf": [
{
"type": "object",
"properties": {}
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"string"
]
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"number"
]
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"boolean"
]
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"enum"
]
},
"values": {
"type": "array",
"items": {
"type": "string"
}
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
}
]
}
}
},
"required": [
"action"
]
} }
] ]
} }
@ -19908,6 +20178,146 @@
"required": [ "required": [
"action" "action"
] ]
},
{
"type": "object",
"properties": {
"credentialsId": {
"type": "string"
},
"action": {
"type": "string",
"enum": [
"Generate variables"
]
},
"model": {
"type": "string",
"enum": [
"claude-3-opus-20240229",
"claude-3-sonnet-20240229",
"claude-3-haiku-20240307",
"claude-2.1",
"claude-2.0",
"claude-instant-1.2"
]
},
"prompt": {
"type": "string"
},
"variablesToExtract": {
"type": "array",
"items": {
"oneOf": [
{
"type": "object",
"properties": {}
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"string"
]
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"number"
]
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"boolean"
]
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"enum"
]
},
"values": {
"type": "array",
"items": {
"type": "string"
}
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
}
]
}
}
},
"required": [
"action"
]
} }
] ]
} }

View File

@ -10059,6 +10059,144 @@
"action" "action"
] ]
}, },
{
"type": "object",
"properties": {
"baseUrl": {
"type": "string"
},
"apiVersion": {
"type": "string"
},
"credentialsId": {
"type": "string"
},
"action": {
"type": "string",
"enum": [
"Generate variables"
]
},
"model": {
"type": "string"
},
"prompt": {
"type": "string"
},
"variablesToExtract": {
"type": "array",
"items": {
"oneOf": [
{
"type": "object",
"properties": {}
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"string"
]
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"number"
]
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"boolean"
]
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"enum"
]
},
"values": {
"type": "array",
"items": {
"type": "string"
}
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
}
]
}
}
},
"required": [
"action"
]
},
{ {
"type": "object", "type": "object",
"properties": { "properties": {
@ -10661,6 +10799,138 @@
"required": [ "required": [
"action" "action"
] ]
},
{
"type": "object",
"properties": {
"credentialsId": {
"type": "string"
},
"action": {
"type": "string",
"enum": [
"Generate variables"
]
},
"model": {
"type": "string"
},
"prompt": {
"type": "string"
},
"variablesToExtract": {
"type": "array",
"items": {
"oneOf": [
{
"type": "object",
"properties": {}
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"string"
]
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"number"
]
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"boolean"
]
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"enum"
]
},
"values": {
"type": "array",
"items": {
"type": "string"
}
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
}
]
}
}
},
"required": [
"action"
]
} }
] ]
} }
@ -10889,6 +11159,146 @@
"required": [ "required": [
"action" "action"
] ]
},
{
"type": "object",
"properties": {
"credentialsId": {
"type": "string"
},
"action": {
"type": "string",
"enum": [
"Generate variables"
]
},
"model": {
"type": "string",
"enum": [
"claude-3-opus-20240229",
"claude-3-sonnet-20240229",
"claude-3-haiku-20240307",
"claude-2.1",
"claude-2.0",
"claude-instant-1.2"
]
},
"prompt": {
"type": "string"
},
"variablesToExtract": {
"type": "array",
"items": {
"oneOf": [
{
"type": "object",
"properties": {}
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"string"
]
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"number"
]
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"boolean"
]
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"enum"
]
},
"values": {
"type": "array",
"items": {
"type": "string"
}
},
"variableId": {
"type": "string"
},
"description": {
"type": "string"
},
"isRequired": {
"type": "boolean"
}
},
"required": [
"type"
]
}
]
}
}
},
"required": [
"action"
]
} }
] ]
} }

View File

@ -11,7 +11,10 @@ export async function createContext(opts: trpcNext.CreateNextContextOptions) {
return { return {
user, user,
origin: opts.req.headers.origin, origin:
(opts.req.headers['x-typebot-iframe-referrer-origin'] as
| string
| undefined) ?? opts.req.headers.origin,
res: opts.res, res: opts.res,
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@typebot.io/js", "name": "@typebot.io/js",
"version": "0.2.87", "version": "0.2.88",
"description": "Javascript library to display typebots on your website", "description": "Javascript library to display typebots on your website",
"type": "module", "type": "module",
"main": "dist/index.js", "main": "dist/index.js",
@ -48,4 +48,4 @@
"tailwindcss": "3.3.3", "tailwindcss": "3.3.3",
"typescript": "5.4.5" "typescript": "5.4.5"
} }
} }

View File

@ -29,6 +29,7 @@ import {
defaultFontType, defaultFontType,
defaultProgressBarPosition, defaultProgressBarPosition,
} from '@typebot.io/schemas/features/typebot/theme/constants' } from '@typebot.io/schemas/features/typebot/theme/constants'
import { CorsError } from '@/utils/CorsError'
export type BotProps = { export type BotProps = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
@ -106,6 +107,10 @@ export const Bot = (props: BotProps & { class?: string }) => {
) )
} }
if (error instanceof CorsError) {
return setError(new Error(error.message))
}
if (!data) { if (!data) {
if (error) { if (error) {
console.error(error) console.error(error)

View File

@ -11,6 +11,7 @@ import {
StartPreviewChatInput, StartPreviewChatInput,
} from '@typebot.io/schemas' } from '@typebot.io/schemas'
import ky from 'ky' import ky from 'ky'
import { CorsError } from '@/utils/CorsError'
type Props = { type Props = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
@ -102,27 +103,40 @@ export async function startChatQuery({
} }
try { try {
const data = await ky const iframeReferrerOrigin =
.post( parent !== window ? new URL(document.referrer).origin : undefined
`${ const response = await ky.post(
isNotEmpty(apiHost) ? apiHost : guessApiHost() `${
}/api/v1/typebots/${typebotId}/startChat`, isNotEmpty(apiHost) ? apiHost : guessApiHost()
{ }/api/v1/typebots/${typebotId}/startChat`,
json: { {
isStreamEnabled: true, headers: {
prefilledVariables, 'x-typebot-iframe-referrer-origin': iframeReferrerOrigin,
resultId, },
isOnlyRegistering: false, json: {
} satisfies Omit< isStreamEnabled: true,
StartChatInput, prefilledVariables,
'publicId' | 'textBubbleContentFormat' resultId,
>, isOnlyRegistering: false,
timeout: false, } satisfies Omit<
} StartChatInput,
) 'publicId' | 'textBubbleContentFormat'
.json<InitialChatReply>() >,
timeout: false,
}
)
return { data } const corsAllowOrigin = response.headers.get('access-control-allow-origin')
if (
iframeReferrerOrigin &&
corsAllowOrigin &&
corsAllowOrigin !== '*' &&
!iframeReferrerOrigin.includes(corsAllowOrigin)
)
throw new CorsError(corsAllowOrigin)
return { data: await response.json<InitialChatReply>() }
} catch (error) { } catch (error) {
return { error } return { error }
} }

View File

@ -0,0 +1,5 @@
export class CorsError extends Error {
constructor(origin: string) {
super('This bot can only be executed on ' + origin)
}
}

View File

@ -1,6 +1,6 @@
{ {
"name": "@typebot.io/nextjs", "name": "@typebot.io/nextjs",
"version": "0.2.87", "version": "0.2.88",
"description": "Convenient library to display typebots on your Next.js website", "description": "Convenient library to display typebots on your Next.js website",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
@ -42,4 +42,4 @@
"next": "12.x || 13.x || 14.x", "next": "12.x || 13.x || 14.x",
"react": "^16.0.0 || ^17.0.0 || ^18.0.0" "react": "^16.0.0 || ^17.0.0 || ^18.0.0"
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@typebot.io/react", "name": "@typebot.io/react",
"version": "0.2.87", "version": "0.2.88",
"description": "Convenient library to display typebots on your React app", "description": "Convenient library to display typebots on your React app",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
@ -45,4 +45,4 @@
"peerDependencies": { "peerDependencies": {
"react": "^16.0.0 || ^17.0.0 || ^18.0.0" "react": "^16.0.0 || ^17.0.0 || ^18.0.0"
} }
} }