Skip to content

Instantly share code, notes, and snippets.

@gscales
Created June 1, 2020 23:38
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 gscales/021becef1e16e34de43eea4b27615ec6 to your computer and use it in GitHub Desktop.
Save gscales/021becef1e16e34de43eea4b27615ec6 to your computer and use it in GitHub Desktop.
Hybrid Modern Auth Invoke-webRequest
function Show-OAuthWindow {
[CmdletBinding()]
param (
[System.Uri]
$Url
)
## Start Code Attribution
## Show-AuthWindow function is the work of the following Authors and should remain with the function if copied into other scripts
## https://foxdeploy.com/2015/11/02/using-powershell-and-oauth/
## https://blogs.technet.microsoft.com/ronba/2016/05/09/using-powershell-and-the-office-365-rest-api-with-oauth/
## End Code Attribution
Add-Type -AssemblyName System.Web
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) }
$Navigated = {
if ($web.DocumentText -match "document.location.replace") {
$Script:oAuthCode = [regex]::match($web.DocumentText, "code=(.*?)\\u0026").Groups[1].Value
$form.Close();
}
}
$web.ScriptErrorsSuppressed = $true
$web.Add_Navigated($Navigated)
$form.Controls.Add($web)
$form.Add_Shown( { $form.Activate() })
$form.ShowDialog() | Out-Null
return $Script:oAuthCode
}
function Get-AccessTokenForEWS {
[CmdletBinding()]
param (
[Parameter(Position = 1, Mandatory = $true)]
[String]
$MailboxName,
[Parameter(Position = 2, Mandatory = $false)]
[String]
$ClientId,
[Parameter(Position = 3, Mandatory = $false)]
[String]
$RedirectURI = "urn:ietf:wg:oauth:2.0:oob",
[Parameter(Position = 4, Mandatory = $false)]
[String]
$scopes = "User.Read.All Mail.Read",
[Parameter(Position = 5, Mandatory = $false)]
[switch]
$Prompt
)
Process {
if ([String]::IsNullOrEmpty($ClientId)) {
$ClientId = "5471030d-f311-4c5d-91ef-74ca885463a7"
}
$state = Get-Random
$authURI = "https://login.microsoftonline.com/Common"
$authURI += "/oauth2/v2.0/authorize?client_id=$ClientId"
$authURI += "&response_type=code&redirect_uri= " + [System.Web.HttpUtility]::UrlEncode($RedirectURI)
$authURI += "&response_mode=query&scope=" + [System.Web.HttpUtility]::UrlEncode($scopes) + "&state=$state"
if ($Prompt.IsPresent) {
$authURI += "&prompt=select_account"
}
# Extract code from query string
$authCode = Show-OAuthWindow -Url $authURI
$Body = @{"grant_type" = "authorization_code"; "scope" = $scopes; "client_id" = "$ClientId"; "code" = $authCode; "redirect_uri" = $RedirectURI }
$tokenRequest = Invoke-RestMethod -Method Post -ContentType application/x-www-form-urlencoded -Uri "https://login.microsoftonline.com/common/oauth2/token" -Body $Body
$AccessToken = $tokenRequest.access_token
return $AccessToken
}
}
$MailboxName = "gscales@datarumble.com";
$body = @{
"username" = $MailboxName
}
$RealmDiscover = Invoke-RestMethod -Uri ("https://login.microsoftonline.com/common/GetCredentialType") -ContentType "application/json; charset=UTF-8" -Method POST -Body ($body | ConvertTo-Json)
if ([Int]$RealmDiscover.EstsProperties.DomainType -eq 1 -bor [Int32]$RealmDiscover.EstsProperties.DomainType -eq 2) {
throw "Not Office365 or hybrid"
}
else {
$AutoDiscoverURI = "https://outlook.office365.com/autodiscover/autodiscover.json/v1.0/" + $MailboxName + "?Protocol=EWS"
$JsonResult = Invoke-WebRequest -Uri $AutoDiscoverURI | ConvertFrom-Json
If ($JsonResult.Url) {
$hostName = ([URI]$JsonResult.Url).Host
$ClientId = "5471030d-f311-4c5d-91ef-74ca885463a7"
$scope = "https://$hostName/EWS.AccessAsUser.All";
Get-AccessTokenForEWS -MailboxName $MailboxName -scopes $scope -ClientId $ClientId
return $TokenResult
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment