调用Graph API addKey添加应用证书时提示Access Token缺失或格式错误求助
问题描述
我正尝试通过Graph API向应用注册(App Registration)添加新证书,操作基本参照这篇文章的步骤执行,同时参照这篇文档的说明生成了令牌。我计划使用PowerShell Core实现,操作代码如下:
$signingCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("${certPath}${certName}", "$certPassword") $signingCreds = New-Object Microsoft.IdentityModel.Tokens.X509SigningCredentials($signingCert) $claimsDict = New-Object System.Collections.Generic.Dictionary"[String,Object]" $claimsDict."aud" = "00000002-0000-0000-c000-000000000000" # 这是我用于发起Graph API调用的应用注册ID,不是应用ID(我也试过用应用ID),是通过Get-MgApplication获取的Graph ID $claimsDict."iss" = "9db7dfa6-4f4c-430b-a573-d64d5dc172fd" $securityToken = New-Object Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor $securityToken.claims = $claimsDict $securityToken.NotBefore = [datetime]::now $securityToken.Expires = [datetime]::now.AddMinutes(10) $securityToken.SigningCredentials = $signingCreds $handler = New-Object Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler $token = $handler.CreateToken($securityToken)
接下来我将该令牌作为proof参数放入POST请求中,代码如下:
$certData = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("${certPath}${newCertName}") $bodyParameter = @{ "keyCredential" = @{ "type" = "AsymmetricX509Cert"; "usage" ="Verify"; "key" = [System.Convert]::ToBase64String($certData.RawData) }; "passwordCredential" = $null; "proof" = $token } ConvertTo-Json $bodyParameter
生成的请求体JSON格式如下:
{ "proof": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjZFOEU3ODRGQ0ZGREQyQzY5RTI3RDQ2OEM4QjgxNEU3QzRFRDgwOEIiLCJ0eXAiOiJKV1QiLCJ4NXQiOiJibzU0VDhfOTBzYWVKOVJveUxnVTU4VHRnSXMifQ.eyJhdWQiOiIwMDAwMDAwMi0wMDAwLTAwMDAtYzAwMC0wMDAwMDAwMDAwMDAiLCJpc3MiOiI5ZGI3ZGZhNi00ZjRjLTQzMGItYTU3My1kNjRkNWRjMTcyZmQiLCJleHAiOjE2MzM5ODIwMjEsIm5iZiI6MTYzMzk4MTQyMSwiaWF0IjoxNjMzOTgxNDIyfQ.a__8to9Mav7r5to85O8PMHzUaz5el_VhsJQ6ahqHqdJRQ2TlcPDuNVEcUc1qHyq7pNaQid0LdnbR8s4Bt5ulZJBGRjXmf64cgPQFOGJFl2TQAneZlhoB_6zVQBwGPCnLL4EZHybT6GwTFhVYKvAiCK3HVdQUgTkVUEsGNKLjUtBzYNGgqxFWoOwKt-uZM7yCALYt2BHH2G8P0KroZEYmUZEU1KcSh1UqyEPg--Pr6qu4CwxFwurtNhmysiYMM3e7vdpIFPaJOT52hKeeppP-lAFsTkeoWQSD0G5Cvwl-HPU2A7uWHgQaZzer2htt5Xeys3woHhcNSHJgHRmceud7fSRMRbctexywlXzeclCOQjWOBYXAWAkIH3gzXbBZ6TomfgR6-EIenXwaxtADHnoflvQKsnclXQLF8BQ69Lw6UaxPBLG6EC1KMC4b_BLaR5E6P5FYf7E4WoljqwtiqD-3DwzQ_0PXBABFqHYV9JtW7cq1skA3pyc9XbUm1PHTh5Z0p7VC2lXRJ00MLuZiDAQxOPjV7RH-VucQZJcvZ06Wbz62hKDEbmKLWfq0BqCgjPPQQfQWsrEeN_eJ4INqrAWh_LWJ-utaiB9hNFq4qe-AvaPulKoIBYRkIb8j_dclR6DWRbvklNOgQ2rg6G56Mk96i_PJZq2afeJW-ocj67o72hk", "passwordCredential": null, "keyCredential": { "key": "MIIFXzCCA0egAwIBAgIJAI0jxh5R52r8MA0GCSqGSIb3DQEBCwUAMDAxLjAsBgNVBAMTJURlbnRvbnMgRGlnaXRhbCAtIFVzZXIgUmVhZCBXcml0ZSBBbGwwHhcNMjEwNzE5MTIyODA0WhcNMjMwNzE5MTIyODA0WjAwMS4wLAYDVQQDEyVEZW50b25zIERpZ2l0YWwgLSBVc2VyIFJlYWQgV3JpdGUgQWxsMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4dz5yNsCsFGAI28NNwpSaI9rxazjHK3yy4OJdjO9vfgNc+mAq+Rc8R6fO0A6cw9NNxy9AEnbJhJiQxgW0Q+JPha2oWiordNNn9d/i9gY5nGDdc6G8xog8JmMiWC7pmW9Ylyweqncp8DL6C8imfv9tMoYCgD+TSbMVqIAYfSR2oCrF8Q5Lwilo+yptrCykaxqKQS8mURLH4JJMB79qzpDK1urkSU2sHP+lYdENlP80qQgo0HzLNuwHxqidw+bueRH/3CSmmgajmYX8V+8DmeJca+R2NHQthC/SR8kKp4A99eIvJ8Fr0AZTdpjqkNrqjXlNsJxp+LLEFIlpnIB/ekuCtBRY8w4vIdh1HWN9LX52Fc/YZLaHxc0crZZHCGOLAljIj2GFcoOAv3wOuD7W5fZguSjnsiLJQwAgbyjbAenMu3ev34Q9TCkqtbKdqqBqDTGceOc2ugkWOGLmAR07MGzSAL7BA2iJ4hEkp5i3f0FmWfs/yHTIL7CeRkbgmfw/vt2clJd+U+kXR2E0LVL4H+UmA0rXd81LgE9wb5QxQ49WlQuDSeK7TfD5dCgqnFyMObD33GOH23CpBkLzkP/ugTHafHNzR0w95KXbap/dlP/Rr7Wi8oHuNv77j/7y31Q+hHQvosU3RYbsYrytdFNMDOsD11hxIskUJ7w9ZdlSDP/O18CAwEAAaN8MHowCwYDVR0PBAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBQySMBv+J3sXXsYdlbNn3r8DWQW6DAfBgNVHSMEGDAWgBQySMBv+J3sXXsYdlbNn3r7DWQW6DANBgkqhkiG9w0BAQsFAAOCAgEAn7V6TKQeQsqb0elbOf29VC2fBmqHY+WJRxcaUS0fbMsCDLVK2LN+0vVbiT5CBEXq0hDQAoSoTT79ILWRPFQegEjQjFmLJCz2RK+yf6kSplNnOiIA8+nstaVQDWcTCarkIQ98xhoPUkMGhVCx2nbtsBsc+FOnx7+zO1SCSxFda/xIEeBV4n/40cEWcXRIZQQOjqdta5fTMstiKSqLJhu2ex/M8zg1jXvJooLs0Ya0GtyPzOLuIhSlW1290YekrZqIcuLe++hjhcjDerfr9sTJan7xlbBPx4O182uIX9WQRX454osXgf7yH0GoqhdOqU9ULi23m9YwxDZUMk2akg2IVbVjGN+/H9BcYfbK8nZGWwTChK+S4DFAWdg13RA6ukfK21HRrhXBQzkq1d1fVBFmCpK5ZG0msBKHovXyjgdTfF6RJS46796NZBiLOetf+pFtqusUI8jlXYbw/WUe/LlAka6oRLXy+K+HAtOwwbAVwoHrKmhc0d2R+m49l/mEKjL7DLhDmlAzQfgnofSaDCvFQXLaVr+0bM2WzLVju/hILN58u6JWjNTIe/+tXUiP8hpWwWC6Lrh7gWWHhCy3DPReRZkIr11Q3HEpFKnc6lHJEo3pOesc1KvWKptQQBflPNlRmSzcy1Ugi9CCXw4FYfhq1p667zm3JDJ7p2jlRb0wisQ=", "type": "AsymmetricX509Cert", "usage": "Verify" } }
在我看来这个请求格式是正确的,和微软官方文档的示例一致。我将proof令牌放入https://jwt.ms这类JWT解码器中解析,结果也显示正常:
{ "alg": "RS256", "kid": "6E8E784FCFFDD2C69E27D468C8B814E7C4ED808B", "typ": "JWT", "x5t": "bo54T8_90saeJ9RoyLgU58TtgIs" }.{ "aud": "00000002-0000-0000-c000-000000000000", "iss": "9db7dfa6-4f4c-430b-a573-d64d5dc172fd", "exp": 1633982021, "nbf": 1633981421, "iat": 1633981422 }.[Signature]
证书指纹和应用注册中已有的证书一致,该证书就是我按照文档要求用来签名令牌的证书。
但我使用上述$bodyParameter JSON发起请求时,收到了如下报错:
{ "error": { "code": "Authentication_MissingOrMalformed", "message": "Access Token missing or malformed.", "innerError": { "date": "2021-10-11T19:44:46", "request-id": "1177fc83-1342-4a3d-82f8-172b452f8471", "client-request-id": "1177fc83-1342-4a3d-82f8-172b452f8471" } } }
不管是用Postman这类工具,还是调用Invoke-MgGraphRequest -Method POST -Uri "https://graph.microsoft.com/v1.0/applications/$appId/addKey" -Body (ConvertTo-Json $bodyParameter),或是Add-MgApplicationKey -ApplicationId $appId -BodyParameter $bodyParameter都会触发该报错。
我看到这篇帖子里有人成功使用了该接口,说明问题出在我的操作上。请问我可能哪里操作有误?
解决方案
- 首先修正
aud(受众)参数:你当前填的00000002-0000-0000-c000-000000000000是旧版Azure AD Graph的客户端ID,你调用的是Microsoft Graph接口,需要将aud的值改为https://graph.microsoft.com。 - 修正
iss(签发者)参数:iss需要填写你要修改的目标应用注册的客户端ID(Application ID/Client ID),不是你通过Get-MgApplication拿到的对象ID(Object ID)。 - 替换本地时间为UTC时间:避免本地时间和Azure服务时间差超过5分钟导致令牌校验失败,将
[datetime]::now改为[datetime]::UtcNow。 - 确认签名证书状态:用来生成proof令牌的证书必须已经上传到目标应用注册的「证书和密码」列表中,且状态为有效未过期,证书的密钥用法需要包含数字签名。
- 调用接口时注意不要额外加Bearer授权头:addKey接口通过请求体中的proof参数完成身份校验,不需要在请求头中传入常规的Graph访问令牌,如果你之前加了需要移除。
内容的提问来源于stack exchange,提问作者rakhesh
相关产品推荐
相关产品推荐

