Remove-MgUser – Office 365 for IT Pros https://office365itpros.com Mastering Office 365 and Microsoft 365 Thu, 11 Jul 2024 04:46:13 +0000 en-US hourly 1 https://i0.wp.com/office365itpros.com/wp-content/uploads/2024/06/cropped-Office-365-for-IT-Pros-2025-Edition-500-px.jpg?fit=32%2C32&ssl=1 Remove-MgUser – Office 365 for IT Pros https://office365itpros.com 32 32 150103932 The Right Way to Replace the Remove-SPOExternalUser Cmdlet https://office365itpros.com/2024/07/11/remove-spoexternaluser-cmdlet/?utm_source=rss&utm_medium=rss&utm_campaign=remove-spoexternaluser-cmdlet https://office365itpros.com/2024/07/11/remove-spoexternaluser-cmdlet/#respond Thu, 11 Jul 2024 04:00:00 +0000 https://office365itpros.com/?p=65499

Microsoft Will Remove-SPOExternalUser Between July 29 and August 9

Message center notification MC806103 (27 June 2024) reports the deprecation of the Remove-SPOExternalUser cmdlet from the SharePoint Online management PowerShell module. Microsoft suggests that administrators replace the cmdlet with the Remove-AzureADUser cmdlet, which is a perfectly reasonable strategy if only the cmdlet isn’t part of the retired and soon-to-be deprecated AzureAD module.

Between July 29. 2024 and August 9, 2024, Microsoft will disable the Remove-SPOExternalUser cmdlet. When the block arrives in a tenant, attempts to run the cmdlet will be greeted with:

To streamline scope and permissions for external users, enhance access management, and strengthen our security posture, this cmdlet has been deprecated. Alternatively, please use the Remove-AzureADUser cmdlet in Microsoft Entra ID for user management.”

Microsoft 365 is so Large that No One Understands Everything

MC806103 is a classic example of Microsoft being such a large organization that no one knows what’s happening across the board, or even what’s happening within Microsoft 365. In this case, the SharePoint Online people want to deprecate the Remove-SPOExternalUser cmdlet. That’s a good idea because the cmdlet has low usage (I don’t think I have ever used it) and doesn’t really make sense inside the Microsoft 365 ecosystem where external access for applications like SharePoint Online is now governed using guest accounts. It makes perfect sense to remove overlapping or conflicting features and replace them with what you’d consider a component that’s closer to the core.

Entra ID is the directory of record for Microsoft 365. Individual workloads like SharePoint Online have their own directory, but everything flows back to Entra ID. Replacing the SharePoint Online cmdlet with an Entra ID cmdlet is the right thing to do. The problem is that the program manager in charge of making the transition obviously doesn’t know that the Entra ID team has been trying to deprecate the AzureAD and AzureADPreview modules since 2020. For the last few years, Microsoft has conducted an ongoing campaign to move tenants off these modules to use the Microsoft Graph PowerShell SDK.

What makes this laughable is that Microsoft launched the Entra PowerShell module in preview on June 27 in the hope that a dedicated Entra module (built on top of the Microsoft Graph PowerShell SDK) would help the remaining customers who have scripts that use the AzureAD and AzureADPreview modules to move to a modern platform. Obviously, whoever wrote MC806103 had no idea that this development was in train.

The Right Way to Replace Remove-ExternalSPOUser

The Get-SPOExternalUser cmdlet reports the external users registered for a SharePoint Online tenant. The last time I discussed its use, I observed that the Get-SPOExternalUser cmdlet is an odd cmdlet in some ways, but it does generate a list of external users from the SharePoint directory.

An external user record looks like:

RunspaceId    : 9630573b-c675-4697-a029-72d535e48613
Email         : charu.someone@microsoft.com
DisplayName   : Charu Someone
UniqueId      : 100320009C9C6789
AcceptedAs    : charsomeone@microsoft.com
WhenCreated   : 20/02/2020 19:45:02
InvitedBy     :
LoginName     :
IsCrossTenant : False

Remove-SPOExternalUser works like this:

Remove-SPOExternalUser -UniqueIDs ($User).UniqueId -Confirm:$false
Successfully removed the following external users
100320009C9C6789

