Share via

Set|New-CsTeamsMeetingPolicy returns 40301 with app-only auth when run from long-running PowerShell process; same call works in one-shot process

Daniel Browne 1 Reputation point
2026-03-12T18:45:00.7666667+00:00

We are using application-based (certificate) authentication with the MicrosoftTeams PowerShell module as described in Application-based authentication in Teams PowerShell Module. The app has the Teams Administrator directory role and the same certificate/auth works for Get/Set operations.

Issue: New-CsTeamsMeetingPolicy -Identity "PolicyName" returns 40301 ("You are not authorized to perform this action") when the cmdlet runs inside a long-running PowerShell process (e.g. a process that started as an HTTP listener and then runs user scripts in the same runspace). The exact same script (Connect-MicrosoftTeams with the same cert + New-CsTeamsMeetingPolicy) succeeds when run in a one-shot PowerShell process (e.g. pwsh -File script.ps1 that exits when the script finishes).

Environment:

  • MicrosoftTeams module 7.5.0
  • PowerShell 7.4.6 (Core)
  • Connect: Connect-MicrosoftTeams -Certificate $cert -ApplicationId $appId -TenantId $tenantId
  • Same app registration, certificate, and tenant in both scenarios

What we’ve ruled out:

  • Same cert, app ID, tenant, and directory role in both cases
  • Reconnecting (Disconnect then Connect) inside the long-running process does not fix 40301
  • Environment variables (USER, TERM, HOME) and pseudo-TTY match between the two runs
  • Get-CsTeamsMeetingPolicy works in the long-running process; Set and New (create) fails there

Example error (from long-running process):

PolicyRpException: {"code":"Forbidden","message":"You are not authorized to perform this action","action":"Please refer to documentation. CorrelationId: ddf6f606-b145-42c2-aa84-94315e79058c","errorCode":40301}

Question: Can you confirm whether the Skype/Teams backend or the module treats long-running vs one-shot PowerShell processes differently for app-only certificate auth (e.g. for create operations like New-CsTeamsMeetingPolicy)? If so, is that intentional, and is there a supported way to run these create operations from an automated, long-running process (e.g. a script host that serves multiple requests)? There is a correlation ID to track in the message above.

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
{count} votes

1 answer

Sort by: Most helpful
  1. Q&A Assist
    2026-03-12T18:45:29.84+00:00
    AI generated content. This question contains an answer created with AI from Q&A Assist. Learn more

    The behavior is not documented as being different for long-running versus one-shot PowerShell processes. Application-based authentication for the MicrosoftTeams module is based solely on the access token issued for the Microsoft Entra application (service principal), its assigned Microsoft Graph permissions, and its assigned Microsoft Entra directory roles.

    Key points from the documented model:

    1. Application-based auth model
      • The Teams PowerShell module uses the application ID, tenant ID, and certificate (thumbprint or object) to obtain an app-only token.
      • The app object in Microsoft Entra ID must have:
        • The required Microsoft Graph API permissions for the cmdlets being used (for example, Group.ReadWrite.All, TeamSettings.ReadWrite.All, etc. for non-*Cs cmdlets).
        • Appropriate Microsoft Entra directory roles assigned (for example, Teams Administrator) so that the role is included in the access token.
      • RBAC for the session is derived from the directory role information in the token, not from process lifetime.
      Reference behavior:

      “Teams PowerShell Module fetches the app-based token using the application ID, tenant ID and certificate thumbprint. The application object provisioned inside Microsoft Entra ID has a Directory Role assigned to it, which is returned in the access token. The session's role-based access control (RBAC) is configured using the directory role information that's available in the token.”

    2. Cmdlet capabilities
      • New-CsTeamsMeetingPolicy is explicitly supported for creating custom meeting policies.
      • It is part of the standard policy management pattern (GET/NEW/SET/REMOVE/GRANT) and is intended to be used in automation scenarios.
      • There is no documented restriction that New-CsTeamsMeetingPolicy cannot be used with app-only authentication or in long-running processes.
      From the cmdlet documentation:
      • New-CsTeamsMeetingPolicy “allows administrators to define new meeting policies that can be assigned to particular users to control Teams features related to meetings.”
      • It is one of the NEW commands in the policy lifecycle used for automation.
    3. Supported automation pattern
      • The supported way to automate Teams policy management (including creating policies) is:
        1. Configure application-based authentication as documented (register app, assign Graph permissions, generate/attach certificate, assign appropriate Microsoft Entra roles).
        2. Use Connect-MicrosoftTeams with the certificate and app ID/tenant ID to establish an app-only session.
        3. Run New-CsTeamsMeetingPolicy, Set-CsTeamsMeetingPolicy, and other policy cmdlets within that authenticated session.
      • The documentation does not differentiate between:
        • A short-lived PowerShell process that exits after the script, and
        • A long-running host process that maintains a runspace and executes multiple scripts.
      • As long as the session is authenticated with a valid app-only token that carries the correct roles and permissions, the cmdlets are supported.
    4. What the 40301 implies in this model
      • A 40301 “You are not authorized to perform this action” from the backend indicates that, for that specific request, the backend did not see sufficient permissions/roles in the token or RBAC context.
      • In the documented model, this is tied to:
        • The directory roles assigned to the app, and
        • The API permissions configured for the app.
      • There is no documented behavior where the backend denies New-CsTeamsMeetingPolicy based on the process being long-running versus one-shot.
    5. Supported path for long-running automation
      • For a supported configuration, ensure that:
        • The app is registered and configured as described in “Application-based authentication in Teams PowerShell Module” (steps 1–5: register app, assign API permissions, generate/attach certificate, assign Microsoft Entra roles).
        • The long-running host always uses a fresh or valid token obtained via Connect-MicrosoftTeams with the certificate/app/tenant.
        • The app has the appropriate directory role (for example, Teams Administrator) and required Graph permissions for policy management.
      • With this configuration, running New-CsTeamsMeetingPolicy from an automated, long-running process is within the supported pattern; there is no separate or special mode required for long-running hosts documented.

    Because the authorization decision is based on the token and assigned roles/permissions, not on process lifetime, any 40301 differences between long-running and one-shot scenarios must be investigated via the correlation ID with Microsoft support, but they are not due to a documented, intentional distinction in how long-running processes are treated.


    References:

    0 comments No comments

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.