diff --git a/api/src/extensions/channels/console/i18n/en/label.json b/api/src/extensions/channels/console/i18n/en/label.json index 3c717b86..b9e4e4f1 100644 --- a/api/src/extensions/channels/console/i18n/en/label.json +++ b/api/src/extensions/channels/console/i18n/en/label.json @@ -1,5 +1,4 @@ { - "verification_token": "Verification Token", "allowed_domains": "Allowed Domains", "start_button": "Enable `Get Started`", "input_disabled": "Disable Input", diff --git a/api/src/extensions/channels/console/i18n/fr/label.json b/api/src/extensions/channels/console/i18n/fr/label.json index 23c3bb70..ce5473a5 100644 --- a/api/src/extensions/channels/console/i18n/fr/label.json +++ b/api/src/extensions/channels/console/i18n/fr/label.json @@ -1,5 +1,4 @@ { - "verification_token": "Jeton de vérification", "allowed_domains": "Domaines autorisés", "start_button": "Activer `Démarrer`", "input_disabled": "Désactiver la saisie", diff --git a/api/src/extensions/channels/console/settings.ts b/api/src/extensions/channels/console/settings.ts index 0f7102a9..d0e5abac 100644 --- a/api/src/extensions/channels/console/settings.ts +++ b/api/src/extensions/channels/console/settings.ts @@ -17,12 +17,6 @@ export const CONSOLE_CHANNEL_NAME = 'console-channel'; export const CONSOLE_CHANNEL_NAMESPACE = 'console_channel'; export default [ - { - group: CONSOLE_CHANNEL_NAMESPACE, - label: Web.SettingLabel.verification_token, - value: 'test', - type: SettingType.text, - }, { group: CONSOLE_CHANNEL_NAMESPACE, label: Web.SettingLabel.allowed_domains, diff --git a/api/src/extensions/channels/web/base-web-channel.ts b/api/src/extensions/channels/web/base-web-channel.ts index 2ff785df..cb8907a6 100644 --- a/api/src/extensions/channels/web/base-web-channel.ts +++ b/api/src/extensions/channels/web/base-web-channel.ts @@ -77,7 +77,7 @@ export default abstract class BaseWebChannelHandler< protected readonly attachmentService: AttachmentService, protected readonly messageService: MessageService, protected readonly menuService: MenuService, - private readonly websocketGateway: WebsocketGateway, + protected readonly websocketGateway: WebsocketGateway, ) { super(name, settingService, channelService, logger); } @@ -98,42 +98,32 @@ export default abstract class BaseWebChannelHandler< */ @OnEvent('hook:websocket:connection', { async: true }) async onWebSocketConnection(client: Socket) { - const settings = await this.getSettings(); - const handshake = client.handshake; - const { channel } = handshake.query; - if (channel !== this.getName()) { - return; - } try { - const { verification_token } = client.handshake.query; - await this.verifyToken(verification_token.toString()); - try { - this.logger.debug( - 'Web Channel Handler : WS connected .. sending settings', - ); - try { - const menu = await this.menuService.getTree(); - return client.emit('settings', { menu, ...settings }); - } catch (err) { - this.logger.warn( - 'Web Channel Handler : Unable to retrieve menu ', - err, - ); - return client.emit('settings', settings); - } - } catch (err) { - this.logger.warn( - 'Web Channel Handler : Unable to verify token, disconnecting ...', - err, - ); - client.disconnect(); + const settings = await this.getSettings(); + const handshake = client.handshake; + const { channel } = handshake.query; + + if (channel !== this.getName()) { return; } + + this.logger.debug( + 'Web Channel Handler : WS connected .. sending settings', + ); + + try { + const menu = await this.menuService.getTree(); + return client.emit('settings', { menu, ...settings }); + } catch (err) { + this.logger.warn('Web Channel Handler : Unable to retrieve menu ', err); + return client.emit('settings', settings); + } } catch (err) { this.logger.error( 'Web Channel Handler : Unable to initiate websocket connection', err, ); + client.disconnect(); } } @@ -218,7 +208,7 @@ export default abstract class BaseWebChannelHandler< * * @returns Formatted message */ - private formatHistoryMessages(messages: AnyMessage[]): Web.Message[] { + protected formatMessages(messages: AnyMessage[]): Web.Message[] { return messages.map((anyMessage: AnyMessage) => { if ('sender' in anyMessage && anyMessage.sender) { return { @@ -262,7 +252,7 @@ export default abstract class BaseWebChannelHandler< until, n, ); - return this.formatHistoryMessages(messages.reverse()); + return this.formatMessages(messages.reverse()); } return []; } @@ -287,35 +277,11 @@ export default abstract class BaseWebChannelHandler< since, n, ); - return this.formatHistoryMessages(messages); + return this.formatMessages(messages); } return []; } - /** - * Verify the received token. - * - * @param verificationToken - Verification Token - */ - private async verifyToken(verificationToken: string) { - const settings = - (await this.getSettings()) as unknown as Settings[typeof WEB_CHANNEL_NAMESPACE]; - const verifyToken = settings.verification_token; - - if (!verifyToken) { - throw new Error('You need to specify a verifyToken in your config.'); - } - if (!verificationToken) { - throw new Error('Did not recieve any verification token.'); - } - if (verificationToken !== verifyToken) { - throw new Error('Make sure the validation tokens match.'); - } - this.logger.log( - 'Web Channel Handler : Token has been verified successfully!', - ); - } - /** * Verify the origin against whitelisted domains. * @@ -405,20 +371,12 @@ export default abstract class BaseWebChannelHandler< * @param req * @param res */ - private async checkRequest( + protected async checkRequest( req: Request | SocketRequest, res: Response | SocketResponse, ) { try { await this.validateCors(req, res); - try { - const { verification_token } = - 'verification_token' in req.query ? req.query : req.body; - await this.verifyToken(verification_token); - } catch (err) { - this.logger.warn('Web Channel Handler : Unable to verify token ', err); - throw new Error('Unauthorized, invalid token!'); - } } catch (err) { this.logger.warn( 'Web Channel Handler : Attempt to access from an unauthorized origin', @@ -741,7 +699,7 @@ export default abstract class BaseWebChannelHandler< * * @returns IP Address */ - private getIpAddress(req: Request | SocketRequest): string { + protected getIpAddress(req: Request | SocketRequest): string { if ('isSocket' in req && req.isSocket) { return req.socket.handshake.address; } else if (Array.isArray(req.ips) && req.ips.length > 0) { diff --git a/api/src/extensions/channels/web/i18n/en/label.json b/api/src/extensions/channels/web/i18n/en/label.json index 3c717b86..b9e4e4f1 100644 --- a/api/src/extensions/channels/web/i18n/en/label.json +++ b/api/src/extensions/channels/web/i18n/en/label.json @@ -1,5 +1,4 @@ { - "verification_token": "Verification Token", "allowed_domains": "Allowed Domains", "start_button": "Enable `Get Started`", "input_disabled": "Disable Input", diff --git a/api/src/extensions/channels/web/i18n/fr/label.json b/api/src/extensions/channels/web/i18n/fr/label.json index 23c3bb70..ce5473a5 100644 --- a/api/src/extensions/channels/web/i18n/fr/label.json +++ b/api/src/extensions/channels/web/i18n/fr/label.json @@ -1,5 +1,4 @@ { - "verification_token": "Jeton de vérification", "allowed_domains": "Domaines autorisés", "start_button": "Activer `Démarrer`", "input_disabled": "Désactiver la saisie", diff --git a/api/src/extensions/channels/web/settings.ts b/api/src/extensions/channels/web/settings.ts index 1011774c..f5382e0f 100644 --- a/api/src/extensions/channels/web/settings.ts +++ b/api/src/extensions/channels/web/settings.ts @@ -16,12 +16,6 @@ export const WEB_CHANNEL_NAME = 'web-channel' as const; export const WEB_CHANNEL_NAMESPACE = 'web_channel'; export default [ - { - group: WEB_CHANNEL_NAMESPACE, - label: Web.SettingLabel.verification_token, - value: 'token123', - type: SettingType.secret, - }, { group: WEB_CHANNEL_NAMESPACE, label: Web.SettingLabel.allowed_domains, diff --git a/api/src/extensions/channels/web/types.ts b/api/src/extensions/channels/web/types.ts index 7442f837..5d475728 100644 --- a/api/src/extensions/channels/web/types.ts +++ b/api/src/extensions/channels/web/types.ts @@ -13,8 +13,6 @@ import { StdQuickReply } from '@/chat/schemas/types/quick-reply'; export namespace Web { export enum SettingLabel { - secret = 'secret', - verification_token = 'verification_token', allowed_domains = 'allowed_domains', start_button = 'start_button', input_disabled = 'input_disabled', diff --git a/api/src/websocket/websocket.gateway.ts b/api/src/websocket/websocket.gateway.ts index 788b5a94..10c7c628 100644 --- a/api/src/websocket/websocket.gateway.ts +++ b/api/src/websocket/websocket.gateway.ts @@ -224,7 +224,7 @@ export class WebsocketGateway 'Unable to load session, creating a new one ...', err, ); - if (searchParams.get('channel') === 'web-channel') { + if (searchParams.get('channel') !== 'console-channel') { return this.createAndStoreSession(client, next); } else { return next(new Error('Unauthorized: Unknown session ID')); diff --git a/docker/.env.example b/docker/.env.example index f9daf1a9..0f529488 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -58,4 +58,3 @@ NEXT_PUBLIC_SSO_ENABLED=false APP_WIDGET_PORT=5173 REACT_APP_WIDGET_API_URL=http://${APP_DOMAIN}:${API_PORT} REACT_APP_WIDGET_CHANNEL=web-channel -REACT_APP_WIDGET_TOKEN=token123 diff --git a/frontend/src/app-components/widget/ChatWidget.tsx b/frontend/src/app-components/widget/ChatWidget.tsx index 4f177184..42dab1b2 100644 --- a/frontend/src/app-components/widget/ChatWidget.tsx +++ b/frontend/src/app-components/widget/ChatWidget.tsx @@ -34,7 +34,6 @@ export const ChatWidget = () => { config={{ apiUrl, channel: "console-channel", - token: "test", language: i18n.language, }} CustomHeader={ChatWidgetHeader} diff --git a/widget/Dockerfile b/widget/Dockerfile index 972df8a6..01e168a2 100644 --- a/widget/Dockerfile +++ b/widget/Dockerfile @@ -7,11 +7,9 @@ COPY package*.json ./ # Set the environment variables ARG REACT_APP_WIDGET_API_URL ARG REACT_APP_WIDGET_CHANNEL -ARG REACT_APP_WIDGET_TOKEN ENV REACT_APP_WIDGET_API_URL=${REACT_APP_WIDGET_API_URL} ENV REACT_APP_WIDGET_CHANNEL=${REACT_APP_WIDGET_CHANNEL} -ENV REACT_APP_WIDGET_TOKEN=${REACT_APP_WIDGET_TOKEN} # Installer stage: Installs dependencies FROM base AS installer diff --git a/widget/src/components/UserSubscription.tsx b/widget/src/components/UserSubscription.tsx index de1c789a..b8bee3db 100644 --- a/widget/src/components/UserSubscription.tsx +++ b/widget/src/components/UserSubscription.tsx @@ -20,7 +20,6 @@ import { useColors } from '../providers/ColorProvider'; import { useConfig } from '../providers/ConfigProvider'; import { useSettings } from '../providers/SettingsProvider'; import { useSocket } from '../providers/SocketProvider'; -import './UserSubscription.scss'; import { useWidget } from '../providers/WidgetProvider'; import { Direction, @@ -28,6 +27,7 @@ import { TMessage, TOutgoingMessageType, } from '../types/message.types'; +import './UserSubscription.scss'; const UserSubscription: React.FC = () => { const config = useConfig(); @@ -55,7 +55,7 @@ const UserSubscription: React.FC = () => { messages: TMessage[]; profile: ISubscriber; }>( - `/webhook/${config.channel}/?verification_token=${config.token}&first_name=${firstName}&last_name=${lastName}`, + `/webhook/${config.channel}/?first_name=${firstName}&last_name=${lastName}`, ); const { messages, profile } = body; diff --git a/widget/src/constants/defaultConfig.ts b/widget/src/constants/defaultConfig.ts index a1711da2..152c2149 100644 --- a/widget/src/constants/defaultConfig.ts +++ b/widget/src/constants/defaultConfig.ts @@ -9,6 +9,5 @@ export const DEFAULT_CONFIG = { apiUrl: process.env.REACT_APP_WIDGET_API_URL || 'http://localhost:4000', channel: process.env.REACT_APP_WIDGET_CHANNEL || 'console-channel', - token: process.env.REACT_APP_WIDGET_TOKEN || 'test', language: 'en', }; diff --git a/widget/src/main.tsx b/widget/src/main.tsx index 82c9e53a..adf9ba47 100644 --- a/widget/src/main.tsx +++ b/widget/src/main.tsx @@ -19,7 +19,6 @@ ReactDOM.createRoot(document.getElementById('root')!).render( {...{ apiUrl: process.env.REACT_APP_WIDGET_API_URL || 'http://localhost:4000', channel: process.env.REACT_APP_WIDGET_CHANNEL || 'web-channel', - token: process.env.REACT_APP_WIDGET_TOKEN || 'token123', language: 'en', }} /> diff --git a/widget/src/providers/ChatProvider.tsx b/widget/src/providers/ChatProvider.tsx index b777eabf..3dd13cbc 100644 --- a/widget/src/providers/ChatProvider.tsx +++ b/widget/src/providers/ChatProvider.tsx @@ -289,7 +289,7 @@ const ChatProvider: React.FC<{ ); setMessage(''); const sentMessage = await socketCtx.socket.post( - `/webhook/${config.channel}/?verification_token=${config.token}`, + `/webhook/${config.channel}/`, { data: { ...data, @@ -308,7 +308,7 @@ const ChatProvider: React.FC<{ messages: TMessage[]; profile: ISubscriber; }>( - `/webhook/${config.channel}/?verification_token=${config.token}&first_name=${firstName}&last_name=${lastName}`, + `/webhook/${config.channel}/?first_name=${firstName}&last_name=${lastName}`, ); localStorage.setItem('profile', JSON.stringify(body.profile)); diff --git a/widget/src/providers/ConfigProvider.tsx b/widget/src/providers/ConfigProvider.tsx index c141c747..eb15c174 100644 --- a/widget/src/providers/ConfigProvider.tsx +++ b/widget/src/providers/ConfigProvider.tsx @@ -13,7 +13,6 @@ import { DEFAULT_CONFIG } from '../constants/defaultConfig'; // Define the type for your config, including all possible properties export type Config = { apiUrl: string; - token: string; channel: string; language: string; }; @@ -23,7 +22,6 @@ const ConfigContext = createContext(DEFAULT_CONFIG); export const ConfigProvider: React.FC<{ apiUrl?: string; - token?: string; channel?: string; language?: string; children: ReactNode; diff --git a/widget/src/providers/SettingsProvider.tsx b/widget/src/providers/SettingsProvider.tsx index f44e71a3..fc8c411c 100644 --- a/widget/src/providers/SettingsProvider.tsx +++ b/widget/src/providers/SettingsProvider.tsx @@ -23,7 +23,6 @@ import { useSubscribe } from './SocketProvider'; type ChannelSettings = { menu: IMenuNode[]; secret: string; - verification_token: string; allowed_domains: string; start_button: boolean; input_disabled: boolean; diff --git a/widget/src/utils/SocketIoClient.ts b/widget/src/utils/SocketIoClient.ts index a90859a3..9b5e2150 100644 --- a/widget/src/utils/SocketIoClient.ts +++ b/widget/src/utils/SocketIoClient.ts @@ -6,7 +6,7 @@ * 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file). */ -import { io, Socket, ManagerOptions, SocketOptions } from 'socket.io-client'; +import { io, ManagerOptions, Socket, SocketOptions } from 'socket.io-client'; import { Config } from '../providers/ConfigProvider'; import { @@ -195,14 +195,16 @@ let socketIoClient: SocketIoClient; * @param handlers Event handlers * @returns Socket io client instance */ -export const getSocketIoClient = (config: Config, handlers: SocketIoEventHandlers) => { +export const getSocketIoClient = ( + config: Config, + handlers: SocketIoEventHandlers, +) => { if (!socketIoClient) { socketIoClient = new SocketIoClient( config.apiUrl, { query: { channel: config.channel, - verification_token: config.token, }, }, handlers,