Microsoft Teams Bot Framework · error code

Teams error 401 Unauthorized (token audience): Wrong token scope or audience

ConfigurationHTTP 401Authentication & identity

Last verified against Microsoft Learn - Status codes from bot conversational APIs

What Teams returns
Authorization has been denied for this request.

What error 401 Unauthorized (token audience) means

Your bot obtained a token successfully, but the token is not acceptable to the service receiving it, so the Connector answers 401 even though Entra was perfectly happy. A Bot Framework service token must be requested with the scope https://api.botframework.com/.default - the exact value Microsoft's authentication troubleshooting guide bakes into its cURL verification step. Request a token scoped for Microsoft Graph, your own API, or any other resource, and the resulting audience claim is wrong; the Connector rejects it regardless of how valid the credentials were.

The same class of failure exists inbound: requests from Teams carry a JWT your adapter validates, and if your endpoint checks the wrong expected audience (for example, after swapping app IDs during a migration) every incoming activity is rejected with 401 before your handler runs - the bot looks deaf rather than mute. Distinguish the directions by where the 401 shows up: outbound failures appear when you call send or reply; inbound failures appear as 401 responses in your own endpoint's access log while Teams retries delivery.

What it looks like

curl -X POST https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token \
  -d "grant_type=client_credentials&client_id=APP_ID&client_secret=APP_PASSWORD&scope=https%3A%2F%2Fapi.botframework.com%2F.default"

Why it happens

  • The token request uses a scope other than https://api.botframework.com/.default (commonly a Graph scope left over from other code).
  • A Graph token and a Connector token are cached in the same slot and the wrong one is attached to Connector calls.
  • The adapter's expected audience/app ID differs from the app ID that Teams addressed the inbound token to.
  • A custom token cache serves a stale token for a previous app registration after a migration.

How to fix Teams error 401 Unauthorized (token audience)

  1. 1Log the failing request's Authorization header (locally, never in production logs) and decode the JWT: check the aud claim.
  2. 2Acquire the Connector token with scope=https%3A%2F%2Fapi.botframework.com%2F.default exactly as the documented cURL check does, and retest.
  3. 3Keep separate named token providers for Connector and Graph so the two can never cross.
  4. 4For inbound 401s, confirm the adapter is configured with the same MicrosoftAppId the manifest advertises, then re-run one message end to end.

How to stop it recurring

Never hand-roll token acquisition for the Connector - the SDK credential classes request the right scope and manage caching correctly. If you must call the REST API directly, hard-code the documented scope as a constant with a comment pointing at the authentication reference. Keep Graph and Connector clients in separate modules with separate credentials objects; shared plumbing is how audiences get crossed. The app ID / password entry covers the case where the token request itself fails.

Official reference: Microsoft Learn - Status codes from bot conversational APIs. See all Teams error codes or the Teams limits and quotas.

Related codes

Error 401 Unauthorized (token audience) - quick answers

What does Teams error 401 Unauthorized (token audience) mean?

Your bot obtained a token successfully, but the token is not acceptable to the service receiving it, so the Connector answers 401 even though Entra was perfectly happy. A Bot Framework service token must be requested with the scope https://api.botframework.com/.default - the exact value Microsoft's authentication troubleshooting guide bakes into its cURL verification step.

How do I fix Teams error 401 Unauthorized (token audience)?

1. Log the failing request's Authorization header (locally, never in production logs) and decode the JWT: check the aud claim. 2. Acquire the Connector token with scope=https%3A%2F%2Fapi.botframework.com%2F.default exactly as the documented cURL check does, and retest. 3. Keep separate named token providers for Connector and Graph so the two can never cross. 4. For inbound 401s, confirm the adapter is configured with the same MicrosoftAppId the manifest advertises, then…

Stop debugging Teams by hand

Connect the channel through Conferbot: tokens, webhooks and retries are handled, failures show as readable status.