{"id":16964917,"url":"https://github.com/garrytrinder/msteams-bot-msgraph-azbot","last_synced_at":"2026-08-03T03:31:23.100Z","repository":{"id":205264464,"uuid":"713485036","full_name":"garrytrinder/msteams-bot-msgraph-azbot","owner":"garrytrinder","description":"Teams Toolkit for Visual Studio Code Basic Bot template with SSO, Azure Bot Service and Azure Cosmos DB for local development","archived":false,"fork":false,"pushed_at":"2023-11-07T17:22:34.000Z","size":670,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-09T02:02:58.683Z","etag":null,"topics":["azure-bot-service","azure-cosmos-db","microsoft-graph","microsoft-teams","microsoft-teams-bot","teams-toolkit"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/garrytrinder.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-11-02T16:03:13.000Z","updated_at":"2024-05-28T01:57:43.000Z","dependencies_parsed_at":"2024-11-28T00:46:19.277Z","dependency_job_id":null,"html_url":"https://github.com/garrytrinder/msteams-bot-msgraph-azbot","commit_stats":null,"previous_names":["garrytrinder/msteams-bot-msgraph-azbot"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/garrytrinder/msteams-bot-msgraph-azbot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garrytrinder%2Fmsteams-bot-msgraph-azbot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garrytrinder%2Fmsteams-bot-msgraph-azbot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garrytrinder%2Fmsteams-bot-msgraph-azbot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garrytrinder%2Fmsteams-bot-msgraph-azbot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/garrytrinder","download_url":"https://codeload.github.com/garrytrinder/msteams-bot-msgraph-azbot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garrytrinder%2Fmsteams-bot-msgraph-azbot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":36216798,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-08-03T02:00:06.975Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azure-bot-service","azure-cosmos-db","microsoft-graph","microsoft-teams","microsoft-teams-bot","teams-toolkit"],"created_at":"2024-10-13T23:44:34.748Z","updated_at":"2026-08-03T03:31:23.083Z","avatar_url":"https://github.com/garrytrinder.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Teams Toolkit for Visual Studio Code Basic Bot template with SSO, Azure Bot Service and Azure Cosmos DB for local development\n\nThis sample extends the out of the box Basic Bot project template in Teams Toolkit for Visual Studio Code and makes the following changes\\enhancements:\n\n- Uses `Azure Bot Service` free-tier for local development loop instead of [Microsoft Bot Framework](https://dev.botframework.com/) bot registration\n- Uses `Azure Cosmos DB` free-tier account in local development loop to [read/write conversation state to storage](https://learn.microsoft.com/azure/bot-service/bot-builder-howto-v4-storage?view=azure-bot-service-4.0\u0026tabs=javascript#using-cosmos-db) instead of `MemoryStorage`. [Why Azure Cosmos DB](#why-azure-cosmos-db)?\n- Uses `aadApp/create` and `aadApp/update` tasks to create Microsoft Entra ID app registration for Azure Bot Service with app registration manifest in local development\n- Uses `arm/deploy` task to update Azure Bot Service during local development, updates messaging endpoint and OAuth connection setting\n- Uses [Azure Bot Service Token Service](https://learn.microsoft.com/azure/bot-service/bot-builder-concept-authentication?view=azure-bot-service-4.0#about-the-bot-framework-token-service) to simplify authentication flow\n- Uses [Dialogs library](https://learn.microsoft.com/en-us/azure/bot-service/bot-builder-concept-dialog) to obtain access token for Microsoft Graph using OAuthPrompt\n- Uses [TeamsSSOTokenExchangeMiddleware]() to handle deduplication in the token exchange step\n- Uses linting (ESLint) and formatting (Prettier) rules for code consistency, configured using [GTS](https://github.com/google/gts) (Google TypeScript Style)\n- Updated project dependencies to latest major versions (as of November '23)\n\n\u003e ℹ️ This sample goes as far as obtaining a valid access token that can be used to call Microsoft Graph API. This is intentional leaving it open for you as a developer to choose your own path and leave this as un-opinionated as possible.\n\n## Prerequisites\n\n- Teams Toolkit for Visual Studio Code\n- Microsoft 365 tenant with [uploading custom apps enabled](https://learn.microsoft.com/microsoftteams/platform/m365-apps/prerequisites#prepare-a-developer-tenant-for-testing)\n- Account with access to an active Azure subscription and has permissions to create a resource group\n\n## Get started\n\n- Clone repo\n- Open repo in VSCode\n- Take a copy of all the files in `env` folder and remove `.sample` from the copies, for example, `.env.local.sample` becomes `.env.local`\n- Press `F5`, follow the sign in prompts\n\n\u003e ℹ️ The `arm/deploy` task generates a prompt that you need to confirm to provision or update the Azure Bot Service in Azure. The Azure Bot Service and Azure Cosmos DB are provisioned using the free tiers, so no cost will be incurred.\n\u003e\n\u003e ⚠️ If you already have an Azure Cosmos DB account that uses the free-tier in your target Azure subscription the provisioning will fail. There is a limitation on one free tier account per Azure subscription.\n\n## Test the bot\n\nSend a message to the bot and an Adaptive Card will be returned with the access token to call Microsoft Graph.\n\n![Screenshot of sign in ](./assets/bot-signin.png)\n\n![Screenshot of Microsoft Entra consent](./assets/bot-consent.png)\n\n![Screenshot of token for Microsoft Graph rendered in an Adaptive Card](./assets/bot-token.png)\n\n## Manage conversation state\n\nTo manage the conversation state saved to Azure Cosmos DB, use the web based [Azure Cosmos DB Explorer](https://cosmos.azure.com/).\n\n![Screenshot of conversation state entry in Azure Cosmos DB Explorer](./assets/cosmos-db-explorer.png)\n\n## What happens when you press F5\n\nThe following sequence diagram shows the interacts between components when you start a debug session in VSCode.\n\n```mermaid\nsequenceDiagram\n    actor Developer\n    participant VSCode\n    participant teamsfx\n    participant DevTunnel\n    participant TDP\n    participant Azure\n    participant npm\n    participant Browser\n\n    activate VSCode\n    activate TDP\n    activate Azure\n    \n    Developer-\u003e\u003eVSCode:startDebug\n\n    rect rgb(240,240,240)\n        VSCode-\u003e\u003eteamsfx:Validate prerequisites (prerequisites, portOccupancy)\n        activate teamsfx\n        teamsfx--\u003e\u003eVSCode: result\n        deactivate teamsfx\n    end\n\n    rect rgb(240,240,240)\n        note right of VSCode: Start DevTunnel\n        VSCode-\u003e\u003eteamsfx:Start local tunnel (type, port, protocol, access, endpoint, domain, env)\n        activate teamsfx\n        teamsfx-\u003e\u003eDevTunnel:start(port, protocol, access)\n        activate DevTunnel\n        DevTunnel--\u003e\u003eteamsfx:tunnel (endpoint, domain)\n        teamsfx-\u003e\u003eteamsfx:write to env file (endpoint, domain)\n        teamsfx--\u003e\u003eVSCode: output\n        deactivate teamsfx\n    end\n\n    rect rgb(240,240,240)\n        note right of VSCode: Provision app\n        VSCode-\u003e\u003eteamsfx:Provision (teamsapp.local.yml)\n        activate teamsfx\n        rect rgb(200, 150, 255)\n            note right of teamsfx: Create app in Teams Developer Portal (TDP)\n            teamsfx-\u003e\u003eTDP: teamsApp/create (name)\n            TDP--\u003e\u003eteamsfx: response (teamsAppId)\n            teamsfx-\u003e\u003eteamsfx:write to env file (teamsAppId)\n        end\n        rect rgb(191, 223, 255)\n            note right of teamsfx: Provision Azure resources\n            teamsfx-\u003e\u003eAzure: aadApp/create (name, generateClientSecret, signInAudience)\n            Azure--\u003e\u003eteamsfx: response (clientId, clientSecret, objectId, tenantId, authority, authorityHost)\n            teamsfx-\u003e\u003eteamsfx:write to env file (clientId, objectId, tenantId, authority, authorityHost)\n            teamsfx-\u003e\u003eteamsfx:write to env user file (clientSecret)\n            teamsfx-\u003e\u003eAzure: aadApp/update (manifest)\n            Azure--\u003e\u003eteamsfx: response (manifest)\n            teamsfx-\u003e\u003eteamsfx: update file (outputFilePath, manifest)\n            teamsfx-\u003e\u003eAzure: arm/deploy (subscriptionId, resourceGroupName, templates)\n            Azure--\u003e\u003eteamsfx: result (202 Accepted)\n        end\n        rect rgb(200, 150, 255)\n            note right of teamsfx: Package and upload Teams app\n            teamsfx-\u003e\u003eTDP: teamsApp/validateManifest (manifest)\n            TDP--\u003e\u003eteamsfx: result\n            teamsfx-\u003e\u003eteamsfx: teamsApp/zipAppPackage (manifestPath, outputZipPath, outputJsonPath)\n            teamsfx-\u003e\u003eTDP:teamsApp/validateAppPackage (appPackagePath)\n            TDP--\u003e\u003eteamsfx: result\n            teamsfx-\u003e\u003eTDP:teamsApp/update (appPackagePath)\n            TDP--\u003e\u003eteamsfx: result\n        end\n            teamsfx--\u003e\u003eVSCode: output\n        deactivate teamsfx\n    end\n\n    rect rgb(240,240,240)\n        note right of Developer: Start local dev server\n        VSCode-\u003e\u003eteamsfx:Deploy (teamsapp.local.yml)\n        activate teamsfx\n        teamsfx-\u003e\u003enpm:npm install\n        activate npm\n        npm--\u003e\u003eteamsfx:result\n        deactivate npm\n        teamsfx-\u003e\u003eteamsfx: file/createOrUpdateEnvironmentFile (target, envs)\n        teamsfx--\u003e\u003eVSCode: output\n        deactivate teamsfx\n        VSCode-\u003e\u003enpm: npm run dev:teamsfx\n        activate npm\n        npm--\u003e\u003eVSCode: output\n        VSCode--\u003e\u003eDeveloper: nodemon task\n    end\n\n    VSCode-\u003e\u003eVSCode: Attach to debugger\n    VSCode-\u003e\u003eBrowser: Launch (sideloading URL)\n    activate Browser\n    Browser--\u003e\u003eVSCode: result\n    Browser--\u003e\u003eDeveloper: Microsoft Teams sideloading UI\n \n    deactivate DevTunnel\n    deactivate VSCode\n    deactivate TDP\n    deactivate Azure\n    deactivate npm\n    deactivate Browser\n```\n\n## System context diagram\n\n```mermaid\nC4Context\n    title System context diagram for Microsoft Teams app that can access data in Microsoft 365 via Microsoft Graph\n\n    Person(user,\"Microsoft 365 User\")\n    System_Ext(teams_client, \"Microsoft Teams Client\", \"Provides access to Microsoft Teams platform\")\n    System(app, \"Microsoft Teams app\", \"Provides functionality to extend Microsoft Teams\")\n    System_Ext(graph, \"Microsoft Graph API\", \"Provides access to Microsoft 365 data\")\n    System_Ext(entra,\"Microsoft Entra ID\", \"Registers app on Microsoft cloud\")\n\n    Rel(user, teams_client, \"Uses\")\n    Rel(teams_client, app, \"Uses\")\n    Rel(app, entra, \"Uses\")\n    Rel(app, graph, \"Uses\")\n```\n\n## Container diagram\n\n```mermaid\nC4Container\n    title Container context diagram for Microsoft Teams app that can access data in Microsoft 365 via Microsoft Graph\n\n    Person(user,\"Microsoft 365 User\")\n    System_Ext(teams_client, \"Microsoft Teams Client\", \"Provides access to Microsoft Teams platform\")\n    System_Ext(entra,\"Microsoft Entra ID\", \"Registers app on Microsoft cloud\")\n    System_Ext(graph, \"Microsoft Graph API\",\"Provides access to Microsoft 365 data\")\n\n    System_Boundary(app, \"Microsoft Teams app\") {\n        Container(teams_app, \"Microsoft Teams app\", \"Microsoft Teams App Package\", \"Extends Microsoft Teams with an app containing a bot\")\n        Container(bot, \"Bot Service\", \"Azure Bot Service\", \"Broker between between Microsoft Teams and bot logic\")\n        Container(web_app, \"Web Application\", \"nodejs, restify\", \"Provides the bot logic\")\n        ContainerDb(db,\"Database\",\"Azure Cosmos DB\",\"Stores bot state\")\n    }\n\n    Rel(web_app,graph,\"Uses\")\n    Rel(user,teams_client,\"Uses\")\n    Rel(teams_client,teams_app,\"Is extended by\")\n    Rel(teams_app,entra,\"Uses for SSO\")\n    Rel(web_app,bot,\"Sends/receives activities from\")\n    Rel(web_app,entra,\"Authenticates users with\")\n    Rel(web_app,db,\"Reads/writes to\")\n```\n## Why Azure Cosmos DB?\n\n`MemoryStorage` is commonly used to provide functionality to save state during local development. Unfortunately, using `MemoryStorage` has drawbacks such as when the server is restarted, for example, when the developer makes a code change, the current state is lost. When using state, it is desirable to have data persist after making code changes so that the developer does not have to start over again.\n\n[Write directly to storage](https://learn.microsoft.com/azure/bot-service/bot-builder-howto-v4-storage?view=azure-bot-service-4.0\u0026tabs=javascript) article suggests three ways to write to storage:\n\n1. MemoryStorage\n2. Azure Cosmos DB\n3. Azure Blob Storage\n\n[Add code to enable SSO in your bot app](https://learn.microsoft.com/microsoftteams/platform/bots/how-to/authentication/bot-sso-code?tabs=js1%2Cjs2%2Ccs3%2Cjs4%2Cjs5\u0026pivots=bot-app#add-code-to-request-a-token) article provides guidance and recommends that developers use the \n[TeamsSSOTokenExchangeMiddleware](https://learn.microsoft.com/javascript/api/botbuilder/teamsssotokenexchangemiddleware?view=botbuilder-ts-latest) class to handle deduplication in the token exchange step.\n\nHowever, the `TeamsSSOTokenExchangeMiddleware` class only supports `MemoryStorage` and `Azure Cosmos DB`, so we cannot use `Azure Blob Storage`.\n\nThis leaves two options:\n\n1. Stand-up an Azure Cosmos DB resource in Azure using the free-tier\n2. Implement emulated Azure Cosmos DB resource [locally using Docker](https://learn.microsoft.com/en-us/azure/cosmos-db/how-to-develop-emulator?tabs=docker-linux%2Ccsharp\u0026pivots=api-nosql)\n\nOption one provides the easiest implementation, the project already provisions an Azure Bot Service for local development so it would just be a case of updating the existing bicep files to add this in. The only drawback is that you can only have one free-tier resource per subscription, so developers would need to keep this in mind if they had multiple projects that used this approach using the same Azure subscription. If that would be the case then developers would need to provide the resource IDs in the environment files and ensure that table names do not conflict.\n\nOption two does not require any Azure resources to be stood up, but adds additional requirements such as Docker and would consume more local resources. Also depending on which operating system you use the setup instructions are different and would need to be performed manually.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgarrytrinder%2Fmsteams-bot-msgraph-azbot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgarrytrinder%2Fmsteams-bot-msgraph-azbot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgarrytrinder%2Fmsteams-bot-msgraph-azbot/lists"}