TransWikia.com

OAuth2.0 authorization code flow in PowerShell

Stack Overflow Asked on December 23, 2021

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://docs.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"
  }
}

3 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.

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

Answered by Sachin on December 23, 2021

The following example does what you want with a WebBrowser control, which allows you to register a Navigating event handler to catch the authorization code obtained from your authorization server.

PowerShell OAuth2 client

Answered by Bill Lam on December 23, 2021

My guess is that the function has no idea what $RedirectURI is.

You should make that a second parameter to the function or it should be (at least) Script scoped

I'd prefer using a second parameter, but if you do scoping, you should be able to use it inside the function with $script:RedirectURI

Answered by Theo on December 23, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP