Last active
July 3, 2020 02:14
-
-
Save darrenjrobinson/174401ed835c3f25f1c4d9566ed9b86f to your computer and use it in GitHub Desktop.
Get Azure Active Directory auditLogs/directoryAudits events using PowerShell and oAuth. Associated blog post https://blog.darrenjrobinson.com/azure-self-service-password-reset-reporting-using-powershell/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Sample oAuth 2.0 Microsoft API Powershell AuthN/AuthZ Script | |
#The resource URI | |
$resource = "https://graph.microsoft.com" | |
#Your Client ID and Client Secret obainted when registering your WebApp | |
$clientid = "1c29e80e-ec64-43f7-b07a-1234567890" | |
$clientSecret = "UEy9yEnU6vcCLzdZm+ABCDEFGHIJKLMyjyL2nYQeU=" | |
#Your Reply URL configured when registering your WebApp | |
$redirectUri = "https://localhost" | |
#Scope | |
$scope = "AuditLog.Read.All;Directory.Read.All" | |
Add-Type -AssemblyName System.Web | |
#UrlEncode the ClientID and ClientSecret and URL's for special characters | |
$clientIDEncoded = [System.Web.HttpUtility]::UrlEncode($clientid) | |
$clientSecretEncoded = [System.Web.HttpUtility]::UrlEncode($clientSecret) | |
$resourceEncoded = [System.Web.HttpUtility]::UrlEncode($resource) | |
$scopeEncoded = [System.Web.HttpUtility]::UrlEncode($scope) | |
#Refresh Token Path | |
$refreshtokenpath = "C:\temp\ReportingAPI\refresh.token" | |
#Functions | |
# Function to popup Auth Dialog Windows Form for getting an AuthCode | |
Function Get-AuthCode { | |
Add-Type -AssemblyName System.Windows.Forms | |
$form = New-Object -TypeName System.Windows.Forms.Form -Property @{Width=440;Height=640} | |
$web = New-Object -TypeName System.Windows.Forms.WebBrowser -Property @{Width=420;Height=600;Url=($url -f ($Scope -join "%20")) } | |
$DocComp = { | |
$Global:uri = $web.Url.AbsoluteUri | |
if ($Global:uri -match "error=[^&]*|code=[^&]*") {$form.Close() } | |
} | |
$web.ScriptErrorsSuppressed = $true | |
$web.Add_DocumentCompleted($DocComp) | |
$form.Controls.Add($web) | |
$form.Add_Shown({$form.Activate()}) | |
$form.ShowDialog() | Out-Null | |
$queryOutput = [System.Web.HttpUtility]::ParseQueryString($web.Url.Query) | |
$Global:output = @{} | |
foreach($key in $queryOutput.Keys){ | |
$output["$key"] = $queryOutput[$key] | |
} | |
$output | |
} | |
function Get-AzureAuthN ($resource) { | |
# Get Permissions (if the first time, get an AuthCode and Get a Bearer and Refresh Token | |
# Get AuthCode | |
$url = "https://login.microsoftonline.com/common/oauth2/authorize?response_type=code&redirect_uri=$redirectUri&client_id=$clientID&resource=$resourceEncoded&scope=$scopeEncoded" | |
Get-AuthCode | |
# Extract Access token from the returned URI | |
$regex = '(?<=code=)(.*)(?=&)' | |
$authCode = ($uri | Select-string -pattern $regex).Matches[0].Value | |
Write-output "Received an authCode, $authCode" | |
#get Access Token | |
$body = "grant_type=authorization_code&redirect_uri=$redirectUri&client_id=$clientId&client_secret=$clientSecretEncoded&code=$authCode&resource=$resource" | |
$Authorization = Invoke-RestMethod https://login.microsoftonline.com/common/oauth2/token ` | |
-Method Post -ContentType "application/x-www-form-urlencoded" ` | |
-Body $body ` | |
-ErrorAction STOP | |
Write-output $Authorization.access_token | |
$Global:accesstoken = $Authorization.access_token | |
$Global:refreshtoken = $Authorization.refresh_token | |
if ($refreshtoken){$refreshtoken |out-file "$($refreshtokenpath)"} | |
if ($Authorization.token_type -eq "Bearer" ){ | |
Write-Host "You've successfully authenticated to $($resource) with authorization for $($Authorization.scope)" | |
} | |
else{ | |
write-host "Check the console for errors. Chances are you provided the incorrect clientID and clientSecret combination for the API Endpoint selected" | |
} | |
} | |
function Get-NewTokens { | |
# We have a previous refresh token. | |
# use it to get a new token | |
$refreshtoken = Get-Content "$($refreshtokenpath)" | |
# Refresh the token | |
#get Access Token | |
$body = "grant_type=refresh_token&refresh_token=$refreshtoken&redirect_uri=$redirectUri&client_id=$clientId&client_secret=$clientSecretEncoded" | |
$Global:Authorization = Invoke-RestMethod https://login.microsoftonline.com/common/oauth2/token ` | |
-Method Post -ContentType "application/x-www-form-urlencoded" ` | |
-Body $body ` | |
-ErrorAction STOP | |
$Global:accesstoken = $Authorization.access_token | |
$Global:refreshtoken = $Authorization.refresh_token | |
if ($refreshtoken){ | |
$refreshtoken | out-file "$($refreshtokenpath)" | |
write-host "Updated tokens" | |
$Authorization | |
$Global:headerParams = @{'Authorization'="$($Authorization.token_type) $($Authorization.access_token)"} | |
} | |
} | |
#AuthN | |
Get-AzureAuthN ($resource) | |
# Refresh our tokens | |
# Get-NewTokens | |
# Base Azure Graph AuditLogs URI | |
$DirectoryAuditURL = "https://graph.microsoft.com/beta/auditLogs/directoryAudits" | |
# Get Reset Password Events | |
$passwordMgmtAuditData = Invoke-RestMethod -Method Get -Uri "$($DirectoryAuditURL)?`$filter=category eq `'UserManagement`' and activityDateTime ge 2018-12-11T03:15:10.6837342Z and startswith(activityDisplayName%2C+`'Reset password`')" -Headers @{Authorization = "Bearer $($Global:accesstoken)"} | |
write-host -ForegroundColor Cyan "Retreived $($passwordMgmtAuditData.value.count) records" | |
# Get Reset Password Events from the last 14 days | |
# Date Time for the report. Last 14 Days | |
[string]$strDateTimeNow = Get-Date -Format yyyy-MM-ddThh:mm:ss | |
[datetime]$dateTimeNow = Get-Date -Format yyyy-MM-ddThh:mm:ss | |
[datetime]$minus14Days = $dateTimeNow.AddDays(-14) | |
[string]$14daysAgo = get-date($minus14Days) -Format yyyy-MM-ddThh:mm:ss | |
$passwordMgmtAuditData = Invoke-RestMethod -Method Get -Uri "$($DirectoryAuditURL)?`$filter=category eq `'UserManagement`' and activityDateTime ge $($14daysAgo)z and activityDateTime le $($strDateTimeNow)z and startswith(activityDisplayName%2C+`'Reset password`')" -Headers @{Authorization = "Bearer $($Global:accesstoken)"} | |
write-host -ForegroundColor Cyan "Retreived $($passwordMgmtAuditData.value.count) records" | |
Try opening the script in VSCode or PowerShell ISE and stepping through it to see if there is a error response during the AuthCode process.
Ok, it's a WinForms issue. You'll need to trigger the process using IE.
I've tested the Authorization Code Grant Flow using this method and it works.
https://github.com/shawntabrizi/Microsoft-Authentication-with-PowerShell-and-MSAL
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
its a good script for beginners like me who would like to learn how to get auth token for a specific resource. thanks for the script it is really helped me understanding how scoping works and so on. As i tried this script from an elevated powershell with a global admin account, post interative sign in page it gets stuck there. please help me if something that I should do to get it work. The PS version that i am using is PSVersion- 5.1.18362.752. here is the screenshot of the sign page