От имени выпуска токена (AADSTS50013: утверждение содержит недопустимую подпись)

Я получаю сообщение об ошибке (упомянутое ниже), когда пытаюсь использовать токен пользователя Cortana Bot (который является токеном Graph) для создания токена «от имени» для другого приложения-потребителя веб-API с использованием ClientAssertionCertificate / ClientCredential target другому потребляющему веб-API, передав его AppId как ResourceId и userAssertion, сгенерированный с помощью токена пользователя Cortana Bot.

При проверке наших настроек Bot AAD он настроен с другим потребляющим веб-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. Кортана просит пользователя войти в систему
  2. Вход пользователя в Кортану
  3. Кортана отправляет этот токен пользователя (созданный таргетинг для использования https://graph.microsoft.com в качестве аудитории) в Microsoft. API-интерфейс Bot Framework
  4. API Microsoft Bot Framework проверяет и хочет использовать этот токен для вызова другого веб-API (который называется API B).
  5. Поскольку этот токен пользователя Cortana нельзя использовать напрямую, его необходимо сгенерировать как токен от имени для API B из Microsoft Bot Framework API.
  6. Ниже приведен пример кода, который используется для создания токена от имени из API Microsoft Bot Framework:

    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;
    }
    
  7. Получение исключения, о котором говорилось выше на этом шаге:

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

person venu madhav    schedule 02.01.2019    source источник
comment
Добро пожаловать в Stack Overflow! Я настоятельно рекомендую прочитать Как задать хороший вопрос?, чтобы получить несколько советов по началу работы. Ваш вопрос в его нынешнем виде не содержит кода, показывающего, что делает ваше приложение или какие решения вы пробовали до сих пор.   -  person Marc LaFleur    schedule 02.01.2019
comment
docs.microsoft. com / en-us / azure / active-directory / develop / - учитывая приведенную здесь справочную таблицу, вы говорите, что получаете недопустимую подпись при вызове API B, когда вы передаете Auth Bearer с токеном обратного доступа? Добавьте вызывающий URL и заголовки.   -  person Micromuncher    schedule 02.01.2019
comment
@Micromuncher, вы правильно поняли, что мы хотим передать токен от имени пользователя API B через Auth Bearer. Но мы получаем вышеупомянутую ошибку при попытке сгенерировать токен от имени из токена, который был сгенерирован для API A в API B с использованием библиотек Microsoft.IdentityModel .Net SDK.   -  person venu madhav    schedule 03.01.2019
comment
@Marc LaFleur, я добавил дополнительную информацию, которую вы ищете из описания ...   -  person venu madhav    schedule 03.01.2019
comment
Вы как арендатор пробовали обыкновенного? cloudidentity.com/blog/2014/08/26/   -  person Micromuncher    schedule 03.01.2019
comment
@Micromuncher, я попытался изменить клиента на «общий», но все равно получаю ту же ошибку. Утверждение содержит недопустимую подпись.   -  person venu madhav    schedule 04.01.2019
comment
Интересно, что вы извлекаете идентификатор ресурса, потому что в мире oauth2 и конвергентной конечной точке Microsoft (aadv2) вам не нужно этого делать. Вы смешиваете запросы aadv1 и aadv2?   -  person Micromuncher    schedule 08.01.2019
comment
@Micromuncher, да, вы правильно поняли, что мы смешиваем AADv1 (токен, полученный от Cortana, создается с помощью AAD v1) с AAD v2 (токен, запрошенный API B).   -  person venu madhav    schedule 14.01.2019


Ответы (2)


Насколько я понимаю: сначала вы получаете токен пользователя из API-интерфейса MS Graph доступа Cortana; а затем вы хотите использовать токен пользователя для создания токена OBO в API Microsoft Bot Framework; наконец, вы хотите использовать токен OBO для доступа к API B из Microsoft Bot Framework API.

Если вы хотите получить токен OBO в API Microsoft Bot Framework, вы должны использовать идентификатор API и секрет, для этого я никогда не пробовал.

Со своей стороны, я использую конечную точку v1, я создаю два API (API A и B), и мой поток: во-первых, мое приложение запрашивает token1 для API A;

введите здесь описание изображения Затем используйте token1, чтобы запросить OBO token2 для API B из API A;

введите здесь описание изображения

Наконец, используйте токен OBO2, чтобы запросить токен OBO3 для API графа AD из API B.

введите здесь описание изображения

Для конечной точки OBO в v1 прочтите ссылка1.

Для конечной точки OBO в версии 2 прочтите ссылка2.

person SunnySun    schedule 11.01.2019
comment
@venu madhav, если что-нибудь обновится, пожалуйста, дайте мне знать, спасибо. - person SunnySun; 14.01.2019
comment
@ SunnySun, спасибо за ответ. В предоставленном выше потоке вы генерируете токены для API A и B (надеясь, что эти два API настроены для одного и того же приложения AAD). Но в нашем случае мы получаем токен от Cortana, который нам нужно использовать для генерации токена OBO для API B, используя учетные данные сертификата или секрет клиента для нашего приложения Bot AAD, где API B настроен с разрешениями авторизации). - person venu madhav; 14.01.2019

Мы могли бы решить эту проблему, настроив область «user_impersonation» нашего зависимого настраиваемого API (API B) на конфигурацию канала Cortana для нашего бота. С этим изменением конфигурации нам не нужно генерировать токен On-Behalf-Of для API B из нашего приложения Microsoft Bot.

Спасибо всем, кто поддержал решение этой темы ...

person venu madhav    schedule 17.01.2019