The cmdlet removes the external user entry from SharePoint Online. It also removes the matching guest account, if one exists, from Entra ID. In my tenant there are quite a few lingering external accounts that don’t have matching Entra ID guest accounts. These accounts are just another form of digital debris that needs to be cleaned up.

The right way to remove an external account is to use the Remove-MgUser cmdlet from the Microsoft Graph PowerShell SDK:

$User = Get-MgUser -filter "mail eq 'andrew@proton.me"
Remove-MgUser -UserId $User.Id

Or, if you decide to use the preview Entra module:

$User = Get-EntraUser -SearchString 'AdamP@contoso.com'
Remove-EntraUser -ObjectId $User.Id

Either cmdlet has a much longer future ahead of it than the Remove-AzureADUser cmdlet has. In both cases, SharePoint Online synchronizes with Entra ID and removes the matching external user record.

It’s Just Hard to Keep Up

I don’t blame the individual program manager responsible for MC806103. It’s hard to keep up with everything that goes on within Microsoft 365 and all too easy to assume that a solution that works (for now) is the right long-term recommendation. Perhaps Microsoft needs a clearing house to cross-check dependencies outside the control of an individual development group before they publish information to customers?


So much change, all the time. It’s a challenge to stay abreast of all the updates Microsoft makes across the Microsoft 365 ecosystem. Subscribe to the Office 365 for IT Pros eBook to receive monthly insights into what happens, why it happens, and what new features and capabilities mean for your tenant.

]]>
https://office365itpros.com/2024/07/11/remove-spoexternaluser-cmdlet/feed/ 0 65499
Reporting Group Membership for Azure AD Guest Accounts with the Microsoft Graph PowerShell SDK https://office365itpros.com/2023/01/18/old-azure-ad-guest-accounts/?utm_source=rss&utm_medium=rss&utm_campaign=old-azure-ad-guest-accounts https://office365itpros.com/2023/01/18/old-azure-ad-guest-accounts/#comments Wed, 18 Jan 2023 01:00:00 +0000 https://office365itpros.com/?p=58742

Finding Azure AD Guest Accounts in Microsoft 365 Groups

The article explaining how to report old guest accounts and their membership of Microsoft 365 Groups (and teams) in a tenant is very popular and many people use its accompanying script. The idea is to find guest accounts above a certain age (365 days – configurable in the script) and report the groups these guests are members of. Any old guest accounts that aren’t in any groups are candidates for removal.

The script uses an old technique featuring the distinguished name of guest accounts to scan for group memberships using the Get-Recipient cmdlet. The approach works, but the variation of values that can exist in distinguished names due to the inclusion of characters like apostrophes and vertical lines means that some special processing is needed to make sure that lookups work. Achieving consistency in distinguished names might be one of the reasons for Microsoft’s plan to make Exchange Online mailbox identification more effective.

In any case, time moves on and code degrades. I wanted to investigate how to use the Microsoft Graph PowerShell SDK to replace Get-Recipient. The script already uses the SDK to find Azure AD guest accounts with the Get-MgUser cmdlet.

The Graph Foundation

Graph APIs provide the foundation for all SDK cmdlets. Graph APIs provide the foundation for all SDK cmdlets. The first thing to find is an appropriate API to find group membership. I started off with getMemberGroups. The PowerShell example for the API suggests that the Get-MgDirectoryObjectMemberGroup cmdlet is the one to use. For example:

$UserId = (Get-MgUser -UserId Terry.Hegarty@Office365itpros.com).id 
[array]$Groups = Get-MgDirectoryObjectMemberGroup  -DirectoryObjectId $UserId -SecurityEnabledOnly:$False

The cmdlet works and returns a list of group identifiers that can be used to retrieve information about the groups that the user belongs to. For example:

Get-MgGroup -GroupId $Groups[0] | Format-Table DisplayName, Id, GroupTypes

DisplayName                     Id                                   GroupTypes
-----------                     --                                   ----------
All Tenant Member User Accounts 05ecf033-b39a-422c-8d30-0605965e29da {DynamicMembership, Unified}

However, because Get-MgDirectoryObjectMemberGroup returns a simple list of group identifiers, the developer must do extra work to call Get-MgGroup for each group to retrieve group properties. Not only is this extra work, calling Get-MgGroup repeatedly becomes very inefficient as the number of guests and their membership in groups increase.

Looking Behind the Scenes with Graph X-Ray

