Category Archives: Skype Online

The mysterious X-MS-Forest header

When working with the api.interfaces.records.teams.microsoft.com API, I noticed that the MS portal uses an X-MS-Forest header.

At first, ignoring this went fine as doing GET calls to this api didn’t seem to require it. But, of course the moment I wanted more, it suddenly WAS required (PUT/POST).

The question was; how does the portal determine the value for this header and how do we replicate that? Well, that wasn’t difficult: apparently a call to api.interfaces.records.teams.microsoft.com/Teams.Tenant/tenants suffices and returns the value for the X-MS-Forest header for the tenant identified in your token. Example:

    $headers = Get-GraphToken -tenantid $tenantId -scope "https://api.interfaces.records.teams.microsoft.com/user_impersonation"
    #get the correct forest
    $tenantInfo = Invoke-RestMethod -Method GET -uri "https://api.interfaces.records.teams.microsoft.com/Teams.Tenant/tenants" -UseBasicParsing -ContentType "application/json" -Headers $headers
    #add the X-MS-Forest header (required) for subsequent calls
    $headers["X-MS-Forest"] = $tenantInfo.serviceDiscovery.Headers.'X-MS-Forest'

Excluding Skype for Business from ADFS MFA

When you want to use Skype for Business Online, but are using an on premises ADFS implementation and require MFA for all logins, Skype for Business will fail to authenticate. It cannot handle the ADFS Multi-Factor challenge because MFA is not yet supported for Office 365 Online Skype for Business tenants.

To exempt Skype for Business from your ADFS RPT, use the following claims rule


$rp = Get-AdfsRelyingPartyTrust -name "Microsoft Office 365 Identity Platform"

Set-AdfsRelyingPartyTrust –TargetRelyingParty $rp –AdditionalAuthenticationRules 'NOT EXISTS([Type == "http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-user-agent", Value =~ "(?i)skype"]) && NOT EXISTS([Type=="http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-user-agent", Value =~ "(?i)ACOMO"]) && NOT EXISTS([Type=="http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-user-agent", Value =~ "(?i)lync"]) => issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", Value = "http://schemas.microsoft.com/claims/multipleauthn");'

*With thanks to the IT team at NHTV 😉

O365Datacleaner released

The first public version of the O365Datacleaner has been released.

This script can make any given path to a folder/fileshare fully compliant with Onedrive for Business or Sharepoint Online standards, without user interaction. Including path depth resolution and intelligent renaming or moving of files and folders.

A bulk version of this tool is available for free upon request and will also be posted later.

Automating remote mailbox creation in an Exchange 2010/2013 and Office 365 hybrid setup

In organisations that have moved to Office 365, or are moving to Office 365 while using a hybrid setup with an on-premises Exchange 2010, 2013 or 2016 server and/or Lync/Skype, your helpdesk tools and scripts need to be adjusted.

While previously, you would provision your account in Active Directory, the mailbox on the onpremises Exchange Server and voip functionality on the Lync/Skype server, after your migration, you no longer need to provision mailboxes or lync accounts on premises. After a user has been migrated to Office 365, his ‘user type’ in the Exchange on premises server is ‘Remote Mailbox’. But for new users, this is not set automatically.

If you’re using scripting or tools like ADManager, you can use some simple Powershell commands to set the correct properties on a newly created user.

Configure and run below script Continue reading Automating remote mailbox creation in an Exchange 2010/2013 and Office 365 hybrid setup

Get-CsPowerShellEndpoint : The remote server returned an error: (406) Not Acceptable

When you’re attempting to administer Skype for Business Online or Lync Online, you’re likely going to use the Lync Online Module for Windows Powershell, or the Skype for Business Online Windows Powershell Module.

When I ran this for a customer that has two federated domains, I received an error:


$env:PSModulePath += ";C:\Program Files\Common Files\Skype for Business Online\Modules"
ipmo SkypeOnlineConnector
$session = New-CsOnlineSession -credential $cred
Get-CsPowerShellEndpoint : The remote server returned an error: (406) Not Acceptable.
At C:\Program Files\Common Files\Skype for Business Online\Modules\SkypeOnlineConnector\SkypeOnlineConnectorStartup.psm1:94 char:26
+ ... $targetUri = Get-CsPowerShellEndpoint -TargetDomain $adminDomain
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-CsPowerShellEndpoint], WebException
+ FullyQualifiedErrorId : System.Net.WebException,Microsoft.Rtc.Management.OnlineConnector.GetPowerShellEndpointCmdlet

Messing around a bit, I discovered that it did work for another administrator, it ended up being the UPN suffix. When I changed the login domain (UPN) of the user that couldn’t log in to the DEFAULT domain in Office 365 instead of one of the extra domains and waited a while until it was propagated to Skype for Business Online, I could log in without issues.