Skip to content

Instantly share code, notes, and snippets.

@darrenjrobinson
Last active December 21, 2021 20:08
Show Gist options
  • Save darrenjrobinson/15063445df358fa4520cd93d8f429f2f to your computer and use it in GitHub Desktop.
Save darrenjrobinson/15063445df358fa4520cd93d8f429f2f to your computer and use it in GitHub Desktop.
Connecting to Microsoft Graph using the Authorization Code with PKCE Flow and PowerShell. Associated blogpost https://blog.darrenjrobinson.com/connecting-to-microsoft-graph-using-the-authorization-code-with-pkce-flow-and-powershell/
import-module PKCE
import-module JWTDetails
$clientID = '<your AAD clientID>'
$tenantID = '<your AAD tenantID'
$clientSecret = '<your AAD App Client Secret>'
$replyURL = 'https://localhost/'
$scopes = 'user.read.all'
Function Get-AuthCode {
[cmdletbinding()]
param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string]$url
)
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 = {
$uri = $web.Url.AbsoluteUri
if ($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)
$output = @{}
foreach ($key in $queryOutput.Keys) {
$output["$key"] = $queryOutput[$key]
}
return $output
}
$codeChallenge, $codeVerifier, $authResult = $null
$pkceCodes = New-PKCE
$codeChallenge = $pkceCodes.code_challenge
$codeVerifier = $pkceCodes.code_verifier
$state = $codeChallenge.Substring(0, 27)
$url = "https://login.microsoftonline.com/$($tenantID)/oauth2/v2.0/authorize?response_type=code&redirect_uri=$($replyURL)&client_id=$($clientID)&response_mode=query&scope=$($scopes)&state=$($state)&code_challenge=$($codeChallenge)&code_challenge_method=S256"
$authResult = Get-AuthCode -url $url
if ($authResult.code) {
Write-Output "Received an authorization code."
$authCode = $authResult.code
$sessionState = $authResult.session_state
if ($state = $sessionState) {
$tokenParams = @{
grant_type = "authorization_code";
client_id = $clientID;
client_secret = $clientSecret;
code = $authCode;
code_verifier = $codeVerifier;
tenant_id = $tenantID;
redirect_uri = $replyURL;
}
$tokenResponse = Invoke-RestMethod -Method Post `
-Uri "https://login.microsoftonline.com/$($tenantID)/oauth2/v2.0/token" `
-Body $tokenParams -ContentType 'application/x-www-form-urlencoded'
Get-JWTDetails $tokenResponse.access_token
Invoke-RestMethod -Headers @{Authorization = "Bearer $($tokenResponse.access_token)" } `
-Uri 'https://graph.microsoft.com/v1.0/users' `
-Method Get
}
else {
Write-Warning "Something isn't right. Returned Session State doesn't match what was sent"
Write-Warning "Sent State: $($state) `nSession State: $($sessionState)"
}
}
else {
Write-Error $_
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment