代表代币发行(AADSTS50013: Assertion contains an invalid signature)

On behalf of token issue (AADSTS50013: Assertion contains an invalid signature)

当我尝试使用 Cortana Bot 用户令牌(这是一个 Graph 令牌)为另一个消费网站生成 "on-behalf-of" 令牌时出现错误(如下所述)API 应用程序使用 ClientAssertionCertificate / ClientCredential 通过将其 AppId 作为 ResourceIduserAssertion 传递给另一个消费 Web API 通过使用 Cortana Bot 用户生成令牌。

当检查我们的 Bot AAD 设置时,它与其他消费 Web API (API B) 一起配置为有效应用程序以及 Graph 应用程序。我们是否需要在 AAD 中进行任何其他设置才能获得此代表令牌?

AADSTS50013: Assertion contains an invalid signature. 
[Reason - The provided signature value did not match the expected signature value., 
    Thumbprint of key used by client: '9DB0B05B5D70DD7901FB151A5F029148B8CC1C64', 
    Found key 'Start=11/11/2018 00:00:00, 
    End=11/11/2020 00:00:00'
]
Trace ID: a440869f-b8f5-4d87-ba1a-6bd8dd7ba200
Correlation ID: 651e1fa8-2069-4489-a687-e68e5206e193
Timestamp: 2019-01-02 07:14:45Z

以下是我们如何尝试为其他消费网站获取代表令牌的流程和示例代码API (API B)。

流程步骤:

  1. Cortana 要求用户登录
  2. 用户登录 Cortana
  3. Cortana 将此用户令牌(生成的目标使用 https://graph.microsoft.com 作为受众)发送到 Microsoft Bot Framework API
  4. Microsoft Bot Framework API 验证并希望使用此令牌来调用其他 Web API(称为 API B)。
  5. 由于无法直接使用此 Cortana 用户令牌,因此需要从 Microsoft Bot Framework API.
  6. 生成 API B 的代表令牌
  7. 以下是用于从 Microsoft Bot Framework 生成代表令牌的代码示例 API:

    public async Task<string> GetOnBehalfOfTokenAsync(string authority, string resource, string scope = "", string token = "") 
    {
        AuthenticationResult output;
        var clientId = ConfigurationManager.AppSettings["API-B-ClientId"];
    
        // Read certificate which can be used for getting token to API B using ClientAssertionCertificate
        // GetCert() is used to get the Certificate based on Thumbprint configured in Web.config file.
        var certificate = this.GetCert();
    
        // 'authority' is https://login.microsoftonline.com/{tenant id}
        var authContext = new AuthenticationContext(authority);
        var cllientCertificateCredential = new ClientAssertionCertificate(clientId, certificate);
    
        // 'token' is the user token which was received from Cortana.
        var userAssertion = (!string.IsNullOrWhiteSpace(token)) ?
            new UserAssertion(token, "urn:ietf:params:oauth:grant-type:jwt-bearer", 
                TokenHelper.ExtractUserInfoFromAuthToken(token, "upn")) : null;
        try 
        {
            // 'resource' is the Resource Id of API B
            // if UserAssertion is null then get token with ClientAssertionCertificate else get 
            // on-behalf-of token using UserAssertion and ClientAssertionCertificate
            if (userAssertion == null) 
            {
                output = await authContext
                    .AcquireTokenAsync(resource, cllientCertificateCredential)
                    .ConfigureAwait(false);
            }   
            else 
            {
                output = await authContext
                    .AcquireTokenAsync(resource, cllientCertificateCredential, userAssertion)
                    .ConfigureAwait(false);
            }
        } 
        catch (Exception ex) 
        {
            logger.log("Error acquiring the AAD authentication token", ex);
        }
    
        return output.AccessToken;
    }
    
  8. 在这一步出现上面提到的异常:

    output = await authContext
       .AcquireTokenAsync(resource, cllientCertificateCredential, userAssertion)
        .ConfigureAwait(false);
    

我的理解是:首先你从你的 Cortana 访问 ms 图表中获取用户令牌 API;然后您想使用用户令牌在 Microsoft Bot Framework API 中生成 OBO 令牌;最后,您想使用 OBO 令牌从 Microsoft Bot Framework API.

访问 API B

您想在 Microsoft Bot Framework API 中获取 OBO 令牌,您应该使用 API id 和密码,为此,我从未尝试过。

在我这边,我使用 v1 端点,我创建了两个 API(API A 和 B),我的流程是: 首先,我的应用程序为 API A 请求 token1;

接下来,使用令牌 1 从 API A 请求 API B 的 OBO 令牌 2;

最后,使用 OBO 令牌 2 向 API B.

请求广告图 API 的 OBO 令牌 3

对于 v1 端点中的 OBO,请阅读 link1

对于 v2 端点中的 OBO,请阅读 link2

我们可以通过将依赖自定义 API (API B) "user_impersonation" 范围配置到我们的机器人的 Cortana 通道配置来解决此问题。通过此配置更改,我们不需要从我们的 Microsoft Bot 应用程序生成 API B 的代表令牌。

感谢所有支持为此线程提供解决方案的人...