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"
]
},
{
"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",
"properties": {
@ -19680,6 +19818,138 @@
"required": [
"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": [
"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"
]
},
{
"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",
"properties": {
@ -10661,6 +10799,138 @@
"required": [
"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": [
"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 {
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,
}
}

View File

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

View File

@ -29,6 +29,7 @@ import {
defaultFontType,
defaultProgressBarPosition,
} from '@typebot.io/schemas/features/typebot/theme/constants'
import { CorsError } from '@/utils/CorsError'
export type BotProps = {
// 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 (error) {
console.error(error)

View File

@ -11,6 +11,7 @@ import {
StartPreviewChatInput,
} from '@typebot.io/schemas'
import ky from 'ky'
import { CorsError } from '@/utils/CorsError'
type Props = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@ -102,27 +103,40 @@ export async function startChatQuery({
}
try {
const data = await ky
.post(
`${
isNotEmpty(apiHost) ? apiHost : guessApiHost()
}/api/v1/typebots/${typebotId}/startChat`,
{
json: {
isStreamEnabled: true,
prefilledVariables,
resultId,
isOnlyRegistering: false,
} satisfies Omit<
StartChatInput,
'publicId' | 'textBubbleContentFormat'
>,
timeout: false,
}
)
.json<InitialChatReply>()
const iframeReferrerOrigin =
parent !== window ? new URL(document.referrer).origin : undefined
const response = await ky.post(
`${
isNotEmpty(apiHost) ? apiHost : guessApiHost()
}/api/v1/typebots/${typebotId}/startChat`,
{
headers: {
'x-typebot-iframe-referrer-origin': iframeReferrerOrigin,
},
json: {
isStreamEnabled: true,
prefilledVariables,
resultId,
isOnlyRegistering: false,
} satisfies Omit<
StartChatInput,
'publicId' | 'textBubbleContentFormat'
>,
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) {
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",
"version": "0.2.87",
"version": "0.2.88",
"description": "Convenient library to display typebots on your Next.js website",
"main": "dist/index.js",
"types": "dist/index.d.ts",

View File

@ -1,6 +1,6 @@
{
"name": "@typebot.io/react",
"version": "0.2.87",
"version": "0.2.88",
"description": "Convenient library to display typebots on your React app",
"main": "dist/index.js",
"types": "dist/index.d.ts",