Sign-in Audit Logs – One of the hidden shiny gems

Learn how to utilize sign-in audit Logs and Get-MgAuditLogSignIn to get information related to users, devices, sign-ins and many more.

In today’s cloud-driven world, user sign-ins happen almost every second—across different devices, applications, and locations. Yet, for many IT teams, sign-in audit logs remain an underutilized resource, quietly capturing critical details about who’s accessing what, from where, and when. Think of them as a behind-the-scenes narrator, meticulously recording each logon event, ready to reveal patterns of suspicious activity, compliance issues, or simple user trends whenever you decide to look.

But why call them a “hidden gem”? Because buried within these logs is a wealth of insights that can elevate your organization’s security posture, enhance your troubleshooting process, and even uncover business intelligence you never knew you had. In this blog post, we’ll explore why sign-in audit logs deserve a top spot in your IT toolbox, the kinds of stories they can tell, and how you can turn them into a powerful ally for both security and efficiency. Let’s dive in!

Sign-in Audit Logs - One of the hidden gems Users Devices apps Intune and more

Understanding and Using Get-MgAuditLogSignIn

When it comes to exploring sign-in data in Microsoft Entra ID, Get-MgAuditLogSignIn is your go-to PowerShell cmdlet. It taps into the sign-in logs stored in your tenant, revealing details about who signed in, how they authenticated, which device they used, and much more. By leveraging this cmdlet, you gain deep visibility into user activities, enabling better security monitoring, troubleshooting, and auditing. Always reference to the official documentation for the most up-to-date information on this cmdlet.

What does Get-MgAuditLogSignIn do?

Get-MgAuditLogSignIn retrieves sign-in events for Microsoft Entra user accounts in your tenant. These events generally include:

  • Interactive sign-ins: Any login that required a username and password (or another form of interactive authentication).
  • Federated sign-ins: Successful federated logins (e.g., via a third-party identity provider or hybrid identity setup).

Because these logs often hold sensitive information (usernames, device details, IP addresses, etc.), you need appropriate permissions to access them—specifically AuditLog.Read.All or Directory.Read.All at the application level.

Key Points

  1. Permissions
    • Delegated (work or school account): Not supported for this cmdlet.
    • Application (daemon app or script): Requires at least AuditLog.Read.All or Directory.Read.All permissions.
  2. Filtering & Pagination
    • You can filter results on properties such as userPrincipalName, createdDateTime, appDisplayName, and more.
    • Pagination controls like -Top, -Skip, and -All help you navigate through large datasets.
  3. Outputs
    • Each record in the output is typically a sign-in event object containing details like CreatedDateTime, UserPrincipalName, AppDisplayName, DeviceDetail, IpAddress, Location, and more.

Basic Syntax and Usage

The cmdlet offers three main parameter sets as mentioned here. You’ll most commonly use the first one to list or filter sign-in events:

Get-MgAuditLogSignIn
[-ExpandProperty <String[]>]
[-Property <String[]>]
[-Filter <String>]
[-Search <String>]
[-Skip <Int32>]
[-Sort <String[]>]
[-Top <Int32>]
[-All]
...
  • -Filter: Allows you to filter the sign-in events on a given property (e.g., userPrincipalName eq 'alice@contoso.com').
  • -Top: Limits the number of items returned in a single page.
  • -All: Retrieves all pages of results automatically.
  • -Skip: Skips a certain number of items (useful for pagination in scripts).

If you want to retrieve one specific sign-in event by its ID, you can use the parameter set with -SignInId.


Simple Examples

Below are some straightforward examples to get you started.

1. List All Sign-Ins
# 1) Connect to Microsoft Graph with the necessary scopes
Connect-MgGraph -Scopes "AuditLog.Read.All"

# 2) Retrieve all sign-in events (may return many pages)
Get-MgAuditLogSignIn -All

This fetches every sign-in event available within your tenant (subject to retention policies). Because the dataset can be large, it’s often wise to combine this with filters or time-based restrictions.


