You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用PowerShell实现Azure AD OAuth授权码流并接收授权响应

问题原因分析

你遇到的核心问题是**Invoke-WebRequest和弹出的浏览器属于完全独立的会话**:

  • Invoke-WebRequest会在后台创建自己的HTTP会话(包含专属Cookie池),但它触发的浏览器窗口是独立进程,用的是浏览器自身的会话,和PowerShell的后台会话完全不共享。
  • Azure AD的授权流程要求会话一致性,检测到两次请求(PowerShell的后台请求、浏览器的交互请求)会话不匹配时,就会误判为Cookie被禁用,哪怕你浏览器本身已经开启了Cookie功能。
正确实现方案

要完成「弹出授权对话框+脚本接收授权码」的需求,你需要拆成两步操作:

  1. 直接调用系统默认浏览器打开授权URL(绕过Invoke-WebRequest的后台会话)
  2. 在本地启动临时HTTP服务器,监听Azure AD回调的redirect_uri,从中提取授权码

完整示例脚本

# 配置你的Azure AD应用参数
$tenantId = "你的租户ID"
$applicationId = "你的应用注册ID"
$redirectUri = "http://localhost:8080/callback" # 必须在Azure AD应用中提前配置
$resource = "https://graph.microsoft.com" # 要访问的目标资源,比如Microsoft Graph API
$state = [Guid]::NewGuid().ToString() # 生成随机GUID,用于防止CSRF攻击

# 启动本地HTTP监听器,等待授权回调
$listener = New-Object System.Net.HttpListener
$listener.Prefixes.Add($redirectUri + "/")
$listener.Start()
Write-Host "正在等待授权回调...请在弹出的浏览器中完成登录授权"

# 用默认浏览器打开授权URL(自动编码特殊字符避免解析错误)
$authUrl = "https://login.microsoftonline.com/$tenantId/oauth2/authorize?client_id=$applicationId&response_type=code&redirect_uri=$([Uri]::EscapeDataString($redirectUri))&response_mode=query&resource=$([Uri]::EscapeDataString($resource))&state=$state"
Start-Process $authUrl

# 接收回调请求并处理
$context = $listener.GetContext()
$request = $context.Request
$response = $context.Response

# 安全验证:检查state参数是否匹配,防止CSRF攻击
if ($request.QueryString["state"] -ne $state) {
    $response.StatusCode = 400
    $buffer = [Text.Encoding]::UTF8.GetBytes("State参数不匹配,存在CSRF风险")
    $response.OutputStream.Write($buffer, 0, $buffer.Length)
    $response.Close()
    $listener.Stop()
    exit 1
}

# 提取授权码
$authorizationCode = $request.QueryString["code"]
if (-not $authorizationCode) {
    $errorMsg = $request.QueryString["error_description"] ?? "未获取到授权码"
    $response.StatusCode = 400
    $buffer = [Text.Encoding]::UTF8.GetBytes("授权失败:$errorMsg")
    $response.OutputStream.Write($buffer, 0, $buffer.Length)
    $response.Close()
    $listener.Stop()
    exit 1
}

# 给浏览器返回成功提示
$buffer = [Text.Encoding]::UTF8.GetBytes("授权成功!请返回PowerShell继续执行。")
$response.OutputStream.Write($buffer, 0, $buffer.Length)
$response.Close()
$listener.Stop()

# 输出授权码,后续可用于获取访问令牌
Write-Host "成功获取授权码:$authorizationCode"

关键注意事项

  • 配置redirect_uri:必须在Azure AD应用注册的「身份验证」->「平台配置」中添加http://localhost:8080/callback(或你自定义的本地地址),否则Azure AD会拒绝回调请求。
  • 端口选择:建议使用1024以上的端口(比如示例中的8080),低于1024的端口需要管理员权限才能监听。
  • URL编码:用[Uri]::EscapeDataString()对redirect_uri和resource进行编码,避免特殊字符导致的URL解析错误。

内容的提问来源于stack exchange,提问作者hendryanw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:31:45