首页 > 解决方案 > 如何使用 PowerShell 打开并接收来自 Azure Active Directory OAuth 授权代码授予流程的授权对话框的响应

问题描述

我正在尝试编写一个 PowerShell 脚本,让用户授权 Azure Active Directory 应用程序代表他们行事。

遵循Microsoft 的授权代码授予流程文档。我正在使用以下行调用授权端点:

Invoke-WebRequest -Method GET -Uri "https://login.microsoftonline.com/$tenantId/oauth2/authorize?client_id=$applicationId&response_type=code&redirect_uri=$redirectUri&response_mode=query&resource=$resource&state=09876"

它同时在 PowerShell 中返回响应并同时在我的默认浏览器上打开一个网页。

下面是响应的样子:

StatusCode        : 200
StatusDescription : OK
Content           :

                    <!DOCTYPE html>
                    <html dir="ltr" class="" lang="en">
                    <head>
                        <title>Sign in to your account</title>
                        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
                        <meta http-eq...
RawContent        : HTTP/1.1 200 OK
                    Pragma: no-cache
                    Strict-Transport-Security: max-age=31536000; includeSubDomains
                    X-Content-Type-Options: nosniff
                    X-Frame-Options: DENY
                    x-ms-request-id: ed3ee9de-ccc4-47ea-ac52-087b...
Forms             : {}
Headers           : {[Pragma, no-cache], [Strict-Transport-Security, max-age=31536000; includeSubDomains],
                    [X-Content-Type-Options, nosniff], [X-Frame-Options, DENY]...}
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        : mshtml.HTMLDocumentClass
RawContentLength  : 22592

浏览器中显示的网页被重定向到https://login.microsoftonline.com/cookiesdisabled并显示以下消息:

我们无法让您登录您的浏览器当前设置为阻止 cookie。您需要允许 cookie 使用此服务。Cookie 是存储在您计算机上的小型文本文件,当您登录时会告诉我们。要了解如何允许 cookie,请查看您的网络浏览器中的在线帮助。

所以总结一下,它不起作用!

请注意,我的浏览器中启用了 cookie,如果我从 Web 浏览器调用 Web 请求,它将正常工作。

我究竟做错了什么?以及如何使用 PowerShell 向用户提示对话框并在 PowerShell 中接收授权代码响应?

谢谢你。

标签: powershellazureoauth-2.0azure-active-directory

解决方案


你是对的。这是因为 Poweshell 无法捕获随回复 URL 返回的授权代码。

解决方案:

您可以编写一个登录浏览器模块来充当随回复 URL 返回的授权代码的“假”端点。

尝试使用此示例

登录浏览器

Add-Type -AssemblyName System.Web
$outputAuth = ".\Code.txt"
$outputError = ".\Error.txt"

function LoginBrowser
{
    param
    (
        [Parameter(HelpMessage='Authorization URL')]
        [ValidateNotNull()]
        [string]$authorizationUrl,

        [Parameter(HelpMessage='Redirect URI')]
        [ValidateNotNull()]
        [uri]$redirectUri
    )

    # Create an Internet Explorer Window for the Login Experience
    $ie = New-Object -ComObject InternetExplorer.Application
    $ie.Width = 600
    $ie.Height = 500
    $ie.AddressBar = $false
    $ie.ToolBar = $false
    $ie.StatusBar = $false
    $ie.visible = $true
    $ie.navigate($authorzationUrl)

    while ($ie.Busy) {} 

    :loop while($true)
    {   
        # Grab URL in IE Window
        $urls = (New-Object -ComObject Shell.Application).Windows() | Where-Object {($_.LocationUrl -match "(^https?://.+)|(^ftp://)") -and ($_.HWND -eq $ie.HWND)} | Where-Object {$_.LocationUrl}

        foreach ($a in $urls)
        {
            # If URL is in the form we expect, with the Reply URL as the domain, and the code in the URL, grab the code
            if (($a.LocationUrl).StartsWith($redirectUri.ToString()+"?code="))
            {
                $code = ($a.LocationUrl)
                ($code = $code -replace (".*code=") -replace ("&.*")) | Out-File $outputAuth
                break loop
            }
            # If we catch an error, output the error information
            elseif (($a.LocationUrl).StartsWith($redirectUri.ToString()+"?error="))
            {
                $error = [System.Web.HttpUtility]::UrlDecode(($a.LocationUrl) -replace (".*error="))
                $error | Out-File $outputError
                break loop
            }
        }
    }

    # Return the Auth Code
    return $code
}

使用 AUTHCODE 休息

# Load ADAL
Add-Type -Path "..\ADAL\Microsoft.IdentityModel.Clients.ActiveDirectory.dll"

# Load our Login Browser Function
Import-Module ./LoginBrowser.psm1

# Output Token and Response from AAD Graph API
$accessToken = ".\Token.txt"
$output = ".\Output.json"

# Application and Tenant Configuration
$clientId = "<AppIDGUID>"
$tenantId = "<TenantID>"
$resourceId = "https://graph.windows.net"
$redirectUri = New-Object system.uri("<ReplyURL>")
$login = "https://login.microsoftonline.com"

# Create Client Credential Using App Key
$secret = "<AppKey>"

# Create Client Credential Using Certificate
#$certFile = "<PFXFilePath>"
#$certFilePassword = "<CertPassword>"
#$secret = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate -ArgumentList $certFile,$certFilePassword

# Note you can adjust the querystring paramters here to change things like prompting for consent
$authorzationUrl = ("{0}/{1}/oauth2/authorize?response_type=code&client_id={2}&redirect_uri={3}&resource={4}&prompt=consent" -f $login,$tenantId,$clientId,$redirectUri,$resourceId)
# Fake a proper endpoint for the Redirect URI
$code = LoginBrowser $authorzationUrl $redirectUri

# Get an Access Token with ADAL
$clientCredential = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential($clientId,$secret)
$authContext = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext("{0}/{1}" -f $login,$tenantId)
$authenticationResult = $authContext.AcquireToken($resourceId, $clientcredential)
($token = $authenticationResult.AccessToken) | Out-File $accessToken


# Call the AAD Graph API 
$headers = @{ 
    "Authorization" = ("Bearer {0}" -f $token);
    "Content-Type" = "application/json";
}

# Output response as JSON file
Invoke-RestMethod -Method Get -Uri ("{0}/{1}/users?api-version=1.6" -f $resourceId,$tenantId)  -Headers $headers -OutFile $output

推荐阅读