From 39fa6dd2b093e3e4e878d0f23b27a3ae68b53c71 Mon Sep 17 00:00:00 2001 From: Zhipeng Wang Date: Fri, 16 Oct 2020 14:47:54 +0800 Subject: [PATCH 1/4] validate and pass userid to directline channel api --- src/directLine.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/directLine.ts b/src/directLine.ts index 5545ab1c1..cbbdc781d 100644 --- a/src/directLine.ts +++ b/src/directLine.ts @@ -9,6 +9,7 @@ import { IScheduler } from 'rxjs/Scheduler'; import { Subscriber } from 'rxjs/Subscriber'; import { Subscription } from 'rxjs/Subscription'; import { async as AsyncScheduler } from 'rxjs/scheduler/async'; +import { decode } from 'jsonwebtoken'; import 'rxjs/add/operator/catch'; import 'rxjs/add/operator/combineLatest'; @@ -471,6 +472,7 @@ export class DirectLine implements IBotConnection { private retries: number; private localeOnStartConversation: string; + private userIdOnStartConversation: string; private pollingInterval: number = 1000; //ms @@ -630,6 +632,9 @@ export class DirectLine implements IBotConnection { const body = this.conversationId ? undefined : { + user: { + id: this.userIdOnStartConversation + }, locale: this.localeOnStartConversation }; return this.services.ajax({ @@ -749,6 +754,11 @@ export class DirectLine implements IBotConnection { } postActivity(activity: Activity) { + // If user id is set, check if it match activity.from.id and always override it in activity + if (this.userIdOnStartConversation && activity.from && activity.from.id != this.userIdOnStartConversation) { + console.warn('DirectLineJS: Activity.from.id does not match with user id, ignoring activity.from.id'); + activity.from.id = this.userIdOnStartConversation; + } // Use postMessageWithAttachments for messages with attachments that are local files (e.g. an image to upload) // Technically we could use it for *all* activities, but postActivity is much lighter weight // So, since WebChat is partially a reference implementation of Direct Line, we implement both. @@ -1017,5 +1027,21 @@ export class DirectLine implements IBotConnection { return `${DIRECT_LINE_VERSION} (${clientAgent} ${process.env.npm_package_version})`; } + setUserId(userId: string) { + if (this.connectionStatus$.getValue() === ConnectionStatus.Online) { + throw new Error('DirectLineJS: It is connected, we cannot set user id.'); + } + + const { user: userIDFromToken } = decode(this.token) || {}; + if (userIDFromToken) { + return console.warn('DirectLineJS: user id is already set in token, will ignore this user id.'); + } + + if (/^dl_/u.test(userId)) { + return console.warn('DirectLineJS: user id prefixed with "dl_" is reserved and must be embedded into the Direct Line token to prevent forgery.'); + } + + this.userIdOnStartConversation = userId; + } } From e690b715e2cce68458b5a7a367698c097c5b2912 Mon Sep 17 00:00:00 2001 From: Zhipeng Wang Date: Tue, 20 Oct 2020 14:29:21 +0800 Subject: [PATCH 2/4] Add test case and required dependency --- __tests__/happy.userIdOnStartConversation.js | 45 ++++++++ package-lock.json | 108 ++++++++++++++++++- package.json | 2 + src/directLine.ts | 2 +- 4 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 __tests__/happy.userIdOnStartConversation.js diff --git a/__tests__/happy.userIdOnStartConversation.js b/__tests__/happy.userIdOnStartConversation.js new file mode 100644 index 000000000..2d37b2b7b --- /dev/null +++ b/__tests__/happy.userIdOnStartConversation.js @@ -0,0 +1,45 @@ +import 'dotenv/config'; + +import onErrorResumeNext from 'on-error-resume-next'; + +import { timeouts } from './constants.json'; +import * as createDirectLine from './setup/createDirectLine'; +import waitForBotToRespond from './setup/waitForBotToRespond'; + +describe('Happy path', () => { + let unsubscribes; + + beforeEach(() => unsubscribes = []); + afterEach(() => unsubscribes.forEach(fn => onErrorResumeNext(fn))); + + describe('should receive the welcome message from bot', () => { + let directLine; + + describe('using REST', () => { + beforeEach(() => jest.setTimeout(timeouts.rest)); + + test('with secret', async () => { + directLine = await createDirectLine.forREST({ token: false }); + }); + }); + + describe('using Web Socket', () => { + beforeEach(() => jest.setTimeout(timeouts.webSocket)); + + test('with secret', async () => { + directLine = await createDirectLine.forREST({ token: false }); + }); + }); + + afterEach(async () => { + // If directLine object is undefined, that means the test is failing. + if (!directLine) { return; } + + unsubscribes.push(directLine.end.bind(directLine)); + + directLine.setUserId('u_test'); + + await waitForBotToRespond(directLine, ({ text }) => text === 'Welcome'); + }); + }); +}); diff --git a/package-lock.json b/package-lock.json index 57b9797cf..393db87bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2158,6 +2158,15 @@ "integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==", "dev": true }, + "@types/jsonwebtoken": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.0.tgz", + "integrity": "sha512-9bVao7LvyorRGZCw0VmH/dr7Og+NdjYSsKAxB43OQoComFbBgsEpoR9JW6+qSq/ogwVBg8GI2MfAlk4SYI4OLg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/node": { "version": "12.7.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.4.tgz", @@ -3144,6 +3153,11 @@ "isarray": "^1.0.0" } }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -4044,6 +4058,14 @@ "safer-buffer": "^2.1.0" } }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -7041,6 +7063,35 @@ "minimist": "^1.2.0" } }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -7089,6 +7140,25 @@ } } }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -7177,6 +7247,41 @@ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -8771,8 +8876,7 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, "safe-json-stringify": { "version": "1.2.0", diff --git a/package.json b/package.json index 316176b33..3864b79db 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "botframework-streaming": "4.10.3", "core-js": "3.6.4", "cross-fetch": "3.0.4", + "jsonwebtoken": "8.5.1", "rxjs": "5.5.10", "url-search-params-polyfill": "8.0.0" }, @@ -42,6 +43,7 @@ "@babel/preset-env": "^7.6.0", "@babel/preset-typescript": "^7.6.0", "@types/jest": "^24.0.18", + "@types/jsonwebtoken": "^8.5.0", "@types/node": "^12.7.4", "@types/p-defer": "^2.0.0", "babel-jest": "^24.9.0", diff --git a/src/directLine.ts b/src/directLine.ts index cbbdc781d..e4a9a4fb0 100644 --- a/src/directLine.ts +++ b/src/directLine.ts @@ -1032,7 +1032,7 @@ export class DirectLine implements IBotConnection { throw new Error('DirectLineJS: It is connected, we cannot set user id.'); } - const { user: userIDFromToken } = decode(this.token) || {}; + const { user: userIDFromToken } = decode(this.token) as { [key: string]: any; } || {}; if (userIDFromToken) { return console.warn('DirectLineJS: user id is already set in token, will ignore this user id.'); } From 630ebc4aaaced124babca11c33c81929a4594e35 Mon Sep 17 00:00:00 2001 From: Zhipeng Wang Date: Wed, 13 Jan 2021 12:34:43 +0800 Subject: [PATCH 3/4] fixed comments and added tests --- __tests__/happy.replaceActivityFromId.js | 49 ++++++++++++++ __tests__/happy.userIdOnStartConversation.js | 2 +- __tests__/unhappy.setUserIdAfterConnect.js | 44 +++++++++++++ package-lock.json | 67 ++------------------ package.json | 2 +- src/directLine.ts | 19 ++++-- 6 files changed, 116 insertions(+), 67 deletions(-) create mode 100644 __tests__/happy.replaceActivityFromId.js create mode 100644 __tests__/unhappy.setUserIdAfterConnect.js diff --git a/__tests__/happy.replaceActivityFromId.js b/__tests__/happy.replaceActivityFromId.js new file mode 100644 index 000000000..cd1bb0e44 --- /dev/null +++ b/__tests__/happy.replaceActivityFromId.js @@ -0,0 +1,49 @@ +import 'dotenv/config'; + +import onErrorResumeNext from 'on-error-resume-next'; + +import { timeouts } from './constants.json'; +import * as createDirectLine from './setup/createDirectLine'; +import postActivity from './setup/postActivity'; +import waitForBotToRespond from './setup/waitForBotToRespond'; + +describe('Happy path', () => { + let unsubscribes; + + beforeEach(() => unsubscribes = []); + afterEach(() => unsubscribes.forEach(fn => onErrorResumeNext(fn))); + + describe('should receive the welcome message from bot', () => { + let directLine; + + describe('using REST', () => { + beforeEach(() => jest.setTimeout(timeouts.rest)); + + test('with secret', async () => { + directLine = await createDirectLine.forREST({ token: false }); + }); + }); + + describe('using Web Socket', () => { + beforeEach(() => jest.setTimeout(timeouts.webSocket)); + + test('with secret', async () => { + directLine = await createDirectLine.forWebSocket({ token: false }); + }); + }); + + afterEach(async () => { + // If directLine object is undefined, that means the test is failing. + if (!directLine) { return; } + + unsubscribes.push(directLine.end.bind(directLine)); + + directLine.setUserId('u_test'); + + await Promise.all([ + postActivity(directLine, { text: 'Hello, World!', type: 'message' }), + waitForBotToRespond(directLine, ({ from }) => from.id === 'u_test') + ]); + }); + }); +}); diff --git a/__tests__/happy.userIdOnStartConversation.js b/__tests__/happy.userIdOnStartConversation.js index 2d37b2b7b..ba19e709d 100644 --- a/__tests__/happy.userIdOnStartConversation.js +++ b/__tests__/happy.userIdOnStartConversation.js @@ -27,7 +27,7 @@ describe('Happy path', () => { beforeEach(() => jest.setTimeout(timeouts.webSocket)); test('with secret', async () => { - directLine = await createDirectLine.forREST({ token: false }); + directLine = await createDirectLine.forWebSocket({ token: false }); }); }); diff --git a/__tests__/unhappy.setUserIdAfterConnect.js b/__tests__/unhappy.setUserIdAfterConnect.js new file mode 100644 index 000000000..b795e1b28 --- /dev/null +++ b/__tests__/unhappy.setUserIdAfterConnect.js @@ -0,0 +1,44 @@ +import 'dotenv/config'; + +import onErrorResumeNext from 'on-error-resume-next'; + +import { timeouts } from './constants.json'; +import * as createDirectLine from './setup/createDirectLine'; +import waitForConnected from './setup/waitForConnected'; + +describe('Unhappy path', () => { + let unsubscribes; + + beforeEach(() => unsubscribes = []); + afterEach(() => unsubscribes.forEach(fn => onErrorResumeNext(fn))); + + describe('should receive the welcome message from bot', () => { + let directLine; + + describe('using REST', () => { + beforeEach(() => jest.setTimeout(timeouts.rest)); + + test('with secret', async () => { + directLine = await createDirectLine.forREST({ token: false }); + }); + }); + + describe('using Web Socket', () => { + beforeEach(() => jest.setTimeout(timeouts.webSocket)); + + test('with secret', async () => { + directLine = await createDirectLine.forWebSocket({ token: false }); + }); + }); + + afterEach(async () => { + // If directLine object is undefined, that means the test is failing. + if (!directLine) { return; } + + unsubscribes.push(directLine.end.bind(directLine)); + unsubscribes.push(await waitForConnected(directLine)); + + expect(() => directLine.setUserId('e_test')).toThrowError('DirectLineJS: It is connected, we cannot set user id.'); + }); + }); +}); diff --git a/package-lock.json b/package-lock.json index 43a862409..a54d4d0a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3153,11 +3153,6 @@ "isarray": "^1.0.0" } }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" - }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -4058,14 +4053,6 @@ "safer-buffer": "^2.1.0" } }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -7069,35 +7056,6 @@ "minimist": "^1.2.0" } }, - "jsonwebtoken": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", - "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", - "requires": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^5.6.0" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -7146,24 +7104,10 @@ } } }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } + "jwt-decode": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", + "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" }, "kind-of": { "version": "6.0.3", @@ -8888,7 +8832,8 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true }, "safe-json-stringify": { "version": "1.2.0", diff --git a/package.json b/package.json index 69a05044b..63a91413c 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "botframework-streaming": "4.10.3", "core-js": "3.6.4", "cross-fetch": "3.0.4", - "jsonwebtoken": "8.5.1", + "jwt-decode": "3.1.2", "rxjs": "5.5.10", "url-search-params-polyfill": "8.0.0" }, diff --git a/src/directLine.ts b/src/directLine.ts index 911043760..4831e7da4 100644 --- a/src/directLine.ts +++ b/src/directLine.ts @@ -9,7 +9,7 @@ import { IScheduler } from 'rxjs/Scheduler'; import { Subscriber } from 'rxjs/Subscriber'; import { Subscription } from 'rxjs/Subscription'; import { async as AsyncScheduler } from 'rxjs/scheduler/async'; -import { decode } from 'jsonwebtoken'; +import jwtDecode, { JwtPayload, InvalidTokenError } from "jwt-decode"; import 'rxjs/add/operator/catch'; import 'rxjs/add/operator/combineLatest'; @@ -755,7 +755,7 @@ export class DirectLine implements IBotConnection { postActivity(activity: Activity) { // If user id is set, check if it match activity.from.id and always override it in activity - if (this.userIdOnStartConversation && activity.from && activity.from.id != this.userIdOnStartConversation) { + if (this.userIdOnStartConversation && activity.from && activity.from.id !== this.userIdOnStartConversation) { console.warn('DirectLineJS: Activity.from.id does not match with user id, ignoring activity.from.id'); activity.from.id = this.userIdOnStartConversation; } @@ -1047,8 +1047,8 @@ export class DirectLine implements IBotConnection { throw new Error('DirectLineJS: It is connected, we cannot set user id.'); } - const { user: userIDFromToken } = decode(this.token) as { [key: string]: any; } || {}; - if (userIDFromToken) { + const userIdFromToken = this.parseToken(this.token); + if (userIdFromToken) { return console.warn('DirectLineJS: user id is already set in token, will ignore this user id.'); } @@ -1059,4 +1059,15 @@ export class DirectLine implements IBotConnection { this.userIdOnStartConversation = userId; } + private parseToken(token: string) { + try { + const { user } = jwtDecode(token) as { [key: string]: any; }; + return user; + } catch (e) { + if (e instanceof InvalidTokenError) { + return undefined; + } + } + } + } From 62803757a43b66da92eb11441263b715fa5e005f Mon Sep 17 00:00:00 2001 From: William Wong Date: Thu, 4 Feb 2021 12:32:25 -0800 Subject: [PATCH 4/4] Update directLine.ts --- src/directLine.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/directLine.ts b/src/directLine.ts index 4831e7da4..7cc1b15fc 100644 --- a/src/directLine.ts +++ b/src/directLine.ts @@ -9,7 +9,7 @@ import { IScheduler } from 'rxjs/Scheduler'; import { Subscriber } from 'rxjs/Subscriber'; import { Subscription } from 'rxjs/Subscription'; import { async as AsyncScheduler } from 'rxjs/scheduler/async'; -import jwtDecode, { JwtPayload, InvalidTokenError } from "jwt-decode"; +import jwtDecode, { JwtPayload, InvalidTokenError } from 'jwt-decode'; import 'rxjs/add/operator/catch'; import 'rxjs/add/operator/combineLatest';