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: <PII: Moderator removed>","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

2 answers

Sort by: Most helpful
  1. Anonymous
    2026-03-12T23:35:48.5+00:00

    Please understand that our forum is a public platform, and we will modify your question to cover the personal information in the description. Kindly ensure that you hide these personal or organization information next time you post error or some information to protect personal data.

    Dear @Daniel Browne,

    Welcome to Microsoft Q&A Forum!

    Thank you for your detailed explanation and for sharing your observations. I understand how confusing this behavior can be, especially when the same script works in one scenario but fails in another.

    Based on Microsoft’s official documentation for application‑based authentication in the Teams PowerShell module, I would like to clarify how authorization is evaluated and what may cause the 40301 (“You are not authorized to perform this action”) error you are seeing.

    1.How authorization works with app‑only authentication:

    When using application‑based (certificate) authentication, authorization is not determined by the local account that runs PowerShell, but by the Microsoft Entra application (service principal) that is used to connect via Connect‑MicrosoftTeams.

    2.According to Microsoft’s documentation:

    • The Teams PowerShell session uses the directory roles assigned to the application (for example, Teams Administrator or Global Administrator) to configure RBAC.
    • Required Microsoft Graph API permissions must also be assigned and admin‑consented, such as Organization.Read.All for *-Cs cmdlets.
    • If these roles or permissions are missing or incomplete, write operations (such as New‑CsTeamsMeetingPolicy or Set‑CsTeamsMeetingPolicy) will be blocked, even though some read‑only commands may still work.

    Official reference: Application-based authentication in Teams PowerShell Module

    User's image

    3.Why this is important to verify:

    If any of the required roles or permissions described in the article were not assigned, the behavior you would typically see is:

    • Get‑Cs* cmdlets may succeed
    • New‑Cs* / Set‑Cs* cmdlets return 40301 (Forbidden)
    • This is expected when the application is not fully authorized.

    4.How this applies to your case:

    Since you mentioned that the same application, certificate, and script succeed when run in a one‑shot PowerShell process, this strongly suggests that:

    • The application does have the required roles and permissions assigned correctly
    • The local account running PowerShell is not a factor in authorization

    For completeness, I would still recommend confirming that the application configuration fully matches the requirements in the Microsoft article, in particular:

    • The application is assigned a Teams Administrator (or Global Administrator) directory role
    • Organization.Read.All is present under Microsoft Graph API permissions and admin consent has been granted
    • No unnecessary permissions (such as “Skype and Teams Tenant Admin API”) were added, as this may cause failures

    Finally, I would like to give you a summary:

    • Authorization is evaluated entirely based on the application’s roles and permissions in Microsoft Entra ID.
    • Missing or incomplete application permissions can result in 40301 errors for policy creation or update commands.
    • Since your command succeeds in a fresh PowerShell session, this indicates the application configuration is likely correct, and the remaining difference is related to how the session is being executed.

    Also, I found a partially similar behavior that you can consult as well: https://help.duo.com/s/article/3893?language=en_US

    Note: This information is provided as a convenience to you. This site is not controlled by Microsoft, and Microsoft cannot make any representations regarding the quality, safety, or suitability of any software or information found there. Please ensure that you fully understand the risks before using any suggestions from the above link.

    I hope this information can give you some insights in this case and you can also take a look in the answer of Q&A Assist AI to see if they can give you any helpful information.


    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. 


  2. 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:

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.