2. Retrieve the First 10 Sign-Ins for a Specific Application
# Connect to Graph (only needed once per session)
Connect-MgGraph -Scopes "AuditLog.Read.All"

# Fetch the first 10 sign-ins to apps that start with "Graph"
Get-MgAuditLogSignIn -Filter "startsWith(appDisplayName,'Graph')" -Top 10

In this example, we’re using the -Filter parameter to look for sign-ins where the application’s display name begins with “Graph.” The -Top 10 parameter limits the output to the first 10 matching records.


3. Filter by Date (Local PowerShell Filtering)

The -Filter parameter supports certain OData filters, but if you need to do more complex date filtering, you can retrieve sign-ins and then filter locally:

Connect-MgGraph -Scopes "AuditLog.Read.All"

# Retrieve all sign-ins from the service
$allSignIns = Get-MgAuditLogSignIn -All

# Filter in PowerShell for sign-ins in the last 7 days
$since = (Get-Date).AddDays(-7)
$recentSignIns = $allSignIns | Where-Object { $_.CreatedDateTime -ge $since }

$recentSignIns

While server-side filtering (-Filter "createdDateTime ge 2023-01-01T00:00:00Z") can be more efficient, local filtering is an option when you need advanced logic or if certain filter operations aren’t supported on the server side.


4. Retrieving a Specific Sign-In by ID

If you already have a sign-in ID (for instance, from a previous query or an alert), you can fetch just that one record:

Connect-MgGraph -Scopes "AuditLog.Read.All"

# Example sign-in ID
$signInId = "b87efbc1-983f-4ec9-abc6-999999999999"

Get-MgAuditLogSignIn -SignInId $signInId

This will return the details of that single sign-in event.


Tips for Effective Usage

  1. Combine Filters: Use -Filter to narrow down results by userPrincipalName, appDisplayName, or createdDateTime. This cuts down on noise and speeds up queries.
  2. Pagination: Large organizations can have thousands or millions of sign-ins. Use -Top in combination with -Skip or simply use -All if you need to loop through everything in a script.
  3. Exporting Results: If you want to analyze sign-ins offline or in Excel, pipe the output to Export-Csv: Get-MgAuditLogSignIn -All | Export-Csv -Path "C:\Temp\AllSignIns.csv" -NoTypeInformation
  4. Security & Privacy: Sign-in logs often contain IP addresses, user emails, and other sensitive data. Handle them according to your organization’s security and privacy guidelines.

Get sign-in information for specific devices

One of the most powerful ways to dig deeper into your audit logs is by focusing on specific devices—whether that’s a set of shared workstations or a fleet of corporate-owned mobile devices. Below is a PowerShell script that demonstrates how to retrieve sign-in events for a defined list of devices. We’ll walk through what it does, step by step.

What the Script Does

  1. Sets Up a Logging Environment
    • The script starts by ensuring the C:\Temp directory exists and begins a transcript, capturing all console output in C:\Temp\AuditLogsDevices.log. This makes it easy to review exactly what happened during the script run. Always use logging at the one way or another to know what is happening in your script.
  2. Connects to Microsoft Graph
    • It then connects to Microsoft Graph with the AuditLog.Read.All scope. This permission level is necessary to retrieve sign-in data from Microsoft Entra audit logs.
  3. Prepares a DataTable
    • A new DataTable is created to store each sign-in event’s key information. Columns such as DeviceName, SignInTime, and UserPrincipalName are added to keep everything neatly organized.
  4. Reads Device Names from a File
    • The script reads device names (one per line) from C:\Temp\devices.txt. Each entry might be a device’s display name or a known naming pattern.
  5. Retrieves All Sign-Ins for a Specified Time Window
    • To optimize performance, the script fetches all sign-ins from the last 30 days—only once. This can be adjusted to any time range you need by modifying the $since variable.
  6. Filters the Sign-Ins Locally
    • With a full dataset of recent sign-ins in hand, the script loops through each device name from the text file. It uses Where-Object to match any sign-in events whose DeviceName property corresponds to that device.
    • If matches are found, they’re appended to the DataTable. If not, a console message indicates that no sign-ins were found for that device.
  7. Displays and Exports Results
    • Finally, the script displays the entire DataTable in the console, as well as in an Out-GridView window for quick, interactive inspection.
    • It also exports the results to a CSV file in C:\Temp\DeviceSignIns.csv, making it easy to share or analyze the data in Excel or other tools.
  8. Stops Transcript
    • The script ends by stopping the transcript, closing out the log file so you have a complete record of every command and output.

