Skip to content

Commit 05fd0e0

Browse files
added getSignInLink overload (#1803)
* migrate .net change in for adding oauth app credentials as a parameter * rename variable * change turn state key name * fix use ternary operator * use CredentialTokenProvider interface that extends UserTokenProvider interface * remove unused comments * correct the credentialTokenProvider interface path * fix import * fix the dependency chain * fix parameter name * fix comments * fix tests * fix token resolve test * fix test * added getSignInLink overload * - Merge branch 'master' into oauthOverloads - dropped unnecessary overloads - added param docstrings * remove accidental merge file Co-authored-by: Ted <tedlee@microsoft.com>
1 parent 8ab5676 commit 05fd0e0

File tree

2 files changed

+100
-4
lines changed

2 files changed

+100
-4
lines changed

libraries/botbuilder/src/botFrameworkAdapter.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -581,10 +581,14 @@ export class BotFrameworkAdapter extends BotAdapter implements CredentialTokenPr
581581
* @param context The context object for the turn.
582582
* @param connectionName The name of the auth connection to use.
583583
* @param oAuthAppCredentials AppCredentials for OAuth.
584+
* @param userId The user id that will be associated with the token.
585+
* @param finalRedirect The final URL that the OAuth flow will redirect to.
584586
*/
585-
public async getSignInLink(context: TurnContext, connectionName: string): Promise<string>;
586-
public async getSignInLink(context: TurnContext, connectionName: string, oAuthAppCredentials?: AppCredentials): Promise<string>;
587-
public async getSignInLink(context: TurnContext, connectionName: string, oAuthAppCredentials?: AppCredentials): Promise<string> {
587+
public async getSignInLink(context: TurnContext, connectionName: string, oAuthAppCredentials?: AppCredentials, userId?: string, finalRedirect?: string): Promise<string> {
588+
if (userId && userId != context.activity.from.id) {
589+
throw new ReferenceError(`cannot retrieve OAuth signin link for a user that's different from the conversation`);
590+
}
591+
588592
this.checkEmulatingOAuthCards(context);
589593
const conversation: Partial<ConversationReference> = TurnContext.getConversationReference(context.activity);
590594
const url: string = this.oauthApiUrl(context);
@@ -597,7 +601,7 @@ export class BotFrameworkAdapter extends BotAdapter implements CredentialTokenPr
597601
};
598602

599603
const finalState: string = Buffer.from(JSON.stringify(state)).toString('base64');
600-
return (await client.botSignIn.getSignInUrl(finalState, { channelId: context.activity.channelId }))._response.bodyAsText;
604+
return (await client.botSignIn.getSignInUrl(finalState, { channelId: context.activity.channelId, finalRedirect }))._response.bodyAsText;
601605
}
602606

603607
/**

libraries/botbuilder/tests/botFrameworkAdapter.test.js

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,98 @@ describe(`BotFrameworkAdapter`, function () {
10241024
assert(false, `should have thrown an error message`);
10251025
});
10261026

1027+
describe('getSignInLink()', () => {
1028+
it(`should throw if userName != from.id`, async () => {
1029+
const adapter = new BotFrameworkAdapter();
1030+
const context = new TurnContext(adapter, incomingMessage);
1031+
try {
1032+
const response = await adapter.getSignInLink(context, 'aConnectionName', new MicrosoftAppCredentials('abc', 'abc'), 'invalidId');
1033+
} catch (err) {
1034+
assert(err.message === `cannot retrieve OAuth signin link for a user that's different from the conversation`);
1035+
return;
1036+
}
1037+
assert(false, `should have thrown an error message`);
1038+
});
1039+
it(`should return return a sign-in URL with context and connectionName`, async () => {
1040+
const argsPassedToMockClient = [];
1041+
class MockTokenApiClient {
1042+
constructor() {
1043+
this.botSignIn = {
1044+
getSignInUrl: async (...args) => {
1045+
argsPassedToMockClient.push({getSignInUrl: args});
1046+
return {
1047+
_response: {status: 200, bodyAsText: 'http://mockedurl.com' }
1048+
}
1049+
}
1050+
};
1051+
this.credentials = new MicrosoftAppCredentials('abc', 'abc');
1052+
}
1053+
1054+
}
1055+
const {TokenApiClient} = connector;
1056+
connector.TokenApiClient = MockTokenApiClient;
1057+
1058+
const adapter = new BotFrameworkAdapter();
1059+
const context = new TurnContext(adapter, incomingMessage);
1060+
const response = await adapter.getSignInLink(context, 'aConnectionName');
1061+
assert(response, 'http://mockedurl.com');
1062+
1063+
connector.TokenApiClient = TokenApiClient; // restore
1064+
});
1065+
it(`should return return a sign-in URL with context connectionName, oauthAppCredentials`, async () => {
1066+
const argsPassedToMockClient = [];
1067+
class MockTokenApiClient {
1068+
constructor() {
1069+
this.botSignIn = {
1070+
getSignInUrl: async (...args) => {
1071+
argsPassedToMockClient.push({getSignInUrl: args});
1072+
return {
1073+
_response: {status: 200, bodyAsText: 'http://mockedurl.com' }
1074+
}
1075+
}
1076+
};
1077+
this.credentials = new MicrosoftAppCredentials('abc', 'abc');
1078+
}
1079+
1080+
}
1081+
const {TokenApiClient} = connector;
1082+
connector.TokenApiClient = MockTokenApiClient;
1083+
1084+
const adapter = new BotFrameworkAdapter();
1085+
const context = new TurnContext(adapter, incomingMessage);
1086+
const response = await adapter.getSignInLink(context, 'aConnectionName', new MicrosoftAppCredentials('abc', 'abc'));
1087+
assert(response, 'http://mockedurl.com');
1088+
1089+
connector.TokenApiClient = TokenApiClient; // restore
1090+
});
1091+
it(`should return return a sign-in URL with context connectionName, oauthAppCredentials, userId, finalRedirect`, async () => {
1092+
const argsPassedToMockClient = [];
1093+
class MockTokenApiClient {
1094+
constructor() {
1095+
this.botSignIn = {
1096+
getSignInUrl: async (...args) => {
1097+
argsPassedToMockClient.push({getSignInUrl: args});
1098+
return {
1099+
_response: {status: 200, bodyAsText: 'http://mockedurl.com' }
1100+
}
1101+
}
1102+
};
1103+
this.credentials = new MicrosoftAppCredentials('abc', 'abc');
1104+
}
1105+
1106+
}
1107+
const {TokenApiClient} = connector;
1108+
connector.TokenApiClient = MockTokenApiClient;
1109+
1110+
const adapter = new BotFrameworkAdapter();
1111+
const context = new TurnContext(adapter, incomingMessage);
1112+
const response = await adapter.getSignInLink(context, 'aConnectionName', new MicrosoftAppCredentials('abc', 'abc'), incomingMessage.from.id, 'http://finalredirect.com');
1113+
assert(response, 'http://mockedurl.com');
1114+
1115+
connector.TokenApiClient = TokenApiClient; // restore
1116+
});
1117+
});
1118+
10271119
describe('getTokenStatus()', () => {
10281120
xit(`should return the status of every connection the user has`, async () => {
10291121
const adapter = new AdapterUnderTest();

0 commit comments

Comments
 (0)