Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSO Implementation #12559

Open
arundhathiMenon opened this issue Oct 21, 2024 · 5 comments
Open

SSO Implementation #12559

arundhathiMenon opened this issue Oct 21, 2024 · 5 comments
Assignees
Labels

Comments

@arundhathiMenon
Copy link

can you please guide me on this,

I have two accounts: [email protected] and [email protected]. On Azure, I have a subscription under the one.ai tenant, where I’ve registered both an app and a bot. However, I have a SharePoint license and a Microsoft Teams account associated with the [email protected] account.

Currently, I’m implementing SSO (Single Sign-On) to authorize users when they log in to Microsoft Teams, but I am using the app registration credentials (client ID, secret, etc.) from the [email protected] tenant.

Will this setup work, or is there a requirement to have a subscription under the two.ai tenant as well for proper SSO functionality? Would having the app and bot registered under two.ai be necessary for this scenario?

@microsoft-github-policy-service microsoft-github-policy-service bot added the needs attention This issue needs the attention of a contributor. label Oct 21, 2024
@adashen adashen added investigating TA:Auth Team Area: Auth labels Oct 22, 2024
@blackchoey
Copy link
Contributor

As long as you configured the Entra app registration as multi-tenant, it should work. Please share the error message if you meet any issues.

@blackchoey blackchoey added needs more info Need user to provide more info and removed needs attention This issue needs the attention of a contributor. labels Oct 22, 2024
@arundhathiMenon
Copy link
Author

arundhathiMenon commented Oct 22, 2024

index.ts File:

import * as restify from "restify";
require('dotenv').config();
import {
CloudAdapter,
ConfigurationServiceClientCredentialFactory,
ConfigurationBotFrameworkAuthentication,
TurnContext,
MemoryStorage, ConversationState, UserState,
} from "botbuilder";
import { TeamsBot } from "./teamsBot";
import config from "./config";

const credentialsFactory = new ConfigurationServiceClientCredentialFactory({
MicrosoftAppId: config.botId,
MicrosoftAppPassword: config.botPassword,
MicrosoftAppType: "MultiTenant",
});

const botFrameworkAuthentication = new ConfigurationBotFrameworkAuthentication(
{},
credentialsFactory
);

const adapter = new CloudAdapter(botFrameworkAuthentication);

const onTurnErrorHandler = async (context: TurnContext, error: Error) => {
console.error(\n [onTurnError] unhandled error: ${error});

if (context.activity.type === "message") {
await context.sendTraceActivity(
"OnTurnError Trace",
${error},
"https://www.botframework.com/schemas/error",
"TurnError"
);
await context.sendActivity(The bot encountered unhandled error:\n ${error.message});
await context.sendActivity("To continue to run this bot, please fix the bot source code.");
}
};

adapter.onTurnError = onTurnErrorHandler;

const memoryStorage = new MemoryStorage();

const conversationState = new ConversationState(memoryStorage);
const userState = new UserState(memoryStorage);

const bot = new TeamsBot(conversationState, userState);

const server = restify.createServer();
server.use(restify.plugins.bodyParser());
server.listen(process.env.port || process.env.PORT || 3978, () => {
console.log(\nBot Started, ${server.name} listening to ${server.url});
});

server.post("/api/messages", async (req, res) => {
await adapter.process(req, res, async (context) => {
await bot.run(context);
});
});

.....................................
teamsBot.ts File

import {
TeamsActivityHandler,
CardFactory,
MessageFactory,
UserTokenClient,
ConversationState,
UserState,
TurnContext,
} from "botbuilder";
import OnedriveLinkInputAdaptiveCard from "./adaptiveCards/cd_one_drive_input.json";
import HelpAdaptiveCard from "./adaptiveCards/cd_help_user.json";
import GreetAdaptiveCard from "./adaptiveCards/cd_greet_user.json";
import {
DialogSet,
DialogTurnStatus,
OAuthPrompt,
WaterfallDialog,
WaterfallStepContext,
} from "botbuilder-dialogs";
import { CloudAdapter } from "botbuilder";
const OAUTH_PROMPT_ID = "oauthPrompt";
const MAIN_DIALOG = "mainDialog";
import config from "./config";