The script (many devices)

You can also find all the script in my GitHub page here.

# Ensure the directory exists
$logDirectory = "C:\Temp"
if (!(Test-Path $logDirectory)) {
    New-Item -ItemType Directory -Path $logDirectory | Out-Null
}

# Start transcript to capture console output to a file
Start-Transcript -Path "C:\Temp\AuditLogsDevices.log" -Append

try {
    ###############################################################################
    # Connect to Microsoft Graph
    ###############################################################################
    Connect-MgGraph -Scopes "AuditLog.Read.All"

    ###############################################################################
    # Prepare the DataTable
    ###############################################################################
    $table = New-Object System.Data.DataTable
    $table.Columns.Add("DeviceName")        | Out-Null
    $table.Columns.Add("DeviceID")          | Out-Null
    $table.Columns.Add("IsManaged")         | Out-Null
    $table.Columns.Add("SignInTime")        | Out-Null
    $table.Columns.Add("UserPrincipalName") | Out-Null
    $table.Columns.Add("AppDisplayName")    | Out-Null
    $table.Columns.Add("TokenIssuerType")   | Out-Null
    $table.Columns.Add("IsInteractive")     | Out-Null

    ###############################################################################
    # Read the list of device names from a text file
    # (one device name per line in C:\Temp\devices.txt)
    ###############################################################################
    $devices = Get-Content -Path "C:\Temp\devices.txt"

    ###############################################################################
    # Retrieve ALL sign-in logs for a specified time window
    # Adjust the date range as needed, e.g. last 30 days
    ###############################################################################
    $since = (Get-Date).AddDays(-30).ToString("yyyy-MM-ddTHH:mm:ssZ")
    Write-Host "`nFetching all sign-ins from the last 30 days... (This might take a while.)"

    $allSignInLogs = Get-MgAuditLogSignIn -All `
        -Filter "createdDateTime ge $since" `
        | Select-Object `
            CreatedDateTime,
            UserPrincipalName,
            AppDisplayName,
            IsInteractive,
            TokenIssuerType,
            @{
                Name       = 'DeviceId'
                Expression = { $_.DeviceDetail.DeviceId }
            },
            @{
                Name       = 'DeviceName'
                Expression = { $_.DeviceDetail.DisplayName }
            },
            @{
                Name       = 'IsManaged'
                Expression = { $_.DeviceDetail.IsManaged }
            }

    Write-Host "Total sign-ins retrieved: $($allSignInLogs.Count)"

    ###############################################################################
    # For each device in the text file, filter the sign-ins locally
    ###############################################################################
    foreach ($dev in $devices) {
        Write-Host "`n=== Searching sign-in logs for device: $dev ==="

        # Filter locally for sign-ins that match this device name
        $signInLogs = $allSignInLogs | Where-Object {
            $_.DeviceName -and ($_.DeviceName -like "*$dev*")
        }

        if ($signInLogs -and $signInLogs.Count -gt 0) {
            Write-Host "Found $($signInLogs.Count) sign-ins for device: $dev"
            foreach ($log in $signInLogs) {
                $row = $table.NewRow()
                $row["DeviceName"]        = $log.DeviceName
                $row["DeviceID"]          = $log.DeviceId
                $row["IsManaged"]         = $log.IsManaged
                $row["SignInTime"]        = $log.CreatedDateTime
                $row["UserPrincipalName"] = $log.UserPrincipalName
                $row["AppDisplayName"]    = $log.AppDisplayName
                $row["TokenIssuerType"]   = $log.TokenIssuerType
                $row["IsInteractive"]     = $log.IsInteractive
                $table.Rows.Add($row)
            }
        }
        else {
            Write-Host "No sign-in logs found for device: $dev"
        }
    }

    ###############################################################################
    # Display the results
    ###############################################################################
    Write-Host "`n=== Final Table of Device Sign-Ins ==="
    $table  # Shows the DataTable on screen in the console

    # Display in a separate GridView window (useful for interactive inspection)
    $table | Out-GridView -Title "Device Sign-Ins"

    # Export to CSV if desired:
    $table | Export-Csv -Path "C:\Temp\DeviceSignIns.csv" -NoTypeInformation
    Write-Host "Exported results to C:\Temp\DeviceSignIns.csv"

} finally {
    # Stop transcript to end console logging
    Stop-Transcript
}

