如何用PowerShell的Invoke-RestMethod通过证书获取Microsoft Graph访问令牌
使用PowerShell的Invoke-RestMethod通过证书获取Microsoft Graph访问令牌
核心逻辑说明
通过证书获取Graph访问令牌的核心是生成客户端断言(client_assertion)——这是一个用证书私钥签名的JWT,用来替代客户端密钥完成身份验证。以下是基于Invoke-RestMethod的完整实现:
1. 准备证书
确保你持有对应应用注册的证书(需包含可用私钥),可从本地证书存储获取或导入PFX文件:
# 从当前用户证书存储获取证书(替换为你的证书指纹) $certThumbprint = "YOUR_CERT_THUMBPRINT" $cert = Get-ChildItem -Path Cert:\CurrentUser\My | Where-Object {$_.Thumbprint -eq $certThumbprint} # 若证书不在存储中,从PFX文件导入(替换路径和密码) # $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("path/to/your/cert.pfx", "PFX_PASSWORD")
2. 生成客户端断言(JWT)
客户端断言需要包含指定格式的头部和负载,并用证书私钥签名:
# 定义JWT头部(alg固定为RS256,kid为证书指纹,需去除空格) $header = @{ alg = "RS256" kid = $cert.Thumbprint.Replace(" ", "") typ = "JWT" } | ConvertTo-Json -Compress # 定义JWT负载 $tenantId = "YOUR_TENANT_ID" $clientId = "YOUR_APP_ID" $tokenEndpoint = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" $now = [DateTimeOffset]::UtcNow $payload = @{ iss = $clientId sub = $clientId aud = $tokenEndpoint exp = $now.AddSeconds(3600).ToUnixTimeSeconds() # 令牌1小时后过期 nbf = $now.ToUnixTimeSeconds() jti = [Guid]::NewGuid().ToString() } | ConvertTo-Json -Compress # 自定义Base64Url编码函数(符合JWT规范) function ConvertTo-Base64Url { param([string]$input) $bytes = [System.Text.Encoding]::UTF8.GetBytes($input) $base64 = [System.Convert]::ToBase64String($bytes) return $base64.Replace('+', '-').Replace('/', '_').TrimEnd('=') } $encodedHeader = ConvertTo-Base64Url $header $encodedPayload = ConvertTo-Base64Url $payload $unsignedJwt = "$encodedHeader.$encodedPayload" # 用证书私钥签名JWT $privateKey = $cert.PrivateKey $signatureBytes = $privateKey.SignData([System.Text.Encoding]::UTF8.GetBytes($unsignedJwt), [System.Security.Cryptography.HashAlgorithmName]::SHA256, [System.Security.Cryptography.RSASignaturePadding]::Pkcs1) $encodedSignature = ConvertTo-Base64Url ([System.Convert]::ToBase64String($signatureBytes)) # 最终生成客户端断言 $clientAssertion = "$unsignedJwt.$encodedSignature"
3. 调用令牌端点获取访问令牌
通过Invoke-RestMethod发送POST请求获取令牌:
# 构造请求参数 $body = @{ client_id = $clientId scope = "https://graph.microsoft.com/.default" grant_type = "client_credentials" client_assertion_type = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" client_assertion = $clientAssertion } # 发送请求并获取响应 $tokenResponse = Invoke-RestMethod -Uri $tokenEndpoint -Method Post -ContentType "application/x-www-form-urlencoded" -Body $body # 提取访问令牌 $accessToken = $tokenResponse.access_token Write-Host "获取到的Microsoft Graph访问令牌:$accessToken"
关键注意事项
- 应用注册中需已上传该证书的公钥(在「证书和密码」选项卡添加)
- 应用需配置对应的Microsoft Graph应用权限,且已获得管理员同意
- 证书必须包含私钥(从PFX导入时需确保密码正确且私钥可访问)
内容的提问来源于stack exchange,提问作者John Ranger
相关产品推荐
相关产品推荐