The Azure AD admin center (and the Entra admin center) both list the groups that user accounts (tenant and guests) belong to. Performance is snappy and it seemed unlikely that the code used was making multiple calls to retrieve the properties for each group. Many of the sections in these admin centers use Graph API requests to fetch information, and the Graph X-Ray tool reveals those requests. Looking at the output, it’s interesting to see that the admin center uses the beta Graph endpoint with the groups memberOf API (Figure 1).

Using the Graph X-Ray tool to find the Graph API for group membership

Azure AD Guest Accounts
Figure 1: Using the Graph X-Ray tool to find the Graph API for group membership

We can reuse the call used by the Azure AD center to create the query (containing the object identifier for the user account) and run the query using the SDK Invoke-MgGraphRequest cmdlet. One change made to the command is to include a filter to select only Microsoft 365 groups. If you omit the filter, the Graph returns all the groups a user belongs to, including security groups and distribution lists. The group information is in an array that’s in the Value property returned by the Graph request. For convenience, we put the data into a separate array.

$Uri = ("https://graph.microsoft.com/beta/users/{0}/memberOf/microsoft.graph.group?`$filter=groupTypes/any(a:a eq 'unified')&`$top=200&$`orderby=displayName&`$count=true" -f $Guest.Id)
[array]$Data = Invoke-MgGraphRequest -Uri $Uri
[array]$GuestGroups = $Data.Value

Using the Get-MgUserMemberOf Cmdlet

The equivalent SDK cmdlet is Get-MgUserMemberOf. To return the set of groups an account belongs to, the command is:

[array]$Data = Get-MgUserMemberOf -UserId $Guest.Id -All
[array]$GuestGroups = $Data.AdditionalProperties

The format of returned data marks a big difference between the SDK cmdlet and the Graph API request. The cmdlet returns group information in a hash table in the AdditionalProperties array while the Graph API request returns a simple array called Value. To retrieve group properties from the hash table, we must enumerate through its values. For instance, to return the names of the Microsoft 365 groups in the hash table, we do something like this:

[Array]$GroupNames = $Null
ForEach ($Item in $GuestGroups.GetEnumerator() ) {
   If ($Item.groupTypes -eq "unified") { $GroupNames+= $Item.displayName }
}
$GroupNames= $GroupNames -join ", "

SDK cmdlets can be inconsistent in how they return data. It’s just one of the charms of working with cmdlets that are automatically generated from code. Hopefully, Microsoft will do a better job of ironing out inconsistencies when they release V2.0 of the SDK sometime later in 2023.

A Get-MgUserTransitiveMemberOf cmdlet is also available to return the membership of nested groups. We don’t need to do this because we’re only interested in Microsoft 365 groups, which don’t support nesting. The cmdlet works in much the same way:

[array]$TransitiveData = Get-MgUserTransitiveMemberOf -UserId Kim.Akers@office365itpros.com -All

The Script Based on the SDK

Because of the extra complexity in accessing group properties, I decided to use a modified version of the Graph API request from the Azure AD admin center. It’s executed using the Invoke-MgGraphRequest cmdlet, so I think the decision is justified.

When revising the script, I made some other improvements, including adding a basic assessment of whether a guest account is stale or very stale. The assessment is intended to highlight if I should consider removing these accounts because they’re obviously not being used. Figure 2 shows the output of the report.

Report highlighting potentially obsolete guest accounts
Figure 2: Report highlighting potentially obsolete Azure AD guest accounts

You can download a copy of the script from GitHub.

Cleaning up Obsolete Azure AD Guest Accounts

Reporting obsolete Azure AD guest accounts is nice. Cleaning up old junk from Azure AD is even better. The script generates a PowerShell list with details of all guests over a certain age and the groups they belong to. To generate a list of the very stale guest accounts, filter the list:

[array]$DeleteAccounts = $Report | Where-Object {$_.StaleNess -eq "Very Stale"}

To complete the job and remove the obsolete guest accounts, a simple loop to call Remove-MgUser to process each account:

ForEach ($Account in $DeleteAccounts) {
   Write-Host ("Removing guest account for {0} with UPN {1}" -f $Account.Name, $Account.UPN) 
   Remove-MgUser -UserId $Account.Id }

