目前我正在与 MS Azure
on_behalf_of
流作斗争并面临此错误:
{
"error": "invalid_grant",
"error_description": "AADSTS50013: Assertion failed signature validation. [Reason - The key was not found., Please visit the Azure Portal, Graph Explorer or directly use MS Graph to see configured keys for app Id '00000000-0000-0000-0000-000000000000'. Review the documentation at https://docs.microsoft.com/en-us/graph/deployments to determine the corresponding service endpoint and https://docs.microsoft.com/en-us/graph/api/application-get?view=graph-rest-1.0&tabs=http to build a query request URL, such as 'https://graph.microsoft.com/beta/applications/00000000-0000-0000-0000-000000000000']. Trace ID: Correlation ID: Timestamp: 2024-09-25 10:37:05Z",
"error_codes": [
50013
],
"timestamp": "2024-09-25 10:37:05Z",
"trace_id": "",
"correlation_id": "",
"error_uri": "https://login.microsoftonline.com/error?code=50013"
}
我在做什么:
$ openssl req -newkey rsa -new -nodes -x509 -days 3650 -pkeyopt rsa_keygen_bits:4096 -keyout key.pem -out cert.pem
$ openssl x509 -pubkey -noout -in cert.pem > pubkey.pem
"keyCredentials": [
{
"customKeyIdentifier": "IDENTIFIER",
"displayName": "app-name",
"endDateTime": "2034-09-22T09:20:28Z",
"key": null,
"keyId": "key-uuid",
"startDateTime": "2024-09-24T09:20:28Z",
"type": "AsymmetricX509Cert",
"usage": "Verify"
}
]
client_credentials
POST https://login.microsoftonline.com/my-app-tenant-id/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=my-client-id
&client_secret=my-secret
&scope=api://my-client-id/.default
这工作正常,并返回给我一个看起来像这样的令牌:
{
"typ": "JWT",
"alg": "RS256",
"x5t": "",
"kid": ""
}
{
"aud": "api://my-client-id",
"iss": "https://sts.windows.net/my-app-tenant-id/",
"iat": 1727252274,
"nbf": 1727252274,
"exp": 1727256174,
"aio": "",
"appid": "my-client-id",
"appidacr": "1",
"idp": "https://sts.windows.net/my-app-tenant-id/",
"oid": "some-value",
"rh": "",
"sub": "some-value",
"tid": "my-app-tenant-id",
"uti": "",
"ver": "1.0"
}
assertion
。该断言用作POST https://login.microsoftonline.com/my-app-tenant-id/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&client_id=my-client-id
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=here-i-put-the-token-received-from-client-credentials-flow
&assertion=here-i-put-the-signed-assertion
&requested_token_use=on_behalf_of
&scope=api://my-client-id/default
这是我签字前的断言:
{
"iss" : "my-app-tenant-id",
"customerXRef" : "som-value",
"aud" : "https://login.microsoftonline.com/my-app-tenant-id/oauth2/v2.0/token"
}
这是我如何签名的(该代码适用于带有 Gravitee 的 OAuth):
String getToken() {
try {
var jwsHeader = new JWSHeader.Builder(alg)
.type(new JOSEObjectType(typ))
.keyID(kid) // here I put the same value as I have in `keyCredentials.keyId` above
.build();
var jwsObject = new JWSObject(jwsHeader, payload);
var privateKey = RsaKeyConverters.pkcs8().convert(new ByteArrayInputStream(this.privateKey));
var signer = new RSASSASigner(privateKey);
jwsObject.sign(signer);
return jwsObject.serialize();
} catch (JOSEException e) {
throw new RuntimeException(e);
}
}
我的问题是我做错了什么?
我查看了https://login.microsoftonline.com/error?code=50013但没有找到任何线索。
附注根据 @juunas 的建议,我修改了断言的标题,使其看起来像
{
"typ": "JWT",
"x5t#s256": "IDENTIFIER",
"alg": "RS256"
}
其中
IDENTIFIER
与 keyCredentials.customKeyIdentifier
的值完全相同,但我仍然收到 The key was not found.
错误消息
P.P.S。我发现,在 https://login.microsoftonline.com/my-app-tenant-id/discovery/keys 之后,我看不到我上传的证书。有什么想法吗?
典型流程是这样的:
原始代币
您获得了机器级访问令牌,这是代表流程可能失败的一个重要原因。请改为使用用户级访问令牌尝试您的请求。
客户凭证
这些参数代表高级客户端凭证。您的要求看起来不错:
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=here-i-put-the-signed-assertion
但也许可以尝试简化:
代表流量
流程的主要部分是在
assertion
参数中提供原始用户级别访问令牌。一旦客户端秘密起作用,您就知道任何剩余的问题都与客户端断言有关:
POST https://login.microsoftonline.com/my-app-tenant-id/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&client_id=my-client-id
&client_secrer=xxx
&requested_token_use=on_behalf_of
&scope=api://my-client-id/default