I am writing this primarily as a beginners guide but also to serve as a dump of all my own knowledge so when I inevitably forget this, I can come back and reference it! Ever since Microsoft introduced their two-factor requirements for MSPs this year, I’ve been struggling to come up with a comprehensive solution that worked for me from start to finish. I think this is partially because it’s a multi-stage problem, and in my experience it’s often the case that Microsoft’s own examples either don’t work well or don’t work properly when utilising delegated partner permissions.

Before I start with this post, let me be clear that what I am about to suggest is not necessarily the right way or the best way to achieve this. I am not omniscient, this is simply my best interpretation based on what I know and I absolutely welcome people’s input in to alternate ways to approach this as well as pointing out any errors I may have made here!

I intend this to be Part 1 in a series of articles designed to help specifically MSPs utilise PowerShell and Office 365 to their advantage.

What are delegated admin privileges?

Simply put, it’s a way of utilising your own credentials to access things in your clients tenant. That way, you only have one set of credentials that you need to remember, and with it you can manage all of your clients without having to log on with a specific global admin account. It sounds simple in theory, but in reality you don’t get full access. Access to a number of security related settings is restricted and certain things don’t work properly. You can find out how to set this up at https://docs.microsoft.com/en-us/partner-center/customers_revoke_admin_privileges

Can I not just use my delegated access in PowerShell scripts?

Yes and no. This is where it gets confusing. It differs for a number of Microsoft PowerShell modules. When you are utilising PowerShell to connect your tenants, most frequently with some sort of Connect- verbage, to be able to access your underlying client you need to specify the tenant id of that particular client. To understand the difficulty, you have to understand the modules that are available and also understand why they are different in certain circumstances.

Powershell Module: MSOnline

Documentation: https://docs.microsoft.com/en-us/powershell/module/msonline/?view=azureadps-1.0

Out of all of the modules, I find this the easiest to deal with. It can easily be used interactively to loop through your client tenants. Connecting interactively is easy:

Running this will pop up a modern authentication prompt that supports 2FA, where you can login.

It will appear that nothing will happen, but in-fact you are now authenticated to the MSOnline module and you’re ready to run commands. You’ll notice that if you run

You get an output containing information about your own partner tenant:

Handy, but not amazing. What if we could get that information out for all tenants? Run the following command:


You will see it outputs a list of Tenant IDs. We can utilise these.

If you run this, you will see it output all information for all companies! This is how the -TenantID switch works. Once you are authenticated, you can utilise it to get information about that particular tenant.

At this point, it’s just a case of utilising PowerShell to clean up the output. Step 1 is putting all this information in one place so we can export it in a reasonable format.

Final Script: Output information about Clients with AD Sync Enabled including Last Sync Time

Boom! As simple as that you now have a report that tells you whether AD Sync is on for all of your clients, including the last time they synced. It is ALWAYS worth inspecting each object in PowerShell to see what else you can extract. In the same session for example, type the following:

Biggest Tip: You’ll get a grid popup showing all the information that’s available. You will likely find doing this that you come across something worthwhile. I always do this when extracting data from anything and I often find additional information that I think would be suitable

Utilising the same methods, lets investigate Get-MSOLUser.


This is the command I use most frequently for extracting information out of Office 365. To see the wealth of information at your fingertips run:

So much information!! Lets see what we can do..

Final Script: Output information about all users and their licensing

This follows exactly the same structure, but it utilises a bit of PowerShell when creating the hash table to make sure the content displays how I want it to. Getting a simple value out of this can be just as simple as $User.SignInName but sometimes it’s not as easy as that. Take the user licenses for example, if you were just output $User.Licenses it would look like this:

Not really helpful for an output. Each box represents a license, and as you can see there is a lot of information about each license.

If we delve in to AccountSKU with $User.Licenses.AccountSKU

Again, not helpful but we’re making progress. The SkuPartNumber looks perfect. We can get that with $User.Licenses.AccountSKU.SkuPartNumber

That’s great! Well, it nearly is. There are two results there. To get them in to one we need to join them.

($User.Licenses.AccountSKU.SkuPartNumber) -join “,”

Now we have an output that will work well in a spreadsheet or CSV. Extracting data from PowerShell is an iterative process, as you can see above.

Big Tip: Utilise Visual Studio Code with Debugging and breakpoints to stop the script at certain parts and see a list of all information on the left hand side when debugging.