Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OAuth2.0 authorization code flow in PowerShell

I wrote the below function to pop up an IE window to handle the user authentication of the OAuth2.0 authorization code flow in PowerShell which works but when calling it as a function, it doesn't stay in the while loop to wait for the URL of the IE window to change and to filter out the OAuth2.0 authorization code and then close the window.

Is there a way to keep the function "open" for longer and to make sure it waits for the URL of the IE window to change?

All remarks regarding the function are welcome...

function Show-OAuth2AuthCodeWindow {
  [CmdletBinding()]
  param
  (
    [Parameter(Mandatory = $true, Position = 0, HelpMessage = "The OAuth2 authorization code URL pointing towards the oauth2/v2.0/authorize endpoint as documented here: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow")]
    [System.Uri] $URL
  )
  try {

    # create an Internet Explorer object to display the OAuth 2 authorization code browser window to authenticate
    $InternetExplorer = New-Object -ComObject InternetExplorer.Application
    $InternetExplorer.Width = "600"
    $InternetExplorer.Height = "500"
    $InternetExplorer.AddressBar = $false # disable the address bar
    $InternetExplorer.ToolBar = $false # disable the tool bar
    $InternetExplorer.StatusBar = $false # disable the status bar

    # store the Console Window Handle (HWND) of the created Internet Explorer object
    $InternetExplorerHWND = $InternetExplorer.HWND

    # make the browser window visible and navigate to the OAuth2 authorization code URL supplied in the $URL parameter
    $InternetExplorer.Navigate($URL)

    # give Internet Explorer some time to start up
    Start-Sleep -Seconds 1

    # get the Internet Explorer window as application object
    $InternetExplorerWindow = (New-Object -ComObject Shell.Application).Windows() | Where-Object {($_.LocationURL -match "(^https?://.+)") -and ($_.HWND -eq $InternetExplorerHWND)}

    # wait for the URL of the Internet Explorer window to hold the OAuth2 authorization code after a successful authentication and close the window
    while (($InternetExplorerWindow = (New-Object -ComObject Shell.Application).Windows() | Where-Object {($_.LocationURL -match "(^https?://.+)") -and ($_.HWND -eq $InternetExplorerHWND)})) {
      Write-Host $InternetExplorerWindow.LocationURL
      if (($InternetExplorerWindow.LocationURL).StartsWith($RedirectURI.ToString() + "?code=")) {
        $OAuth2AuthCode = $InternetExplorerWindow.LocationURL
        $OAuth2AuthCode = $OAuth2AuthCode -replace (".*code=") -replace ("&.*")
        $InternetExplorerWindow.Quit()
      }
    }

    # return the OAuth2 Authorization Code
    return $OAuth2AuthCode

  }
  catch {
    Write-Host -ForegroundColor Red "Could not create a browser window for the OAuth2 authentication"
  }
}
like image 408
Glenn Avatar asked Feb 05 '26 19:02

Glenn


1 Answers

Answer from this blog post

I managed to get the Auth code flow working using the headless chrome. All you need are these two components.

  • Chrome/edge driver
  • Selenium driver

Once you have these setup, you need to use the below Powershell commands to generate token using Auth code flow

$SeleniumWebDriverFullPath = ".\WebDriver.dll" # Full path to selenium web driver
$ClientId = ""
$Scopes = ""
$RedirectUri = ""

$authCodeUri = "$($AuthorizeEndpoint.TrimEnd("/"))?client_id=$ClientId&scope=$Scopes&redirect_uri=$RedirectUri&response_type=code

Write-Host $authCodeUri

Import-Module $SeleniumWebDriverFullPath
$ChromeOptions = New-Object OpenQA.Selenium.Edge.EdgeOptions
$ChromeOptions.AddArgument('headless')
$ChromeOptions.AcceptInsecureCertificates = $True

$ChromeDriver = New-Object OpenQA.Selenium.Edge.EdgeDriver($ChromeOptions);
$ChromeDriver.Navigate().GoToUrl($authCodeUri);

while (!$ChromeDriver.Url.Contains("code")) { Start-Sleep 1 }

Write-Host $ChromeDriver.Url

$ParsedQueryString = [System.Web.HttpUtility]::ParseQueryString($ChromeDriver.Url)
$Code = $ParsedQueryString[0]

Write-Host "Received code: $Code"
Write-Host "Exchanging code for a token"

$tokenrequest = @{ "client_id" = $ClientId; "grant_type" = "authorization_code"; "redirect_uri" = $RedirectUri; "code" = $ParsedQueryString[0] }
$token = Invoke-RestMethod -Method Post -Uri $AuthTokenEndpoint -Body $tokenrequest

$tokenString = $token | ConvertTo-Json
like image 83
Sachin Avatar answered Feb 07 '26 10:02

Sachin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!