M365 Licensing With Graph PowerShell Module Part 1

Posted on Jul 3, 2025

You can ask just about anyone. Microsoft’s myriad licenses and licensing models for their myriad products is a quizzical quagmire that conquers most quixotic questers that challenge its mystery. There are consultancies who make significant income sending their MS licensing experts to clients to help sort out that knot. My look is going to be focused on the fairly standard M365 licenses and some situations one can get into.

Table Of Contents

Woodward and Bernstein would read this section

It’s the slog. It’s the boring part. There’s no code here. This is some background. Microsoft has a number of plans that can be right for your business. Seriously, though, make sure to talk to your account reps. In smaller orgs, or organizations with fairly flat and standardized types of people, this usually isn’t too difficult. I don’t work in an organization like that. We’ve got hundreds of thousands of users that all occupy various niches of status.

And how does that make you feel

We have a mix of E1 and E5, and something like 95 groups that have licenses assigned to them using the new and “easier” group-based licensing. I say “new” because I’ve been in this space since before it was standardized and, in using the logic that was already extant to manage all of these users on-prem, it was actually a little easier to deal with back then.

License conflicts can be show stoppers and licenses may not be applied at all, at times. Yes, this type of work lived in my wheelhouse. No, I don’t want to elaborate. Suffice it to say that this work is being democratized with further participation of our latest IdP but the licensing component is not in place. We get licensing tickets regularly and I’d… prefer not to. So let’s take a deep dive.

Where in the world is (all this license information)

Alright, gumshoe, we need to start by seeing. By gathering information. By compiling. By correlating. It’s a process. But that’s good, because people like process. We can add some snappy cuts and use environmental storytelling to tell a compelling story of your journey through my journey. We won’t. We won’t even film it. But we could. Anyway, there’s some ground work to lay down.

Connect-MGGraph is our friend

We need to Connect-MGGraph and, what we’re looking for here specifically are the permissions User.Read.All, LicenseAssignment.Read.All, and Group.Read.All. These permissions, surprising no one, will allow us to read all information about users, license assignments, and groups. And we’ll use each one. Altogether it will look like this:

# The standard look
Connect-MgGraph -Scopes "User.Read.All", "LicenseAssignment.Read.All", "Group.Read.All"

# Sometimes I like to use UseDeviceAuthentication because it's a process for me to log in
Connect-MgGraph -Scopes "User.Read.All", "LicenseAssignment.Read.All", "Group.Read.All" -UseDeviceAuthentication

You can also check the official documentation to see the various ways that you can connect. The important part is that you, or your app, or your managed identity, have those permissions. If you run into issues, you may need to be specifying your tenant.

With trembling hands I made a tiny command

You’d think that using the very obvious command of Get-MgUser would give us what we’re looking for. You would think that because there is a field in the returned object AssignedLicenses and, in my case, it’s wonderfully blank. Lovely. But where there is a will, there is a way. So we dig deeper and don’t let the filled-in passages deter us. Like Howard Carter we keep going and we find that Get-MgUserLicenseDetail exists. So, uncovering that documentation and it looks like it’s going to do what we need.

You’ll note from the docs page that we can use our lovely Entra User ID to get the details for the licenses assigned to a user. And what we get for our trouble is another two IDs: an Id, that is not particularly helpful for our purposes but represents this specific assignment, and a SkuId which is much more helpful. But it’s also another lookup. Fun stuff. If we’re trying to report on a large number of users, we would probably want to keep the list of SKUs in memory. Enter Get-MgSubscribedSku.

$skus = Get-MgSubscribedSku
$skuHash = @{}
foreach ($sku in $skus) {
    $skuHash[$sku.SkuId] = $sku
}

Putting it together

Ok. We’ve got a few things going for us now. Let’s slap it together and see if we can make something out of it. It’s likely that I won’t be hooking all these pieces together for each post, but I’ll leave it with a simple example. Use it for inspiration.

$output = @()
# Get your users. Probably not like this.
$users = Get-MgUser -All # There's nuance here... 
foreach ($user in $users) {
    $assignedLicenses = Get-MgUserLicenseDetail -UserId $user.Id
    foreach ($assignedLicense in $assignedLicenses) {
        $license = $skuHash[$licenseDetail.SkuId]
        $output += [PSCustomObject]@{
            DisplayName = $user.DisplayName
            UPN = $user.UserPrincipalName
            SkuPartNumber = $license.SkuId
            SkuId = $license.SkuId
        }
    }
}
$output | format-list

So with this primitive example you may have enough to set you on the right path. Anyone who has worked MS Graph for any length of time has found that there are things that have changed and there are gaps in knowledge that you may need to cross. Maybe this is a little bit of a boost but there will be at least one follow up to this. Writing and improving and adding features and optimizing scripts and reporting can be a bit of a rabbit hole.

