Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save darrenjrobinson/174401ed835c3f25f1c4d9566ed9b86f to your computer and use it in GitHub Desktop.
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/
#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"
@sujith-cy
Copy link

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
image

@darrenjrobinson
Copy link
Author

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.

@sujith-cy
Copy link

As suggested by you, I tried with PowerShell ISE but unfortunately the same issue
image

please assist

@darrenjrobinson
Copy link
Author

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