Why This Approach Works

  • Efficiency: By pulling all sign-ins once (for a given time range) and then filtering in PowerShell, you avoid repeated calls to Microsoft Graph for each device. This is especially handy if you have a long list of device names.
  • Flexibility: You can customize the date range, add or remove columns in the DataTable, or modify the filter logic (for example, using an exact match instead of a -like wildcard).
  • Audit-Friendly: The transcript feature captures everything that happens in the session, so you have a clear audit trail of exactly which data was fetched and how it was processed.

Key Considerations

When pulling sign-in data for specific devices, it’s important to understand the broader context and potential pitfalls. Here are some considerations to keep in mind as you tailor the script to your environment:

  1. Data Volume and Performance
    • Large Data Sets: Retrieving all sign-ins from the last 30 days can be resource-intensive, especially in larger tenants. You might consider narrowing the time range (e.g., last 7 days) or adding server-side filters (like userPrincipalName eq '...') to limit results.
    • Graph Throttling: Microsoft Graph enforces rate limits. If you’re processing large amounts of data, you may hit throttling. Implement retry logic or break down queries into smaller chunks if you notice performance degradation.
  2. Naming Conventions vs. Exact Matches
    • Wildcard Searches: The script uses -like "*$dev*" to find partial matches for device names. If your environment has strict naming conventions (e.g., exact device names), you may want to switch to an exact match (-eq) or refine the wildcard approach.
    • Case Sensitivity: The -like operator in PowerShell is typically case-insensitive by default, which can be helpful for device names that might vary in case.
  3. Script Customization
    • Date Range: By default, this script pulls the last 30 days of data. Adjust the -Filter "createdDateTime ge $since" portion to suit your auditing window or your organization’s retention period.
    • Output Format: The script exports to CSV for convenience. If you prefer JSON, XML, or direct insertion into a database, adapt the output steps accordingly.
    • Additional Columns: If you need more sign-in details (e.g., IP addresses, location, conditional access status), consider extending the Select-Object portion to include more properties from the sign-in logs.

By keeping these considerations in mind, you’ll ensure that your device-focused sign-in audits are both effective and aligned with your organization’s performance, security, and compliance needs.

Bonus script (one device)

Sometimes, you only need to focus on a single device rather than scanning all sign-ins for your entire environment. In such cases, it’s much more efficient to filter directly on the server side—using the device’s display name—rather than retrieving all sign-ins and filtering locally. Below is a PowerShell script that demonstrates how to do just that.

Why Server-Side Filtering?
  • Performance: You avoid fetching thousands (or millions) of irrelevant sign-in records, reducing network overhead and load on Microsoft Graph.
  • Simplicity: Fewer steps are involved since you’re targeting just one device in a single query.
  • Clarity: The script remains focused on exactly the data you need.
# Ensure the directory exists
$logDirectory = "C:\Temp"
if (!(Test-Path $logDirectory)) {
    New-Item -ItemType Directory -Path $logDirectory | Out-Null
}