Hi, this post was checked with vale which is a content-aware linter. It was checked using the Microsoft style as well as some rules that I made. A summary of those results is below. More details as to how this was put together check out this post. This post had: 4 errors, 50 warnings and 10 suggestions For details on the linting of this post
 ./content/posts/m365-licensing-with-graph-ps-module.md
 1:1     suggestion  You averaged 1.05 complex       marktoso.Kiss            
                     words per sentence                                       
 9:322   warning     Use first person (such as       Microsoft.FirstPerson    
                     'My') sparingly.                                         
 9:342   suggestion  'be focused' looks like         Microsoft.Passive        
                     passive voice.                                           
 9:360   warning     Consider removing 'fairly'.     Microsoft.Adverbs        
 13:288  warning     Consider removing 'Seriously'.  Microsoft.Adverbs        
 13:386  warning     Consider removing 'fairly'.     Microsoft.Adverbs        
 13:465  warning     Use first person (such as ' I   Microsoft.FirstPerson    
                     ') sparingly.                                            
 13:509  warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'We'.                           
 16:1    warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'We'.                           
 16:1    error       Use 'we've' instead of 'We      Microsoft.Contractions   
                     have'.                                                   
 16:143  warning     Use first person (such as ' I   Microsoft.FirstPerson    
                     ') sparingly.                                            
 16:144  suggestion  Try to keep sentences short (<  Microsoft.SentenceLength 
                     30 words).                                               
 16:204  suggestion  'was standardized' looks like   Microsoft.Passive        
                     passive voice.                                           
 16:279  warning     Consider using 'all' instead    Microsoft.Wordiness      
                     of 'all of'.                                             
 18:61   suggestion  'be applied' looks like         Microsoft.Passive        
                     passive voice.                                           
 18:122  warning     Use first person (such as       Microsoft.FirstPerson    
                     'my') sparingly.                                         
 18:140  warning     Use first person (such as ' I   Microsoft.FirstPerson    
                     ') sparingly.                                            
 18:204  suggestion  'being democratized' looks      Microsoft.Passive        
                     like passive voice.                                      
 18:253  warning     Try to avoid using              Microsoft.We             
                     first-person plural like                                 
                     'our'.                                                   
 18:290  suggestion  Consider using 'part' instead   Microsoft.ComplexWords   
                     of 'component'.                                          
 18:300  error       Use 'isn't' instead of 'is      Microsoft.Contractions   
                     not'.                                                    
 18:317  warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'We'.                           
 18:342  warning     Consider removing 'regularly'.  Microsoft.Adverbs        
 18:359  warning     In general, don't use an        Microsoft.Ellipses       
                     ellipsis.                                                
 18:381  warning     Try to avoid using              Microsoft.We             
                     first-person plural like                                 
                     'let's'.                                                 
 21:19   warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'we'.                           
 21:165  warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'We'.                           
 21:279  warning     Use first person (such as       Microsoft.FirstPerson    
                     'my') sparingly.                                         
 21:291  warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'We'.                           
 21:301  warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'We'.                           
 21:328  warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'we'.                           
 23:24   warning     Try to avoid using              Microsoft.We             
                     first-person plural like                                 
                     'our'.                                                   
 24:1    warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'We'.                           
 24:38   warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'we'.                           
 24:182  error       More than 3 commas!             marktoso.TresComas       
 24:208  suggestion  Verify your use of 'allow'      Microsoft.Vocab          
                     with the A-Z word list.                                  
 24:214  warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'us'.                           
 24:291  warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'we'.                           
 34:25   warning     Use first person (such as ' I   Microsoft.FirstPerson    
                     ') sparingly.                                            
 35:28   warning     Consider removing 'very'.       Microsoft.Adverbs        
 35:78   warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'us'.                           
 35:86   warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'we'.                           
 35:204  warning     Use first person (such as       Microsoft.FirstPerson    
                     'my') sparingly.                                         
 35:218  warning     Consider removing               Microsoft.Adverbs        
                     'wonderfully'.                                           
 35:295  warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'we'.                           
 35:375  warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'we'.                           
 35:393  warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'we'.                           
 35:643  warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'we'.                           
 37:37   warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'we'.                           
 37:48   warning     Try to avoid using              Microsoft.We             
                     first-person plural like                                 
                     'our'.                                                   
 37:129  suggestion  Try to keep sentences short (<  Microsoft.SentenceLength 
                     30 words).                                               
 37:138  warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'we'.                           
 37:149  warning     Try to avoid using              Microsoft.We             
                     first-person plural like                                 
                     'our'.                                                   
 37:194  error       Use 'that's' instead of 'that   Microsoft.Contractions   
                     is'.                                                     
 37:231  warning     Try to avoid using              Microsoft.We             
                     first-person plural like                                 
                     'our'.                                                   
 37:373  warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'we'.                           
 37:399  warning     Consider using 'many' instead   Microsoft.Wordiness      
                     of 'a large number of'.                                  
 37:424  warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'we'.                           
 47:5    warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'We'.                           
 47:38   warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'us'.                           
 47:46   warning     Try to avoid using              Microsoft.We             
                     first-person plural like                                 
                     'Let's'.                                                 
 47:80   warning     Try to avoid using              Microsoft.We             
                     first-person plural like 'we'.                           
 47:129  warning     Use first person (such as ' I   Microsoft.FirstPerson    
                     ') sparingly.                                            
 66:82   suggestion  Try to keep sentences short (<  Microsoft.SentenceLength 
                     30 words).                                               
 69:21   suggestion  'was checked' looks like        Microsoft.Passive        
                     passive voice.                                           
 69:127  suggestion  'was checked' looks like        Microsoft.Passive        
                     passive voice.                                           
 69:165  suggestion  Verify your use of 'as well     Microsoft.Vocab          
                     as' with the A-Z word list.                              
 69:191  warning     Use first person (such as ' I   Microsoft.FirstPerson    
                     ') sparingly.                                            
 69:265  suggestion  'was put' looks like passive    Microsoft.Passive        
                     voice.                                                   

4 errors, 51 warnings and 14 suggestions in 1 file.