Query Details

Audit Logs End Userconsentstoppedduetorisk Basedconsent

Query

AuditLogs
| where OperationName has "Consent to application" and Result == "failure" and ResultReason has "UserConsentBlockedForRiskyAppsException"
| extend
    Initiator = iif(isnotempty(InitiatedBy["app"]), tostring(InitiatedBy["app"]["displayName"]), tostring(InitiatedBy["user"]["userPrincipalName"])),
    InitiatorId = iif(isnotempty(InitiatedBy["app"]), tostring(InitiatedBy["app"]["servicePrincipalId"]), tostring(InitiatedBy["user"]["id"])),
    IPAddress = tostring(InitiatedBy[tostring(bag_keys(InitiatedBy)[0])]["ipAddress"])
| mv-expand TargetResource = TargetResources
//| where TargetResource["type"] == "Application"
| extend
    AppDisplayName = tostring(TargetResource["displayName"])
| mv-apply modifiedProperty = TargetResource["modifiedProperties"] on (
    summarize BagToUnpack = make_bag(pack(tostring(modifiedProperty["displayName"]), pack("oldValue", trim(@'[\"\s]+', tostring(modifiedProperty["oldValue"])), "newValue", trim(@'[\"\s]+', tostring(modifiedProperty["newValue"])))))
    )
| evaluate bag_unpack(BagToUnpack, columnsConflict='replace_source')
| extend
    AdminConsent = tostring(column_ifexists("ConsentContext.IsAdminConsent", dynamic(null))["newValue"]),
    OnBehalfOfAllUsers = tostring(column_ifexists("ConsentContext.OnBehalfOfAll", dynamic(null))["newValue"]),
    ActionReason = tostring(column_ifexists("ConsentAction.Reason", dynamic(null))["newValue"]),
    Permissions = extract_all(@"PrincipalId: ([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})?, ResourceId: ([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}), ConsentType:\s+(\w+), Scope:\s+([^,]+)", extract(@"\=\>\s+(.*)", 1, tostring(column_ifexists("ConsentAction.Permissions", dynamic(null))["newValue"])))
| mv-apply Permissions on (
    extend PermissionsDict = bag_pack("ConsentType", tostring(Permissions[2]), "TargetId", tostring(Permissions[0]), "PermissionsResourceId", tostring(Permissions[1]), "Scope", array_sort_asc(split(Permissions[3], ' ')))
    | summarize Permissions = make_list(PermissionsDict)
    )
| extend Target = iff(InitiatorId == Permissions[0]["TargetId"], Initiator, "")
| project
    TimeGenerated,
    Initiator,
    IPAddress,
    OperationName,
    Target,
    Result,
    ResultReason,
    ActionReason,
    AppDisplayName,
    Permissions,
    AdminConsent,
    OnBehalfOfAllUsers,
    InitiatorId,
    InitiatedBy,
    AdditionalDetails,
    TargetResources,
    CorrelationId

Explanation

This query is looking at audit logs where the operation name includes "Consent to application", the result is a failure, and the reason for the failure is "UserConsentBlockedForRiskyAppsException". It then extracts information about the initiator of the operation, including their name, ID, and IP address.

The query also expands the target resources and extracts the display name of the application. It then unpacks the modified properties of the target resource and extracts information about the consent context, the reason for the consent action, and the permissions involved.

The query then checks if the initiator ID matches the target ID in the permissions, and if so, it sets the target as the initiator.

Finally, the query projects a number of fields including the time the operation was generated, the initiator, the IP address, the operation name, the target, the result and reason for the result, the action reason, the application display name, the permissions, whether admin consent was given, whether the operation was on behalf of all users, the initiator ID, who initiated the operation, any additional details, the target resources, and the correlation ID.

In simpler terms, this query is looking at failed attempts to give consent to applications, specifically where the user's consent was blocked because the application was deemed risky. It's extracting a lot of detail about these failed attempts, including who tried to give consent, what application they were trying to give consent to, and why it failed.

Details

Jose Sebastián Canós profile picture

Jose Sebastián Canós

Released: February 27, 2023

Tables

AuditLogs

Keywords

AuditLogs,OperationName,Result,ResultReason,Initiator,InitiatorId,IPAddress,TargetResource,AppDisplayName,ModifiedProperty,BagToUnpack,AdminConsent,OnBehalfOfAllUsers,ActionReason,Permissions,ConsentType,TargetId,PermissionsResourceId,Scope,Target,TimeGenerated,Result,AdditionalDetails,TargetResources,CorrelationId

Operators

AuditLogswhereextendiifisnotemptytostringmv-expandsummarizemake_bagpacktrimevaluatebag_unpackcolumn_ifexistsdynamicextract_allextractmv-applybag_packarray_sort_ascsplitmake_listiffproject.

Actions