Skip to content
This repository was archived by the owner on Jan 5, 2026. It is now read-only.

Commit 14fb6b5

Browse files
authored
Support CloudAdapter and ExpectReplies in SSO (#4766)
1 parent cd6cf6f commit 14fb6b5

1 file changed

Lines changed: 33 additions & 32 deletions

File tree

libraries/botbuilder-dialogs/src/skillDialog.ts

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import {
1414
ConversationReference,
1515
DeliveryModes,
1616
ExpectedReplies,
17-
ExtendedUserTokenProvider,
1817
OAuthCard,
1918
SkillConversationIdFactoryOptions,
2019
StatusCodes,
@@ -30,6 +29,7 @@ import { DialogContext } from './dialogContext';
3029
import { DialogEvents } from './dialogEvents';
3130
import { SkillDialogOptions } from './skillDialogOptions';
3231
import { TurnPath } from './memory/turnPath';
32+
import * as UserTokenAccess from './prompts/userTokenAccess';
3333

3434
/**
3535
* A specialized Dialog that can wrap remote calls to a skill.
@@ -333,45 +333,46 @@ export class SkillDialog extends Dialog<Partial<BeginSkillDialogOptions>> {
333333
activity: Activity,
334334
connectionName: string
335335
): Promise<boolean> {
336-
if (!connectionName || !('exchangeToken' in context.adapter)) {
337-
// The adapter may choose not to support token exchange, in which case we fallback to showing skill's OAuthCard to the user.
336+
if (!connectionName) {
338337
return false;
339338
}
340339

341340
const oAuthCardAttachment: Attachment = (activity.attachments || []).find(
342341
(c) => c.contentType === CardFactory.contentTypes.oauthCard
343342
);
344-
if (oAuthCardAttachment) {
345-
const tokenExchangeProvider: ExtendedUserTokenProvider = (context.adapter as unknown) as ExtendedUserTokenProvider;
346-
const oAuthCard: OAuthCard = oAuthCardAttachment.content;
347-
348-
const uri = oAuthCard && oAuthCard.tokenExchangeResource && oAuthCard.tokenExchangeResource.uri;
349-
if (uri) {
350-
try {
351-
const result: TokenResponse = await tokenExchangeProvider.exchangeToken(
352-
context,
353-
connectionName,
354-
context.activity.from.id,
355-
{ uri }
356-
);
357-
358-
if (result && result.token) {
359-
// If token above is null or undefined, then SSO has failed and we return false.
360-
// If not, send an invoke to the skill with the token.
361-
return await this.sendTokenExchangeInvokeToSkill(
362-
activity,
363-
oAuthCard.tokenExchangeResource.id,
364-
oAuthCard.connectionName,
365-
result.token
366-
);
367-
}
368-
} catch {
369-
// Failures in token exchange are not fatal. They simply mean that the user needs to be shown the skill's OAuthCard.
370-
return false;
371-
}
343+
if (!oAuthCardAttachment) {
344+
return false;
345+
}
346+
347+
const oAuthCard: OAuthCard = oAuthCardAttachment.content;
348+
const uri = oAuthCard && oAuthCard.tokenExchangeResource && oAuthCard.tokenExchangeResource.uri;
349+
350+
if (!uri) {
351+
return false;
352+
}
353+
354+
try {
355+
const result: TokenResponse = await UserTokenAccess.exchangeToken(
356+
context,
357+
{ title: 'Sign In', connectionName: connectionName },
358+
{ uri }
359+
);
360+
361+
if (!result || !result.token) {
362+
// If token above is null or undefined, then SSO has failed and we return false.
363+
return false;
372364
}
365+
// If not, send an invoke to the skill with the token.
366+
return await this.sendTokenExchangeInvokeToSkill(
367+
activity,
368+
oAuthCard.tokenExchangeResource.id,
369+
oAuthCard.connectionName,
370+
result.token
371+
);
372+
} catch {
373+
// Failures in token exchange are not fatal. They simply mean that the user needs to be shown the skill's OAuthCard.
374+
return false;
373375
}
374-
return false;
375376
}
376377

377378
/**

0 commit comments

Comments
 (0)