【问题标题】:How to use PowerShell to open and receive response from authorization dialog of Azure Active Directory OAuth Authorization Code Grant Flow如何使用 PowerShell 打开并接收来自 Azure Active Directory OAuth 授权代码授予流程的授权对话框的响应
【发布时间】:2018-11-03 09:11:22
【问题描述】:

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

遵循授权代码授予流程documentation from 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,如果我从网络浏览器调用网络请求,它将正常工作。

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

谢谢。

【问题讨论】:

    标签: powershell azure oauth-2.0 azure-active-directory


    【解决方案1】:

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

    解决方案:

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

    尝试使用this Example

    登录浏览器

    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 的 REST

    # 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
    

    【讨论】:

      猜你喜欢
      • 2015-05-22
      • 2018-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 2019-08-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多