# Start transcript to capture console output to a file
Start-Transcript -Path "C:\Temp\AuditLogsDevices.log" -Append

try {
    ###############################################################################
    # Connect to Microsoft Graph
    ###############################################################################
    Connect-MgGraph -Scopes "AuditLog.Read.All"

    ###############################################################################
    # Prepare the DataTable
    ###############################################################################
    $table = New-Object System.Data.DataTable
    $table.Columns.Add("DeviceName")        | Out-Null
    $table.Columns.Add("DeviceID")          | Out-Null
    $table.Columns.Add("IsManaged")         | Out-Null
    $table.Columns.Add("SignInTime")        | Out-Null
    $table.Columns.Add("UserPrincipalName") | Out-Null
    $table.Columns.Add("AppDisplayName")    | Out-Null
    $table.Columns.Add("TokenIssuerType")   | Out-Null
    $table.Columns.Add("IsInteractive")     | Out-Null

    ###############################################################################
    # Define the single device name (adjust as needed)
    ###############################################################################
    $deviceName = "MyLaptop"

    ###############################################################################
    # Retrieve sign-in logs for the last 30 days for this one device
    # Using server-side filter to be more efficient
    ###############################################################################
    $since = (Get-Date).AddDays(-30).ToString("yyyy-MM-ddTHH:mm:ssZ")
    Write-Host "`nFetching sign-ins from the last 30 days for device: $deviceName"

    # Note: 'contains(...)' + 'tolower(...)' helps match partial/case-insensitive device names.
    $signInLogs = Get-MgAuditLogSignIn -All `
        -Filter "createdDateTime ge $since and contains(tolower(deviceDetail/displayName), '$($deviceName.ToLower())')" `
        | Select-Object `
            CreatedDateTime,
            UserPrincipalName,
            AppDisplayName,
            IsInteractive,
            TokenIssuerType,
            @{
                Name       = 'DeviceId'
                Expression = { $_.DeviceDetail.DeviceId }
            },
            @{
                Name       = 'DeviceName'
                Expression = { $_.DeviceDetail.DisplayName }
            },
            @{
                Name       = 'IsManaged'
                Expression = { $_.DeviceDetail.IsManaged }
            }

    Write-Host "Total sign-ins retrieved for device '$deviceName': $($signInLogs.Count)"

    ###############################################################################
    # Populate the DataTable with the sign-in details
    ###############################################################################
    if ($signInLogs -and $signInLogs.Count -gt 0) {
        foreach ($log in $signInLogs) {
            $row = $table.NewRow()
            $row["DeviceName"]        = $log.DeviceName
            $row["DeviceID"]          = $log.DeviceId
            $row["IsManaged"]         = $log.IsManaged
            $row["SignInTime"]        = $log.CreatedDateTime
            $row["UserPrincipalName"] = $log.UserPrincipalName
            $row["AppDisplayName"]    = $log.AppDisplayName
            $row["TokenIssuerType"]   = $log.TokenIssuerType
            $row["IsInteractive"]     = $log.IsInteractive
            $table.Rows.Add($row)
        }
    }
    else {
        Write-Host "No sign-in logs found for device: $deviceName"
    }

    ###############################################################################
    # Display the results
    ###############################################################################
    Write-Host "`n=== Final Table of Device Sign-Ins ==="
    $table  # Shows the DataTable on screen in the console

    # Display in a separate GridView window (useful for interactive inspection)
    $table | Out-GridView -Title "Device Sign-Ins"

    # Export to CSV if desired:
    $table | Export-Csv -Path "C:\Temp\DeviceSignIns.csv" -NoTypeInformation
    Write-Host "Exported results to C:\Temp\DeviceSignIns.csv"

} finally {
    # Stop transcript to end console logging
    Stop-Transcript
}

