Share via

Inconsistent behavior when integrating Microsoft Teams APIs with custom services using delegated and application permissions

Gerwin Van de Lurg 60 Reputation points
2026-01-13T12:58:00.4233333+00:00

I’m integrating Microsoft Teams APIs into a custom backend service that combines Microsoft Graph, Azure Bot Service, and a custom OAuth2 flow. The solution uses delegated permissions for user-initiated actions (chat and channel message retrieval) and application permissions for background processing (compliance logging and message archiving).

The issue occurs when switching between delegated and application contexts. Certain Teams endpoints (such as /teams/{id}/channels/{id}/messages and /chats/{id}/messages) succeed under delegated tokens but fail with application tokens, even though the required permissions are granted and admin consent is approved. In some cases, the same endpoint works intermittently depending on the tenant or user scope.

Additional complications include:

Tokens are issued correctly via MSAL, but the roles and scp claims vary depending on how the API call is triggered

Microsoft Teams | Development
Microsoft Teams | Development

Building, integrating, or customizing apps and workflows within Microsoft Teams using developer tools and APIs

0 comments No comments

Answer accepted by question author

  1. Kudos-Ng 15,050 Reputation points Microsoft External Staff Moderator
    2026-01-13T15:10:10.46+00:00

    Hi Gerwin Van de Lurg,

    Thank you for posting your question in the Microsoft Q&A forum. 

    From your description, it appears you’re using both delegated tokens and application (app‑only) tokens in the same solution for different purposes, and MSAL is used to acquire tokens for both authentication flows. This scenario is inherently more complex because you’re switching execution between two security contexts. You’ve already verified permission grants and admin consent, yet you’re still observing intermittent failures when switching contexts.

    To help troubleshoot further, could you share the exact HTTP status code and error details (including any error, error_description, and claims challenges) returned when the calls fail? These details are essential to distinguish a permissions/consent issue from a token‑lifecycle or conditional access challenge.

    For clarity: delegated and app‑only tokens carry different claims. Delegated tokens present scp (scopes), while application tokens present roles (app roles). Please log and inspect the token used for each failing request to confirm that the token type matches the endpoint’s requirement. You can safely decode the JWT at jwt.ms and verify the aud, tid, appid/azp, and the presence of scp (delegated) or roles (application), but not both simultaneously.
    *The link above may reference Microsoft-related content but is not hosted on an official Microsoft domain (such as .microsoft.com). Please note that Microsoft is not responsible for the accuracy, security, or advertising on this site.

    Regarding renewal behavior: MSAL caches tokens after acquisition. For delegated flows, MSAL will attempt silent acquisition and, when needed, use a refresh token to obtain a new access token without user interaction (subject to your policy constraints). In contrast, client credentials (app‑only) flows do not use refresh tokens; when an app‑only access token expires, your code must request a new token.

    Because your solution uses both token types, I recommend clearly separating token caches and acquisition paths to avoid cross‑context reuse of the wrong token. In practice, that means using distinct MSAL client instances and cache partitions for delegated versus app‑only operations, and always mapping each endpoint to the required permission type before issuing the call. The MSAL articles below provide concrete details for two token type cache:

    I hope this helps.


    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Was this answer helpful?


1 additional answer

Sort by: Most helpful
  1. Q&A Assist
    2026-01-13T12:58:12.11+00:00
    AI generated content. This question contains an answer created with AI from Q&A Assist. Learn more

    When integrating Microsoft Teams APIs with custom services using both delegated and application permissions, it's important to understand the differences in how these permissions operate and the contexts in which they are used.

    1. Delegated Permissions: These permissions allow the application to act on behalf of a signed-in user. This means that the application can only access the information that the user has access to. If your API calls for chat and channel message retrieval succeed under delegated tokens, it indicates that the user has the necessary permissions to access that data.
    2. Application Permissions: These permissions allow the application to act on its own, without a signed-in user. This means that the application can access data associated with the permissions granted, regardless of any individual user's access rights. However, application permissions can carry more privacy risks since they allow broader access to data.

    The inconsistent behavior you're experiencing could be due to several factors:

    • Scope of Permissions: Ensure that the application permissions you are using are sufficient for the operations you are trying to perform. The permissions granted must align with the data access requirements of the Teams APIs.
    • Token Acquisition: Make sure that the tokens are being acquired correctly and that the type of permissions requested matches the type of access token being used. For instance, using delegated tokens for application-level permissions or vice versa can lead to errors.
    • Tenant and User Scope: The behavior of certain endpoints may vary depending on the tenant configuration and user roles. Some tenants may have stricter policies or different configurations that affect how permissions are handled.
    • Claims in Tokens: The roles and scopes (scp) claims in the tokens can differ based on how the API call is triggered. This can lead to inconsistencies in access rights when switching contexts.

    To resolve these issues, you may want to implement a robust error handling and logging mechanism to capture the specific errors returned by the API calls. This can help identify whether the issue is related to permissions, token scopes, or tenant configurations.

    Additionally, consider reviewing the Microsoft Graph permissions documentation to ensure that you are adhering to best practices for permission management and token handling.


    References:

    Was this answer helpful?

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.