Search code examples
powershellazure-active-directoryazure-ad-b2cazure-ad-b2bentra

Retrieving the last or most recent SignInLogs in a specific Azure AD B2C using Get-MgAuditLogSignIn -All throws error Stream does not support reading


I got this error:

WARNING: Failed to retrieve last sign-in logs for: . Error: One or more errors occurred. (Stream does not support reading. (Parameter 'stream'))

Using https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.reports/get-mgauditlogsignin?view=graph-powershell-1.0#-sort to retrieve the most recent or the last SignInLogs in a specific Entra ID / Azure AD B2C tenant.

This is the Function I use:

Function Get-LastSignIn {
    Param (
        [string]
        $TenantDomain # Example: "contoso.onmicrosoft.com"
    )
    
    Try {
        $signInLogs = Get-MgAuditLogSignIn -All -ErrorAction Stop
        
        If ($signInLogs) {
            # Filter logs for the specified B2C tenant domain
            $latestSignIn = $signInLogs | Where-Object {
                $_.userPrincipalName -match "@$TenantDomain$"
            } |
            Sort-Object createdDateTime -Descending |
            Select-Object -First 1
            
            If ($latestSignIn) {
                Return [PSCustomObject]@{
                    LastSignIn     = $latestSignIn.createdDateTime
                    LastSignedUser = $latestSignIn.userPrincipalName
                }
            }
        }
    }
    Catch {
        Write-Warning "Failed to retrieve last sign-in logs for: $TenantDomain. Error: $($_))"
    }
    
    Return [PSCustomObject]@{
        LastSignIn     = "N/A";
        LastSignedUser = "N/A"
    }
}

Solution

  • The error "Stream does not support reading" occurs due to multiple reasons such as large data sets being returned or the manner in which you're accessing the results.

    The below script worked for me for B2C tenant:

    Connect-MgGraph -TenantID xxx.onmicrosoft.com -Scopes "AuditLog.Read.All", "Directory.Read.All"
    
    # Replace with your Azure AD/B2C tenant domain (e.g., "contoso.onmicrosoft.com")
    $TenantDomain = "xxx.onmicrosoft.com"
    
    Try {
        # Retrieve all sign-in logs
        $signInLogs = Get-MgAuditLogSignIn -All -ErrorAction Stop
    
        If ($signInLogs) {
            # Filter logs for the specified B2C tenant domain and get the most recent sign-in
            $latestSignIn = $signInLogs | Where-Object {
                $_.userPrincipalName -match "@$TenantDomain$"
            } |
            Sort-Object createdDateTime -Descending |
            Select-Object -First 1
    
            If ($latestSignIn) {
                # Output the result
                [PSCustomObject]@{
                    LastSignIn     = $latestSignIn.createdDateTime
                    LastSignedUser = $latestSignIn.userPrincipalName
                }
            } Else {
                Write-Warning "No sign-ins found for the specified domain."
            }
        }
    } Catch {
        Write-Warning "Failed to retrieve last sign-in logs for: $TenantDomain. Error: $($_)"
    }
    
    # If no logs were retrieved, output default values
    [PSCustomObject]@{
        LastSignIn     = "N/A"
        LastSignedUser = "N/A"
    }
    

    enter image description here

    For Microsoft Entra ID tenant:

    enter image description here

    If still the error occurs, you can use Top or filter with createdDateTime like below:

    # Replace with your Azure AD tenant domain (e.g., "contoso.onmicrosoft.com")
    $TenantDomain = "rukk33.onmicrosoft.com"
    
    # Get today's date and calculate the date 14 days ago
    $endDate = Get-Date
    $startDate = $endDate.AddDays(-14)
    
    # Format the dates in ISO 8601 format
    $startDateFormatted = $startDate.ToString("yyyy-MM-ddTHH:mm:ssZ")
    $endDateFormatted = $endDate.ToString("yyyy-MM-ddTHH:mm:ssZ")
    
    Try {
        # Retrieve sign-in logs with the specified date filter
        $signInLogs = Get-MgAuditLogSignIn -Filter "createdDateTime ge $startDateFormatted and createdDateTime le $endDateFormatted" -ErrorAction Stop
    
        If ($signInLogs) {
            # Filter logs for the specified B2C tenant domain and get the most recent sign-in
            $latestSignIn = $signInLogs | Where-Object {
                $_.userPrincipalName -match "@$TenantDomain$"
            } |
            Sort-Object createdDateTime -Descending |
            Select-Object -First 1
    
            If ($latestSignIn) {
                # Output the result
                [PSCustomObject]@{
                    LastSignIn     = $latestSignIn.createdDateTime
                    LastSignedUser = $latestSignIn.userPrincipalName
                }
            } Else {
                Write-Warning "No sign-ins found for the specified domain."
            }
        }
    } Catch {
        Write-Warning "Failed to retrieve last sign-in logs for: $TenantDomain. Error: $($_)"
    }
    
    # If no logs were retrieved, output default values
    [PSCustomObject]@{
        LastSignIn     = "N/A"
        LastSignedUser = "N/A"
    }
    

    enter image description here

    • Otherwise, you can still make use of $signInLogs = Get-MgAuditLogSignIn -Top 100 -ErrorAction Stop
    • Make sure you have consented to AuditLog.Read.All API permission.