PowerShell中的OAuth2.0授权代码流

时间:2020-07-01 10:39:41

标签: powershell oauth-2.0

我编写了以下函数,以弹出IE窗口来处理PowerShell中OAuth2.0授权代码流的用户身份验证,该方法可以正常工作,但是当将其作为函数调用时,它不会停留在while循环中等待更改IE窗口的URL,并过滤掉OAuth2.0授权代码,然后关闭窗口。

有没有办法使功能“打开”更长的时间,并确保它等待IE窗口的URL更改?

欢迎对该功能进行所有评论...

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 个答案:

答案 0 :(得分:0)

我的猜测是该函数不知道filter(function(a) { return a.Val == this.value; })[0].Url是什么。

您应该在函数中添加第二个参数,或者至少应该是Script scoped

我更喜欢使用第二个参数,但是如果您进行范围界定,则应该可以在$RedirectURI函数中使用它

答案 1 :(得分:0)

下面的示例使用WebBrowser控件实现所需的功能,该控件使您可以注册导航事件处理程序以捕获从授权服务器获得的授权代码。

PowerShell OAuth2 client

答案 2 :(得分:0)

来自此blog post

的答案

我设法使用无头 chrome 使 Auth 代码流正常工作。您只需要这两个组件。

完成这些设置后,您需要使用以下 Powershell 命令使用身份验证代码流生成令牌

$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