By focusing on one device and applying a server-side filter, you streamline the entire process—no need to pull every sign-in record for all devices. This approach is particularly helpful in large environments where performance and clarity are paramount. Simply adjust $deviceName and the date range to suit your needs, and you’re ready to go.

Get Sign-In Information for a Specific Cloud App

Sometimes you want to focus on a single cloud application—perhaps you suspect an issue with user authentication, or you need to audit a particular business-critical app. The following script demonstrates how to retrieve sign-in logs for one specific application in your tenant by:

  1. Storing the results in a DataTable and exporting them to CSV.
  2. Defining the app name in a PowerShell variable.
  3. Fetching all sign-ins from a specified date range (e.g., last 30 days).
  4. Filtering those sign-ins locally based on the app’s display name.

What the Script Does

  1. Transcript Logging
    • The script ensures the directory C:\Temp exists and then starts a transcript in C:\Temp\AuditLogsSingleApp.log. This logs everything printed to the console, providing a clear audit trail.
  2. Connection to Microsoft Graph
    • It connects to Microsoft Graph with the AuditLog.Read.All scope, allowing the script to query sign-in logs in Microsoft Entra (Azure AD).
  3. DataTable Setup
    • A DataTable is created to store sign-in details such as the application name, sign-in time, user principal name, device info, and more.
  4. Single App Name Definition
    • You define the target application name in a variable (e.g., $appName = "SharePoint"). The script uses this variable to filter sign-in logs for the chosen app.
  5. Retrieve All Sign-Ins for the Last 30 Days
    • The script fetches all sign-ins from the past 30 days (-Filter "createdDateTime ge $since") in one go, which can be adjusted based on your needs.
  6. Local Filtering
    • After retrieving the full dataset, the script filters locally for sign-ins whose AppDisplayName property contains the specified $appName string.
  7. Output and Export
    • The results are displayed in the console, in an Out-GridView window, and exported to a CSV file (C:\Temp\SingleAppSignIns.csv).
  8. Stop Transcript
    • The script concludes by stopping the transcript, ensuring you have a complete record of the script’s actions.

The script

# Ensure the directory exists
$logDirectory = "C:\Temp"
if (!(Test-Path $logDirectory)) {
    New-Item -ItemType Directory -Path $logDirectory | Out-Null
}

# Start transcript to capture console output to a file
Start-Transcript -Path "C:\Temp\AuditLogsSingleApp.log" -Append