export class TeamsBot extends TeamsActivityHandler {
private oneDriveLink: string | null;
private pdfContents: string[];

private conversationState: ConversationState;
private dialogState: any;
private dialogs: DialogSet;

constructor(conversationState: ConversationState, userState: UserState) {
super();
this.oneDriveLink = null;
this.pdfContents = [];

this.conversationState = conversationState;
this.dialogState = this.conversationState.createProperty("dialogState");

this.dialogs = new DialogSet(this.dialogState);

this.dialogs.add(
  new OAuthPrompt(OAUTH_PROMPT_ID, {
    connectionName: config.ConnectionName, // Replace with your connection name
    text: "Please sign in to continue.",
    title: "Sign in",
    timeout: 300000,
  })
);

this.dialogs.add(
  new WaterfallDialog(MAIN_DIALOG, [
    this.promptForLoginStep.bind(this),
    this.processLoginResultStep.bind(this),
  ])
);
this.onMessage(async (context, next) => {
  console.log("Messages from teams channel: ", context.activity);
  const dialogContext = await this.dialogs.createContext(context);
  const results = await dialogContext.continueDialog();

  if (results.status === DialogTurnStatus.empty) {
    await dialogContext.beginDialog(MAIN_DIALOG);
  }

  await this.conversationState.saveChanges(context, false);

  await next();
});

this.onMembersAdded(async (context, next) => {
  const welcomeText =
    "Hello and welcome by tune's intelligent AI assistant";
  await context.sendActivity(MessageFactory.text(welcomeText));
  await next();
});

}

private async promptForLoginStep(step: WaterfallStepContext) {
const userTokenClient: UserTokenClient = step.context.turnState.get(
step.context.adapter.UserTokenClientKey
) as UserTokenClient;

const tokenResponse = await userTokenClient.getUserToken(
  step.context,
  config.ConnectionName,
  null
);
console.log("tokenResponse..", tokenResponse);
if (!tokenResponse) {
  return await step.prompt(OAUTH_PROMPT_ID, {});
} else {
  return await step.next(tokenResponse);
}

}

private async processLoginResultStep(step: WaterfallStepContext) {
const tokenResponse = step.result;

if (tokenResponse && tokenResponse.token) {
  const accessToken = tokenResponse.token;
  console.log("accessToken..", accessToken);
  await step.context.sendActivity("Login successful!");
} else {
  await step.context.sendActivity("Login failed. Please try again.");
}

return await step.endDialog();

}

}
............................................
I am currently testing a Teams bot application using the BOTID and BOTPASSWORD provided by the bot service. I have configured the Azure setup according to the documentation.

I’m facing an issue with the package I am using. It keeps returning errors indicating that certain functionality is not present in the package. I believe the botbuilder package might have been updated, and I am looking for the correct package that supports Single Sign-On (SSO) and allows retrieval of an access token with user context.

Could you please provide guidance on the latest package version I should use to enable SSO and obtain an access token with the user's context in a Teams bot application?

@microsoft-github-policy-service microsoft-github-policy-service bot added needs attention This issue needs the attention of a contributor. and removed needs more info Need user to provide more info labels Oct 22, 2024
@blackchoey
Copy link
Contributor

You could refer this sample for implementation details: https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/bot-conversation-sso-quickstart/js

@blackchoey blackchoey removed the needs attention This issue needs the attention of a contributor. label Oct 23, 2024
@arundhathiMenon
Copy link
Author

i am refering to https://github.com/OfficeDev/Microsoft-Teams-Samples/blob/main/samples/bot-sso-adaptivecard/nodejs/bots/botSSOAdaptiveCard.js,
here i am getting error :
[onTurnError] unhandled error: TypeError: context.adapter.getSignInLink is not a function

Don't we have getSignInLink method on the adapter object in the current version?

@microsoft-github-policy-service microsoft-github-policy-service bot added the needs attention This issue needs the attention of a contributor. label Oct 26, 2024
@blackchoey
Copy link
Contributor

@arundhathiMenon To get better support, could you please create an issue in the Microsoft-Teams-Samples repo asking them to update the sample code? You could also create an issue in the botbuilder package's repo for help: https://github.com/microsoft/botbuilder-js.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants