Environment
self-hosted (https://develop.sentry.dev/self-hosted/)
Steps to Reproduce
On a self-hosted Sentry (26.6.0), set up the Microsoft Teams integration from scratch, following https://develop.sentry.dev/integrations/msteams/
- Create a Teams app + bot in the Teams Developer Portal.
- Create an Azure Bot resource for it (required — a Developer-Portal-only bot has no Bot Framework identity and can never send outbound messages). Azure today offers only
Single Tenant or User-Assigned Managed Identity as "Type of App"; Multi Tenant no longer exists, since Microsoft deprecated multi-tenant bot creation on 2025-07-31.
- Creation type: Use existing app registration
- Backed by a multi-tenant Entra app registration ("Accounts in any organizational directory")
- On the Azure Bot resource: set the messaging endpoint to
https://<sentry-host>/extensions/msteams/webhook/ and enable the Microsoft Teams channel.
- Set
msteams.client-id (bot app id) and msteams.client-secret in config.yml, restart web.
- Publish the Teams app org-wide and add it to a team.
Expected Result
Sentry posts the "Welcome to Sentry for Microsoft Teams" card to the channel, the webhook returns 200, and an Integration row with provider='msteams' is created.
Actual Result
The inbound webhook is reached and passes JWT validation, but every outbound Bot Connector call returns 401, so the webhook handler raises and returns 500. The integration is never created and no welcome message is sent.
[INFO] sentry.access.api: api.access (method='POST' view='sentry.integrations.msteams.webhook.MsTeamsWebhookEndpoint' response='500' path='/extensions/msteams/webhook/' user_agent='Microsoft-SkypeBotApi (Microsoft-BotFramework/3.0)') [WARNING] sentry.integrations.client: integration.http_response (url='https://smba.trafficmanager.net/at//v3/conversations/19:...@thread.tacv2/activities' integration='msteams' status_string='401' error='401 Client Error: Unauthorized') [ERROR] django.request: Internal Server Error: /extensions/msteams/webhook/ (status_code=500)
Root cause
Sentry acquires the Bot Connector token from the multi-tenant authority, hardcoded in
src/sentry/integrations/msteams/client.py#L140:
class OAuthMsTeamsClient(ApiClient):
TOKEN_URL = "/oauth2/v2.0/token"
def __init__(self, client_id, client_secret):
tenant_id = options.get("msteams.tenant-id") # new option, defaults to ""
self.base_url = (
f"https://login.microsoftonline.com/{tenant_id}"
if tenant_id
else "https://login.microsoftonline.com/botframework.com"
)
...
A single-tenant Azure Bot — now the only kind that can be created — must obtain its token from the tenant-specific authority instead:
https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/token
There is no option to configure this, so the integration cannot work.
Proof (same credentials, same scope, same conversation — only the authority differs)
SCOPE = "https://api.botframework.com/.default"
URL = f"{service_url}/v3/conversations/{conversation_id}/members" # read-only probe
A) what Sentry does today
tok_a = client_credentials("https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token")
GET(URL, bearer=tok_a) # -> 401 {"message":"Authorization has been denied for this request."}
B) tenant-specific authority
tok_b = client_credentials(f"https://login.microsoftonline.com/{TENANT_ID}/oauth2/v2.0/token")
GET(URL, bearer=tok_b) # -> 200 OK
Both tokens carry aud=https://api.botframework.com and the correct appid; only the issuer differs.
Workarounds that do NOT exist
Creating a multi-tenant Azure Bot: blocked by Microsoft since 2025-07-31.
Flipping an existing bot to multi-tenant: az resource update --set properties.msaAppType=MultiTenant --remove properties.msaAppTenantId returns HTTP 200 with no error, but silently does not apply the change — msaAppType stays SingleTenant. Re-measuring afterwards confirms the 401 persists.
Upgrading Sentry: master carries the same hardcoded line.
Impact
Any self-hosted instance configuring MS Teams for the first time after 2025-07-31 cannot complete the integration. Existing installs backed by legacy multi-tenant bots are unaffected, which likely explains why this has gone unnoticed. This may be the underlying cause of #108113.
Suggested fix (backwards compatible)
Make the authority configurable; default to today's behaviour.
class OAuthMsTeamsClient(ApiClient):
TOKEN_URL = "/oauth2/v2.0/token"
def __init__(self, client_id, client_secret):
tenant_id = options.get("msteams.tenant-id") # new option, defaults to ""
self.base_url = (
f"https://login.microsoftonline.com/{tenant_id}"
if tenant_id
else "https://login.microsoftonline.com/botframework.com"
)
...
In src/sentry/options/defaults.py, next to the existing msteams.* options:
```python
register("msteams.tenant-id", flags=FLAG_PRIORITIZE_DISK | FLAG_AUTOMATOR_MODIFIABLE)
Existing multi-tenant deployments keep working untouched; single-tenant deployments set msteams.tenant-id in config.yml.
The docs at https://develop.sentry.dev/integrations/msteams/ should also state that an Azure Bot resource is mandatory — the current instructions stop at the Teams Developer Portal, which by itself produces a bot that can never send outbound messages.
References
Multi-tenant bot deprecation (2025-07-31): https://techcommunity.microsoft.com/discussions/teamsdeveloper/questions-about-alternatives-to-multi-tenant-bots-after-july-31-2025-deprecation/4423676
Multi-tenant app + single-tenant bot → use tenant-specific authority: https://learn.microsoft.com/en-us/answers/questions/5584294/multitenant-app-associated-to-single-tenant-azure
Developer-Portal-only bots cannot send outbound messages: https://learn.microsoft.com/en-us/answers/questions/5650695/single-tenant-teams-bot-(dev-portal-only)-gets-401
Product Area
Settings - Integrations
Link
No response
DSN
No response
Version
26.6.0
Environment
self-hosted (https://develop.sentry.dev/self-hosted/)
Steps to Reproduce
On a self-hosted Sentry (26.6.0), set up the Microsoft Teams integration from scratch, following https://develop.sentry.dev/integrations/msteams/
Single TenantorUser-Assigned Managed Identityas "Type of App";Multi Tenantno longer exists, since Microsoft deprecated multi-tenant bot creation on 2025-07-31.https://<sentry-host>/extensions/msteams/webhook/and enable the Microsoft Teams channel.msteams.client-id(bot app id) andmsteams.client-secretinconfig.yml, restartweb.Expected Result
Sentry posts the "Welcome to Sentry for Microsoft Teams" card to the channel, the webhook returns 200, and an
Integrationrow withprovider='msteams'is created.Actual Result
The inbound webhook is reached and passes JWT validation, but every outbound Bot Connector call returns 401, so the webhook handler raises and returns 500. The integration is never created and no welcome message is sent.
[INFO] sentry.access.api: api.access (method='POST' view='sentry.integrations.msteams.webhook.MsTeamsWebhookEndpoint' response='500' path='/extensions/msteams/webhook/' user_agent='Microsoft-SkypeBotApi (Microsoft-BotFramework/3.0)') [WARNING] sentry.integrations.client: integration.http_response (url='https://smba.trafficmanager.net/at//v3/conversations/19:...@thread.tacv2/activities' integration='msteams' status_string='401' error='401 Client Error: Unauthorized') [ERROR] django.request: Internal Server Error: /extensions/msteams/webhook/ (status_code=500)
Root cause
Sentry acquires the Bot Connector token from the multi-tenant authority, hardcoded in
src/sentry/integrations/msteams/client.py#L140:A single-tenant Azure Bot — now the only kind that can be created — must obtain its token from the tenant-specific authority instead:
https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/token
There is no option to configure this, so the integration cannot work.
Proof (same credentials, same scope, same conversation — only the authority differs)
A) what Sentry does today
B) tenant-specific authority
Both tokens carry aud=https://api.botframework.com and the correct appid; only the issuer differs.
Workarounds that do NOT exist
Creating a multi-tenant Azure Bot: blocked by Microsoft since 2025-07-31.
Flipping an existing bot to multi-tenant: az resource update --set properties.msaAppType=MultiTenant --remove properties.msaAppTenantId returns HTTP 200 with no error, but silently does not apply the change — msaAppType stays SingleTenant. Re-measuring afterwards confirms the 401 persists.
Upgrading Sentry: master carries the same hardcoded line.
Impact
Any self-hosted instance configuring MS Teams for the first time after 2025-07-31 cannot complete the integration. Existing installs backed by legacy multi-tenant bots are unaffected, which likely explains why this has gone unnoticed. This may be the underlying cause of #108113.
Suggested fix (backwards compatible)
Make the authority configurable; default to today's behaviour.
Existing multi-tenant deployments keep working untouched; single-tenant deployments set msteams.tenant-id in config.yml.
The docs at https://develop.sentry.dev/integrations/msteams/ should also state that an Azure Bot resource is mandatory — the current instructions stop at the Teams Developer Portal, which by itself produces a bot that can never send outbound messages.
References
Multi-tenant bot deprecation (2025-07-31): https://techcommunity.microsoft.com/discussions/teamsdeveloper/questions-about-alternatives-to-multi-tenant-bots-after-july-31-2025-deprecation/4423676
Multi-tenant app + single-tenant bot → use tenant-specific authority: https://learn.microsoft.com/en-us/answers/questions/5584294/multitenant-app-associated-to-single-tenant-azure
Developer-Portal-only bots cannot send outbound messages: https://learn.microsoft.com/en-us/answers/questions/5650695/single-tenant-teams-bot-(dev-portal-only)-gets-401
Product Area
Settings - Integrations
Link
No response
DSN
No response
Version
26.6.0