try {
    ###############################################################################
    # Connect to Microsoft Graph
    ###############################################################################
    Connect-MgGraph -Scopes "AuditLog.Read.All"

    ###############################################################################
    # Prepare the DataTable
    ###############################################################################
    $table = New-Object System.Data.DataTable
    $table.Columns.Add("AppName")           | Out-Null
    $table.Columns.Add("SignInTime")        | Out-Null
    $table.Columns.Add("UserPrincipalName") | Out-Null
    $table.Columns.Add("IsInteractive")     | Out-Null
    $table.Columns.Add("DeviceName")        | Out-Null
    $table.Columns.Add("IsManaged")         | Out-Null
    $table.Columns.Add("TokenIssuerType")   | Out-Null

    ###############################################################################
    # Define the single app name you want to search for
    ###############################################################################
    $appName = "SharePoint"

    ###############################################################################
    # Retrieve ALL sign-in logs for a specified time window
    # Adjust the date range as needed, e.g. last 30 days
    ###############################################################################
    $since = (Get-Date).AddDays(-30).ToString("yyyy-MM-ddTHH:mm:ssZ")
    Write-Host "`nFetching all sign-ins from the last 30 days... (This might take a while.)"

    $allSignInLogs = Get-MgAuditLogSignIn -All `
        -Filter "createdDateTime ge $since" `
        | Select-Object `
            CreatedDateTime,
            UserPrincipalName,
            AppDisplayName,
            IsInteractive,
            TokenIssuerType,
            @{
                Name       = 'DeviceName'
                Expression = { $_.DeviceDetail.DisplayName }
            },
            @{
                Name       = 'IsManaged'
                Expression = { $_.DeviceDetail.IsManaged }
            }

    Write-Host "Total sign-ins retrieved: $($allSignInLogs.Count)"

    ###############################################################################
    # Filter the sign-ins locally for the specified app
    ###############################################################################
    Write-Host "`n=== Searching sign-in logs for app: $appName ==="

    $appSignInLogs = $allSignInLogs | Where-Object {
        $_.AppDisplayName -and ($_.AppDisplayName -like "*$appName*")
    }

    if ($appSignInLogs -and $appSignInLogs.Count -gt 0) {
        Write-Host "Found $($appSignInLogs.Count) sign-ins for app: $appName"
        foreach ($log in $appSignInLogs) {
            $row = $table.NewRow()
            $row["AppName"]           = $log.AppDisplayName
            $row["SignInTime"]        = $log.CreatedDateTime
            $row["UserPrincipalName"] = $log.UserPrincipalName
            $row["IsInteractive"]     = $log.IsInteractive
            $row["DeviceName"]        = $log.DeviceName
            $row["IsManaged"]         = $log.IsManaged
            $row["TokenIssuerType"]   = $log.TokenIssuerType
            $table.Rows.Add($row)
        }
    }
    else {
        Write-Host "No sign-in logs found for app: $appName"
    }

    ###############################################################################
    # Display the results
    ###############################################################################
    Write-Host "`n=== Final Table of App Sign-Ins ==="
    $table  # Shows the DataTable on screen in the console

    # Display in a separate GridView window (useful for interactive inspection)
    $table | Out-GridView -Title "App Sign-Ins"

    # Export to CSV if desired:
    $table | Export-Csv -Path "C:\Temp\SingleAppSignIns.csv" -NoTypeInformation
    Write-Host "Exported results to C:\Temp\SingleAppSignIns.csv"

} finally {
    # Stop transcript to end console logging
    Stop-Transcript
}

Why This Is Useful

  • Targeted Troubleshooting: If an application is experiencing sign-in issues, quickly isolate its logs and see who’s affected.
  • Auditing and Compliance: Validate whether only authorized users have signed in to a sensitive or critical cloud app.
  • Performance: Fetching all logs once and then filtering locally can be more efficient than repeatedly calling Microsoft Graph for each query—especially if you plan to adjust $appName to examine different apps.
  • Easy Adaptation: You can switch from -like "*$appName*" to an exact match (-eq) if you know the exact AppDisplayName or if you want a stricter filter.

With this script, you’ll have a clear, audit-ready overview of who’s signing into a specific cloud application and when, all while retaining the flexibility to expand or refine your queries as needed.

Final Verdict: Elevate Your Visibility with Sign-In Audit Logs

Sign-in audit logs are more than just a troubleshooting tool; they’re a powerful gateway to understanding user behavior, application usage, and potential security vulnerabilities across your environment. By leveraging Get-MgAuditLogSignIn—and pairing it with targeted filters and data-driven scripts—you gain the flexibility to focus on exactly what matters, whether that’s a specific device, a single cloud application, or an entire fleet of shared Android devices.

Throughout this blog post, we’ve explored:

  • How to fetch sign-in data for specific devices.
  • How to narrow down sign-in logs for a particular cloud application.
  • Practical considerations and best practices for handling large datasets and sensitive information.

Remember to experiment with the various configuration options of this cmdlet—things like server-side filtering, pagination, and property selection. Each environment is unique, so feel free to adapt these scripts to match your naming conventions, compliance requirements, and operational workflows.

Finally, if you have any questions or need further assistance in tailoring these approaches to your specific scenario, don’t hesitate to reach out. The beauty of these scripts lies in their flexibility and extensibility; with a little creativity, you can turn your sign-in logs into a dynamic security asset that’s always at your fingertips.

Happy auditing!


References and Documentation

Other Interesting Posts

Leave a Reply

Your email address will not be published. Required fields are marked *