Share via

Graph API auditLogs/signIns?$filter=status/errorCode eq 0 returning records with non-zero errorCode

Anonymous
2025-02-13T22:31:08.2966667+00:00

I've encountered an inexplicable issue where I'm trying to return successful-only sign-ins for security auditing purposes from the Graph API audit log, however non-successful sign-ins are being returned.

For the sake of troubleshooting and debugging, I'm using the following cmdlet:

Get-MgBetaAuditLogSignIn -Filter $filter -All -PageSize 999 -Debug

where $filter = "status/errorCode eq 0 and signInEventTypes/any(t:t eq 'interactiveUser' or t eq 'nonInteractiveUser') and createdDateTime ge $utcStart and createdDateTime le $utcEnd"

$utcStart and $utcEnd represent a full 24 hour period

I'm unable to include all of the data being returned, however I can include a snippet of the raw JSON of one of the objects returned by the -Debug parameter:

  "status": {

    "errorCode": 50053,

    "failureReason": "Sign-in was blocked because it came from an IP address with malicious activity",

    "additionalDetails": null

  }  

This makes no rational sense based on everything I've read related to this endpoint and how to construct the filter string. I'm inclined to believe this the result of some sort of bug on Microsoft's end and I'm hoping by asking this question here will lead to guidance on how to get this fixed.

Microsoft Security | Microsoft Graph
0 comments No comments

1 answer

Sort by: Most helpful
  1. Anonymous
    2025-02-13T23:15:28.4766667+00:00

    After additional debugging and troubleshooting, I figured this out. Due to data security, I had to strip out part of the filter that was being used because I'm lazy and didn't want to manually sanitize it. Below is a sanitized version of the actual filter that was being passed to the endpoint:

    $filter = "status/errorCode eq 0 and signInEventTypes/any(t:t eq 'interactiveUser' or t eq 'nonInteractiveUser') and contains(UserDisplayName, 'Bob Smith') or contains(UserDisplayName, 'John Smith') or contains(UserDisplayName, 'Jack Smith') or contains(UserDisplayName, 'Jill Smith') and createdDateTime ge $utcStart and createdDateTime le $utcEnd"

    The crux of the issue has to do with logical grouping and operator precedence. Basically, UserDisplayName queries needed to be encapsulated:

    $filter = "status/errorCode eq 0 and signInEventTypes/any(t:t eq 'interactiveUser' or t eq 'nonInteractiveUser') and (contains(UserDisplayName, 'Bob Smith') or contains(UserDisplayName, 'John Smith') or contains(UserDisplayName, 'Jack Smith') or contains(UserDisplayName, 'Jill Smith')) and createdDateTime ge $utcStart and createdDateTime le $utcEnd"

    This is visually intuitive with the following formatting:

    status/errorCode eq 0 
    and signInEventTypes/any(t:t eq 'interactiveUser' or t eq 'nonInteractiveUser') 
    and (
        contains(UserDisplayName, 'Bob Smith') 
        or contains(UserDisplayName, 'John Smith') 
        or contains(UserDisplayName, 'Jack Smith') 
        or contains(UserDisplayName, 'Jill Smith')
    ) 
    and createdDateTime ge $utcStart 
    and createdDateTime le $utcEnd
    

    Was this answer helpful?

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.