Obsolete or stale guest accounts are not harmful, but their presence slows down processing like PowerShell scripts. For that reason, it’s a good idea to clean out unwanted guests periodically.


Learn about mastering the Microsoft Graph PowerShell SDK and the Microsoft 365 PowerShell modules by subscribing to the Office 365 for IT Pros eBook. Use our experience to understand what’s important and how best to protect your tenant.

]]>
https://office365itpros.com/2023/01/18/old-azure-ad-guest-accounts/feed/ 2 58742
Basic User Account Management with the Microsoft Graph PowerShell SDK https://office365itpros.com/2022/03/24/entra-id-user-accounts-powershell/?utm_source=rss&utm_medium=rss&utm_campaign=entra-id-user-accounts-powershell https://office365itpros.com/2022/03/24/entra-id-user-accounts-powershell/#comments Thu, 24 Mar 2022 01:00:00 +0000 https://office365itpros.com/?p=54188

Preparing to Migrate Away from Old AzureAD cmdlets

Updated: 15 March, 2023

Manage Entra ID user accounts

I received a lot of reaction when I described Microsoft’s new deprecation schedule for the AzureAD and MSOL modules. In summary, you have until 30 March 2024 to update scripts which assign licenses to user accounts. After this, Microsoft will disable the cmdlets. The other cmdlets will continue working after Microsoft deprecates the modules. However, they’ll be out of support, which is not a good foundation for PowerShell scripts used to automate administrative processes, like managing Entra ID user accounts.

With time running out, it’s obvious that tenants need to inventory and upgrade scripts. One reaction I received was that there’s a dearth of information to help people who are less familiar with PowerShell and might have inherited ownership of some scripts. My response is that the community will publish examples over time, just like they did when Microsoft launched the AzureAD module in 2016 and the Exchange Online management REST-based cmdlets at Ignite 2019. Let’s hope this is true.

Over on Practical365.com, I compare creating a new Entra ID user account and assigning licenses to the account using both the old AzureAD module and the Microsoft Graph PowerShell SDK. In this post, I consider some additional basic user account management actions.

Connections

The basics of using the Microsoft Graph PowerShell SDK (the SDK) is to connect. You can connect interactively (delegated access) or with certificate-based authentication (application access). You can also run SDK cmdlets in Azure Automation runbooks. The simplest approach is to run Connect-MgGraph interactively, which signs into the Graph using the account you signed into PowerShell with.

Scopes

SDK cmdlets interact with Microsoft Graph APIs. A big difference between the SDK and AzureAD modules is that the SDK forces you to request the set of Graph permissions you want to use. The SDK uses a service principal to hold the permissions, and over time, that service principal might become overly permissioned. It’s a thing to keep an eye on.

In this example, we define an array of Graph permissions we wish to use, and then connect. If you request a permission that the SDK service principal doesn’t already hold, you’ll see an administrator prompt for consent.

$RequiredScopes = @("Directory.AccessAsUser.All", "Directory.ReadWrite.All", "User.ReadWrite.All", “User.Read.All”)
Connect-MgGraph -Scopes $RequiredScopes -NoWelcome

Welcome To Microsoft Graph!

Updating Properties for Entra ID User Accounts

Let’s assume that you’ve created the Sue.Ricketts@Office365itpros.com account using the New-MgUser cmdlet as described in this article and stored the user identifier for the account in the $UserId variable.

$UserId = (Get-MgUser -UserId Sue.Ricketts@office365itpros.com).Id

To update the properties of a user account, run the Update-MgUser cmdlet.

Update-MgUser -UserId $UserId -JobTitle "Senior Editor" -State NY

Updating Email Properties for an Account

You can’t update the proxyAddresses property of a user account because the Graph treats it as read-only, possibly because Exchange Online takes care of email proxy address management. However, if you change the UserPrincipalName property of an account, Update-MgUser sets the primary SMTP address of the account to match the new user principal name. The logic here is likely that it is best practice to match the user principal name and primary SMTP address. In most cases, this is true and it’s a good idea to have the cmdlet behave like it does. However, in some circumstances, you might decide to have different values in these properties.

In both situations, you should use the Exchange Online Set-Mailbox cmdlet to update proxy addresses. For example, this command adds a new SMTP proxy address to the mailbox identified by the $UserId variable:

Set-Mailbox -Identity $UserId -EmailAddresses @{Add="Johnnie.West@Office365itpros.com"}

