Import-Module Microsoft.Graph # .\UserLastLoginList.ps1 -GroupName "# Developer ADM" param( [Parameter(Mandatory = $true)] [string]$GroupName ) function Get-EntraGroupByName { param( [Parameter(Mandatory = $true)] [string]$EntraGroupName ) try { Write-Debug "Retrieving group ID for group: $EntraGroupName" # Get group by name $group = Get-MgGroup -Filter "displayName eq '$EntraGroupName'" if ($group) { return $group.Id } else { Write-Warning "Group '$EntraGroupName' not found" return $null } } catch { Write-Error "Error retrieving group: $($_.Exception.Message)" return $null } } Write-Debug "Connecting to Microsoft Graph..." # Connect to Microsoft Graph if not already connected if (-not (Get-MgContext)) { Connect-MgGraph -Scopes "User.Read.All", "Group.Read.All" } function Get-EntraGroupUsersRecursive { param( [Parameter(Mandatory = $true)] [string]$GroupId, [hashtable]$ProcessedGroups = @{} ) try { # Prevent infinite recursion by tracking processed groups if ($ProcessedGroups.ContainsKey($GroupId)) { Write-Debug "Group $GroupId already processed, skipping to prevent recursion" return @() } $ProcessedGroups[$GroupId] = $true Write-Debug "Retrieving users recursively from group with ID: $GroupId" # Get group members $groupMembers = Get-MgGroupMember -GroupId $GroupId -All $users = @() foreach ($member in $groupMembers) { if ($member.AdditionalProperties["@odata.type"] -eq "#microsoft.graph.user") { Write-Debug "Processing user: $($member.DisplayName) ($($member.Id))" $user = Get-MgUser -UserId $member.Id -Property "signInActivity,displayName,userPrincipalName" $users += [PSCustomObject]@{ UserPrincipalName = $user.UserPrincipalName DisplayName = $user.DisplayName LastSignInDateTime = if ($user.SignInActivity) { $user.SignInActivity.LastSignInDateTime } else { "No sign-in data available" } } } elseif ($member.AdditionalProperties["@odata.type"] -eq "#microsoft.graph.group") { Write-Debug "Processing nested group: $($member.DisplayName) ($($member.Id))" $nestedUsers = Get-EntraGroupUsersRecursive -GroupId $member.Id -ProcessedGroups $ProcessedGroups $users += $nestedUsers } } return $users } catch { Write-Error "Error retrieving group users recursively: $($_.Exception.Message)" return @() } } $groupId = Get-EntraGroupByName -EntraGroupName $GroupName if ($groupId) { # Get users recursively from the group Write-Host "Getting users recursively from group..." $recursiveUsers = Get-EntraGroupUsersRecursive -GroupId $groupId if ($recursiveUsers) { Write-Host "Found $($recursiveUsers.Count) users (including nested groups):" $recursiveUsers | Sort-Object DisplayName | Format-Table -AutoSize } else { Write-Warning "No users found in the group hierarchy or an error occurred." } } else { Write-Warning "Group not found." }