Assign per-user Skype for Business Online policies with PowerShell for Microsoft 365

This article applies to both Microsoft 365 Enterprise and Office 365 Enterprise.

Using PowerShell for Microsoft 365 is an efficient way to assign per-user communication settings with Skype for Business Online policies.

Prepare to run the PowerShell commands

Use these instructions to get set up to run the commands (skip the steps you have already completed):


Skype for Business Online Connector is currently part of the latest Teams PowerShell module. If you're using the latest Teams PowerShell public release, you don't need to install the Skype for Business Online Connector.

  1. Install the Teams PowerShell module.

  2. Open a Windows PowerShell command prompt and run the following commands:

    Import-Module MicrosoftTeams

    When prompted, enter your Skype for Business Online administrator account name and password.

Updating external communication settings for a user account

Suppose you want to change external communication settings on a user account. For example, you want to allow Alex to communicate with federated users (EnableFederationAccess is equal to True) but not with Windows Live users (EnablePublicCloudAccess equals False). To do that, you need to do two things:

  1. Find an external access policy that meets our criteria.

  2. Assign that external access policy to Alex.

How do you determine which external access policy to assign Alex? The following command returns all the external access policies where EnableFederationAccess is set to True and EnablePublicCloudAccess is set to False:

Get-CsExternalAccessPolicy -Include All| Where-Object {$_.EnableFederationAccess -eq $True -and $_.EnablePublicCloudAccess -eq $False}

Unless you have created any custom instances of ExternalAccessPolicy, that command returns one policy that meets our criteria (FederationOnly). Here is an example:

Identity                          : Tag:FederationOnly
Description                       :
EnableFederationAccess            : True
EnableXmppAccess                  : False
EnablePublicCloudAccess           : False
EnablePublicCloudAudioVideoAccess : False
EnableOutsideAccess               : True

Now that you know which policy to assign to Alex, we can assign that policy by using the Grant-CsExternalAccessPolicy cmdlet. Here is an example:

Grant-CsExternalAccessPolicy -Identity "Alex Darrow" -PolicyName "FederationOnly"

Assigning a policy is pretty simple: you simply specify the Identity of the user and the name of the policy to be assigned.

And when it comes to policies and policy assignments, you're not limited to working with user accounts one a time. For example, suppose you need a list of all the users who are allowed to communicate with federated partners and with Windows Live users. We already know that those users have been assigned the external user access policy FederationAndPICDefault. Because we know that, you can display a list of all those users by running one simple command. Here is the command:

Get-CsOnlineUser -Filter {ExternalAccessPolicy -eq "FederationAndPICDefault"} | Select-Object DisplayName

In other words, show us all the users where the ExternalAccessPolicy property is set to FederationAndPICDefault. (And, in order to limit the amount of information that appears onscreen, use the Select-Object cmdlet to display show us only each user's display name.)

To configure all our user accounts to use that same policy, use this command:

Get-CsOnlineUser | Grant-CsExternalAccessPolicy "FederationAndPICDefault"

This command uses Get-CsOnlineUser to return a collection of all the users who have been enabled for Lync, then sends all that information to Grant-CsExternalAccessPolicy, which assigns the FederationAndPICDefault policy to each and every user in the collection.

As an additional example, suppose you've previously assigned Alex the FederationAndPICDefault policy and now you've changed your mind and would like him to be managed by the global external access policy. You can't explicitly assign the global policy to anyone. Instead, the global policy is used for a given user if no per-user policy is assigned to that user. Therefore, if we want Alex to be managed by the global policy, you need to unassign any per-user policy previously assigned to him. Here is an example command:

Grant-CsExternalAccessPolicy -Identity "Alex Darrow" -PolicyName $Null

This command sets the name of the external access policy assigned to Alex to a null value ($Null). Null means "nothing". In other words, no external access policy is assigned to Alex. When no external access policy is assigned to a user, that user then gets managed by the global policy.

Managing large numbers of users

To manage large numbers of users (1000 or more), you need to batch the commands via a script block using the Invoke-Command cmdlet. In previous examples, each time a cmdlet is executed, it must set up the call and then wait for the result before sending it back. When using a script block, this allows the cmdlets to be executed remotely, and once completed, send the data back.

$s = Get-PSSession | Where-Object { ($.ComputerName -like '*' -or $.Computername -eq '') -and $.State -eq 'Opened' -and $.Availability -eq 'Available' }

$users = Get-CsOnlineUser -Filter { ClientPolicy -eq $null } -ResultSize 500

$batch = 50
$filter = ''
$total = $users.Count
$count = 0
    $users | ForEach-Object {
    $upn = $_.UserPrincipalName
    $filter += "(UserPrincipalName -eq '$upn')"
    if (($batch -eq 0) -or ($count -eq $total)) {
        Invoke-Command -Session $s -ScriptBlock {param($f) Get-CsOnlineUser -filter $f | Grant-CsClientPolicy -PolicyName "ClientPolicyNoIMURL" -Passthru | Grant-CsExternalAccessPolicy -PolicyName "FederationAndPICDefault"} -ArgumentList $filterSB

        # Reset
        $batch = 50
        $filter = ''
    } else {
        $filter += " -or "

This will find 500 users at a time who do not have a client policy. It will grant them the client policy "ClientPolicyNoIMURL" and the external access policy "FederationAndPicDefault". The results are batched into groups of 50 and each batch of 50 is then sent to the remote machine.

See also

Manage Skype for Business Online with PowerShell

Manage Microsoft 365 with PowerShell

Getting started with PowerShell for Microsoft 365