Skip to content

Commit c5937fc

Browse files
authored
Fixed a bug where OAuth cards were opening the file explorer if ngrok… (#2155)
* Fixed a bug where OAuth cards were opening the file explorer if ngrok was not configured. * Lint fixes. * Fixed test.
1 parent a5be796 commit c5937fc

File tree

9 files changed

+32
-158
lines changed

9 files changed

+32
-158
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111
## Fixed
1212
- [client] Added missing content to signed in view of Cosmos DB service dialog and fixed product page link in PR [2150](https://github.com/microsoft/BotFramework-Emulator/pull/2150)
1313
- [docs] Modified CONTRIBUTING.md to include updated information about global dependencies required to build from source in PR [2153](https://github.com/microsoft/BotFramework-Emulator/pull/2153)
14+
- [client] Fixed a bug where trying to open the sign-in link on an OAuth card would open the file explorer if ngrok was not configured in PR [2155](https://github.com/microsoft/BotFramework-Emulator/pull/2155)
1415

1516
## v4.9.0 - 2020 - 05 - 11
1617
## Added

packages/app/client/src/hyperlinkHandler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ export class HyperlinkHandler {
4747
const { TrackEvent } = SharedConstants.Commands.Telemetry;
4848
try {
4949
const parsed = URL.parse(url) || { protocol: '' };
50-
if ((parsed.protocol || '').startsWith('oauth:')) {
50+
if ((parsed.protocol || '').startsWith(SharedConstants.EmulatedOAuthUrlProtocol)) {
5151
this.navigateEmulatedOAuthUrl(url.substring(8));
52-
} else if (parsed.protocol.startsWith('oauthlink:')) {
52+
} else if (parsed.protocol.startsWith(SharedConstants.OAuthUrlProtocol)) {
5353
this.navigateOAuthUrl(url.substring(12));
5454
} else {
5555
this.commandService.remoteCall(TrackEvent, 'app_openLink', { url }).catch(_e => void 0);

packages/app/main/src/server/routes/channel/userToken/handlers/emulateOAuthCards.spec.ts

Lines changed: 0 additions & 79 deletions
This file was deleted.

packages/app/main/src/server/routes/channel/userToken/handlers/emulateOAuthCards.ts

Lines changed: 0 additions & 55 deletions
This file was deleted.

packages/app/main/src/server/routes/channel/userToken/mountUserTokenRoutes.spec.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import { createBotFrameworkAuthenticationMiddleware } from '../../handlers/botFr
3636
import { createJsonBodyParserMiddleware } from '../../../utils/jsonBodyParser';
3737

3838
import { mountUserTokenRoutes } from './mountUserTokenRoutes';
39-
import { emulateOAuthCards } from './handlers/emulateOAuthCards';
4039
import { getToken } from './handlers/getToken';
4140
import { signOut } from './handlers/signOut';
4241
import { createTokenResponseHandler } from './handlers/tokenResponse';
@@ -77,12 +76,6 @@ describe('mountUserTokenRoutes', () => {
7776
getToken
7877
);
7978

80-
expect(emulatorServer.server.post).toHaveBeenCalledWith(
81-
'/api/usertoken/emulateOAuthCards',
82-
botFrameworkAuthentication,
83-
emulateOAuthCards
84-
);
85-
8679
expect(emulatorServer.server.del).toHaveBeenCalledWith(
8780
'/api/usertoken/SignOut',
8881
botFrameworkAuthentication,

packages/app/main/src/server/routes/channel/userToken/mountUserTokenRoutes.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import { createBotFrameworkAuthenticationMiddleware } from '../../handlers/botFr
3636
import { createJsonBodyParserMiddleware } from '../../../utils/jsonBodyParser';
3737
import { EmulatorRestServer } from '../../../restServer';
3838

39-
import { emulateOAuthCards } from './handlers/emulateOAuthCards';
4039
import { getToken } from './handlers/getToken';
4140
import { signOut } from './handlers/signOut';
4241
import { createTokenResponseHandler } from './handlers/tokenResponse';
@@ -49,8 +48,6 @@ export function mountUserTokenRoutes(emulatorServer: EmulatorRestServer) {
4948

5049
server.get('/api/usertoken/GetToken', botFrameworkAuthentication, getBotEndpoint, getToken);
5150

52-
server.post('/api/usertoken/emulateOAuthCards', botFrameworkAuthentication, emulateOAuthCards);
53-
5451
server.del('/api/usertoken/SignOut', botFrameworkAuthentication, getBotEndpoint, signOut);
5552

5653
server.post('/api/usertoken/tokenResponse', jsonBodyParser, createTokenResponseHandler(emulatorServer));

packages/app/main/src/server/utils/oauthLinkEncoder.spec.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
//
3333

3434
import { AttachmentContentTypes } from '@bfemulator/sdk-shared';
35+
import { SharedConstants } from '@bfemulator/app-shared';
3536

3637
import { OAuthLinkEncoder } from './oauthLinkEncoder';
3738

@@ -111,15 +112,16 @@ describe('The OauthLinkEncoder', () => {
111112
});
112113
});
113114

114-
it('should throw when an error occurs retrieving the link while calling resolveOAuthCards', async () => {
115+
it('should throw when an error occurs retrieving the link while calling resolveOAuthCards, but should also generate an emulated oauth link', async () => {
115116
ok = false;
116117
statusText = 'oh noes!';
117118
const mockActivity = {
118119
attachments: [
119120
{
120121
contentType: AttachmentContentTypes.oAuthCard,
121122
content: {
122-
buttons: [{ type: 'signin' }],
123+
buttons: [{ type: 'signin', value: undefined }],
124+
connectionName: 'oauth-connection',
123125
},
124126
},
125127
],
@@ -129,7 +131,11 @@ describe('The OauthLinkEncoder', () => {
129131
await encoder.resolveOAuthCards(mockActivity);
130132
expect(false);
131133
} catch (e) {
132-
expect(e.message).toEqual(statusText);
134+
expect(e.message).toEqual(`Failed to generate an actual sign-in link: Error: ${statusText}`);
135+
expect(mockActivity.attachments[0].content.buttons[0].type).toBe('openUrl');
136+
expect(mockActivity.attachments[0].content.buttons[0].value).toBe(
137+
SharedConstants.EmulatedOAuthUrlProtocol + '//' + 'oauth-connection' + '&&&' + 'testConversation'
138+
);
133139
}
134140
});
135141

@@ -150,7 +156,7 @@ describe('The OauthLinkEncoder', () => {
150156
await encoder.resolveOAuthCards(mockActivity);
151157
expect(false);
152158
} catch (e) {
153-
expect(e.message).toEqual("I'm in your throw!");
159+
expect(e.message).toEqual(`Failed to generate an actual sign-in link: Error: ${"I'm in your throw!"}`);
154160
}
155161
});
156162

packages/app/main/src/server/utils/oauthLinkEncoder.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import * as crypto from 'crypto';
3535

3636
import { Attachment, OAuthCard } from 'botframework-schema';
37+
import { SharedConstants } from '@bfemulator/app-shared';
3738
import { AttachmentContentTypes } from '@bfemulator/sdk-shared';
3839
import { Activity } from 'botframework-schema';
3940

@@ -42,9 +43,6 @@ import { EmulatorRestServer } from '../restServer';
4243
import { uniqueId } from './uniqueId';
4344

4445
export class OAuthLinkEncoder {
45-
public static OAuthUrlProtocol: string = 'oauthlink:';
46-
public static EmulateOAuthCards: boolean = false;
47-
4846
private readonly authorizationHeader: string;
4947
private readonly conversationId: string;
5048
private activity: Activity;
@@ -75,10 +73,21 @@ export class OAuthLinkEncoder {
7573
const oauthCard: OAuthCard = attachment.content as OAuthCard;
7674
if (oauthCard.buttons && oauthCard.buttons.length === 1) {
7775
const cardAction = oauthCard.buttons[0];
78-
if (cardAction.type === 'signin' && !cardAction.value && !OAuthLinkEncoder.EmulateOAuthCards) {
79-
const link = await this.getSignInLink(oauthCard.connectionName, codeChallenge);
80-
cardAction.value = link;
81-
cardAction.type = 'openUrl';
76+
if (cardAction.type === 'signin' && !cardAction.value) {
77+
// generate a sign-in link for the oauth card and assign it to the button
78+
try {
79+
const link = await this.getSignInLink(oauthCard.connectionName, codeChallenge);
80+
cardAction.value = link;
81+
cardAction.type = 'openUrl';
82+
} catch (e) {
83+
// failed to generate a sign-in link, fall back to an emulated sign-in token
84+
const link =
85+
SharedConstants.EmulatedOAuthUrlProtocol + '//' + oauthCard.connectionName + '&&&' + this.conversationId;
86+
cardAction.value = link;
87+
cardAction.type = 'openUrl';
88+
89+
throw new Error(`Failed to generate an actual sign-in link: ${e}`);
90+
}
8291
}
8392
}
8493
}
@@ -134,7 +143,7 @@ export class OAuthLinkEncoder {
134143
});
135144
if (response.ok) {
136145
const link = await response.text();
137-
return OAuthLinkEncoder.OAuthUrlProtocol + '//' + link + '&&&' + this.conversationId;
146+
return SharedConstants.OAuthUrlProtocol + '//' + link + '&&&' + this.conversationId;
138147
}
139148
errorMessage = response.statusText;
140149
} catch (e) {

packages/app/shared/src/constants/sharedConstants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ export const SharedConstants = {
3939
TEMP_BOT_IN_MEMORY_PATH: 'TEMP_BOT_IN_MEMORY',
4040
EDITOR_KEY_PRIMARY,
4141
EDITOR_KEY_SECONDARY,
42+
EmulatedOAuthUrlProtocol: 'oauth:',
43+
OAuthUrlProtocol: 'oauthlink:',
4244

4345
/** Names of commands used in both main and client */
4446
Commands: {

0 commit comments

Comments
 (0)