This command updates the primary SMTP address for the mailbox without changing the user principal name:

Set-Mailbox -Identity $UserId -WindowsEmailAddress Johnnie.West@Office365itpros.com

Exchange Online uses a dual-write mechanism to make sure that any change made to mailboxes happens simultaneously to the underlying user account.

Updating a User’s Manager

The manager of a user account is updated by reference (to their account) rather than simply updating a property. To update the manager of a user account, run the Set-MgUserManagerByRef cmdlet after storing the identifier of the manager’s account in a variable:

$ManagerId = (Get-MgUser -UserId Terry.Hegarty@office365itpros.com).Id
Set-MgUserManagerByRef -UserId $UserId `
   -AdditionalProperties @{
     "@odata.id" = "https://graph.microsoft.com/v1.0/users/$ManagerId" }

To check that the manager update was successful, we need to fetch the manager’s details (expanded into a dictionary object) and retrieve the property we want.

$ManagerData = Get-Mguser -UserId $UserId -ExpandProperty Manager
$ManagerData.Manager.AdditionalProperties['displayName']
Terry Hegarty

You can also use the Get-MgUserManager cmdlet to return the manager of an account.

Get-MgUserManager -UserId Chris.Bishop@Office365itpros.com | Select-Object @{n="DisplayName";e={$_.AdditionalProperties.displayName}},@{n="UserPrincipalName";e={$_.AdditionalProperties.userPrincipalName}}

DisplayName UserPrincipalName
----------- -----------------
James Ryan  James.Ryan@office365itpros.com

Obviously, Microsoft has made defining and retrieving the manager of an account more complex than it needs to be. It would be nice if they would hide the complexity in code and deliver some straightforward cmdlets that don’t create friction when the time comes to update scripts.

Another way of updating user account properties is with the Invoke-MgGraphRequest cmdlet, which runs a Graph API query. The advantage of this cmdlet is that if you can’t find a way to do something with an SDK cmdlet, you can refer to the Microsoft Graph documentation, find some example code, and run or repurpose it.

In this example, we create a hash table to hold the properties we want to update, convert the table to a JSON object, and pass it to a PATCH query run by Invoke-MgGraphRequest:

$Parameters = @{
   JobTitle = "Managing Editor, Periodicals"
   State = "Vermont"
   OfficeLocation = "Burlington" } | ConvertTo-Json
Invoke-MgGraphRequest -Method PATCH -Uri "https://graph.microsoft.com/v1.0/users/Sue.Ricketts@office365itpros.com" -Body $Parameters -ContentType "application/json; charset=utf-8"

Delete a User Account

The Remove-MgUser cmdlet soft-deletes a user account and moves it into Entra ID’s deleted items container, where it remains for 30 days until Entra ID permanently deletes the object. The cmdlet is very simple, and it doesn’t prompt for confirmation before proceeding to delete a user account.

Remove-MgUser -UserId $UserId

If you need to restore a soft-deleted account, run the Restore-MgUser cmdlet and pass the object identifier of the account you want to restore. See this article for information about how to list the set of soft-deleted user accounts.

Restore-MgUser -UserId $UserId

I’ve experienced some issues with the Restore-MgUser cmdlet in the 1.9.3 release of the SDK which I have reported to Microsoft. Basically, the cmdlet doesn’t work in this release. I’m sure the bug will be fixed soon.

Finding User Accounts

We’ve already seen how the Get-MgUser cmdlet fetches information for an individual user account. It also fetches sets of accounts. To fetch all the accounts in the tenant, run:

[array]$Users = Get-MgUser -All

I always specify that the variable used as the target for a set of objects is an array. This makes it easy to find how many objects are returned, as in:

Write-Host $Users.Count “User accounts found”

Note that unlike Graph API queries, the Get-MgUser cmdlet takes care of data pagination for the query and fetches all available objects.

If you don’t specify the All switch, the cmdlet fetches the first 100 accounts. You can fetch a specific number of accounts using the Top parameter, up to a maximum of 999.

[array]$Top500 = Get-MgUser -Top 500

The Filter parameter uses server-side filtering to restrict the amount of data returned. For instance, here’s how to find all the guest accounts in a tenant:

[array]$Guests = Get- MgUser -Filter "usertype eq 'Guest'" -All

While this filter returns the accounts who usage location (for Microsoft 365 services) is the U.S.

Get-MgUser -Filter "usagelocation eq 'US'"

You can combine properties in a filter. For example:

Get-MgUser -Filter "usagelocation eq 'US' and state eq 'NY'"

Another interesting filter is to find accounts created in a specific date range. This command finds all tenant non-guest accounts created between January 1, 2022 and Matrch 24. Note the trailing Z on the dates. The Graph won’t treat the date as valid if the Z is not present.

Get-MgUser -Filter "createdDateTime ge 2022-01-01T00:00:00Z and createdDateTime le 2022-03-24T00:00:00Z and usertype eq ‘Member’"

Support for SDK Problems via GitHub

Hopefully, the examples listed above are useful in terms of understanding the SDK cmdlets to perform basic management of Entra ID user accounts. If you run into a problem when converting scripts to use SDK cmdlets, you can report the problem (or browse the current known issues) on GitHub. Happy migration!

]]>
https://office365itpros.com/2022/03/24/entra-id-user-accounts-powershell/feed/ 9 54188
Delete and Restore Entra ID User Accounts with the Microsoft Graph PowerShell SDK https://office365itpros.com/2022/03/23/delete-entra-id-user-accounts/?utm_source=rss&utm_medium=rss&utm_campaign=delete-entra-id-user-accounts https://office365itpros.com/2022/03/23/delete-entra-id-user-accounts/#comments Wed, 23 Mar 2022 01:00:00 +0000 https://office365itpros.com/?p=54175

Understanding How to Delete Entra ID User Accounts and Restore Them Afterwards is a Critical Skill

According to message center notification MC344406 (18 March), in early April Microsoft plans to roll-out the capability of recovering deleted service principal objects. Service principals are critical parts of registered Entra ID apps, such as the apps used to execute Microsoft Graph API queries with PowerShell. They’re also used in Azure Automation accounts, the Microsoft Graph PowerShell SDK, and managed identities. In all cases, the service principals hold the permissions needed for an app or account to operate. The worldwide roll-out to all tenants should complete by late May.

When the capability is available, any time an administrator deletes a service principal (for instance, because a registered app is no longer needed) using the Entra admin center, PowerShell (using Remove-AzureADServicePrincipal), or the Microsoft Graph API, Entra ID will place the service principal into a soft-deleted state. This already happens today for user, group, device, and application objects.

Deleted Entra ID objects stay in the deleted items container for 30 days. When the retention period elapses (extending to maybe a few days afterwards), Entra ID proceeds to permanently delete the object.

During the retention period, administrators can restore an object, which makes it easy to recover if someone deletes an important item by accident. For now, the list deleted items API doesn’t support service principals, but it will after the roll-out. Figure 1 shows user objects in the deleted items container as viewed through the Graph Explorer.

Viewing deleted Entra ID user accounts via the Graph Explorer

Delete Entra ID user account
Figure 1: Viewing deleted Entra ID user accounts via the Graph Explorer

Using Old Azure AD Cmdlets

MC344406 features two cmdlets from the Azure AD Preview module:

In some respects, it’s odd that they use cmdlets based on the Azure AD Graph API because Microsoft has scheduled the Azure AD modules for retirement in March 2024.

Of course, apart from the licensing management cmdlets, the rest of the Azure AD cmdlets will continue to work after retirement, which makes it perfectly acceptable to specify the cmdlets now, especially if replacements in the Microsoft Graph PowerShell SDK are unavailable.

Using Microsoft Graph PowerShell SDK Cmdlets to Delete Entra ID User Accounts

The Microsoft Graph PowerShell SDK can be difficult to navigate. It’s composed of 38 separate sub-modules. Although cmdlets are gathered logically, it can still be hard to find the right cmdlet to do a job. As you’d expect, the current version (1.9.3) doesn’t appear to include cmdlets to handle soft-deleted service principal objects. For now, we can see how to perform common administrative actions with user accounts as a guide to what should be available for service principals.

With that in mind, here are the steps to soft-delete user accounts, list the accounts in the deleted items container, and hard-delete (permanently remove) an account.

Soft-Delete an Entra ID User Account

To soft-delete an Entra ID account, run the Remove-MgUser and pass the object identifier or user principal name of the account to delete. The cmdlet does not prompt for a confirmation and deletes the account immediately:

Remove-MgUser -UserId Sue.Ricketts@office365itpros.com

List Soft-Deleted Entra ID User Accounts

During the 30-day retention period in the deleted items container, you can recover the account from the Entra admin center or by running the Restore-MgUser cmdlet. Before we can run Restore-MgUser, we need to know the object identifiers of the objects in the deleted items container. This code:

  • Uses the Get-MgDirectoryDeletedItemAsUser cmdlet to fetch the list of deleted user accounts. The Property parameter can be ‘*’ to return all properties of the deleted objects, but in this case, I’ve chosen to limit the set of properties to those that I want to use.
  • Loops through the data returned by Entra ID to extract the properties we want to use. The different behaviour of the Azure AD cmdlets and the Microsoft Graph PowerShell SDK cmdlets is an example of why tenants need to plan the upgrade and testing of scripts which use old cmdlets.
  • Lists the soft-deleted user accounts.
[array]$DeletedItems = Get-MgDirectoryDeletedItemAsUser -All -Property Id, DisplayName, DeletedDateTime, UserPrincipalName, Usertype
If ($DeletedItems.count -eq 0) { 
   Write-Host "No deleted accounts found - exiting"; break 
}

$Report = [System.Collections.Generic.List[Object]]::new()

ForEach ($Item in $DeletedItems) {
    $DeletedDate = Get-Date($Item.deletedDateTime)
    $ReportLine = [PSCustomObject][Ordered]@{ 
           UserId   = $Item.Id
           Name     = $Item.displayName
           Deleted  = $DeletedDate
           "Days Since Deletion" = (New-TimeSpan $DeletedDate).Days
           Type     = $Item.userType
     }
    $Report.Add($ReportLine)
}

UserId                               Name                      Deleted             Days Since Deletion Type
------                               ----                      -------             ------------------- ----
92cef396-1bd3-4296-b06f-786e2ee09077 The Maestro of Office 365 19/02/2022 17:36:44                  31 Guest
c6133be4-71d4-47c4-b109-e37c0c93f8d3 Oisin Johnston            26/02/2022 18:13:26                  24 Member
2e9f1189-d2d9-4301-be57-2d66f3df6bb1 Jessica Chen (Marketing)  04/03/2022 11:52:48                  18 Member
8cd64635-bce6-4af0-8e64-3bebe354e9a4 Alex Redmond              05/03/2022 17:36:45                  17 Member
0f16501c-8302-468a-99a6-78c22b0903d2 Jennifer Caroline         18/03/2022 21:33:13                   3 Member
3a6116ab-0116-490e-bd60-7e0cd9f36c9d Sue Ricketts (Operations) 20/03/2022 19:53:29                   2 Member
4a25ccf0-17df-42cf-beeb-4fd449531b47 Stephen Rice              22/03/2022 19:30:06                   0 Guest

To restore a soft-deleted user account, run the Restore-MgDirectoryDeletedItem cmdlet and pass the account’s identifier. After restoring the account, remember to assign licenses to allow the account to access Microsoft 365 services.

Restore-MgDirectoryDeletedItem -DirectoryObjectId 3a6116ab-0116-490e-bd60-7e0cd9f36c9d

Remove Soft-Deleted Entra ID User Account

To remove a soft-deleted directory object, run the Remove-MgDirectoryDeletedItem cmdlet and pass the object identifier. Like Remove-MgUser, the cmdlet doesn’t ask for confirmation and permanent deletion happens immediately.

Remove-MgDirectoryDeletedItem -DirectoryObjectId f9d30b84-ad5f-4151-98f0-a55dafe30829

Time of Transition

We’re in a time of transition now as Microsoft does its best to retire the Azure AD modules and build the capabilities (and hopefully the documentation) of the Microsoft Graph PowerShell SDK. In the intervening period, any time you see an example using Azure AD cmdlets, try to convert it to use the SDK. It’s a great way to learn.


Keep up to date with developments like the Microsoft Graph PowerShell SDK by subscribing to the Office 365 for IT Pros eBook. Our monthly updates make sure that our subscribers understand the most important changes happening across Office 365.

]]>
https://office365itpros.com/2022/03/23/delete-entra-id-user-accounts/feed/ 10 54175