Токен носителя не работает при вызове веб-API в Azure

У меня возникают проблемы с работой вызовов приложений API из моего веб-приложения в Azure. Вот как все устроено -

  1. Веб-приложение Asp.Net Core 1.1, защищенное аутентификацией Azure AD — выполняется локально с помощью Kestrel

StartUp.cs веб-приложения имеет следующий код для получения токена в веб-API.

        app.UseCookieAuthentication(); 
        app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
        {
            ClientId = ClientId, //Client Id of my current web app
            ClientSecret = ClientSecret, //ClientSecret of my current web app
            Authority = "https://login.microsoftonline.com/tenantguid",                CallbackPath = Configuration[Constants.ApplicationProxyCallbackPath],
            ResponseType = OpenIdConnectResponseType.CodeIdToken,
            Events = new OpenIdConnectEvents
            {
                OnAuthorizationCodeReceived = OnAuthorizationCodeReceived,
                OnRemoteFailure = OnAuthenticationFailed
            }
        });

Для метода OnAuthorizationCodeReceived это мой код

private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext context)
    {
        string userObjectId = (context.Ticket.Principal.FindFirst(Constants.ClaimsSchemaUri))?.Value;
        ClientCredential clientCred = new ClientCredential(ClientId, ClientSecret);
        AuthenticationContext authContext = new AuthenticationContext(Authority, new NaiveSessionCache(userObjectId, context.HttpContext.Session));
        AuthenticationResult authResult = await authContext.AcquireTokenByAuthorizationCodeAsync(
            context.ProtocolMessage.Code,
            new Uri(context.Properties.Items[OpenIdConnectDefaults.RedirectUriForCodePropertiesKey]),
            clientCred,
            WebAPIClientId);        
     }

Используя приведенный выше код, я могу успешно получить токен на предъявителя.

  1. Класс контроллера, в котором я делаю вызов WebApi

        Task<string> results = null;
        string resultSet = String.Empty;
        AuthenticationResult authResult = null;
    
        string userObjectID = (currentUser.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier"))?.Value;
        AuthenticationContext authContext = new AuthenticationContext(Startup.Authority, new NaiveSessionCache(userObjectID, current.Session));
        ClientCredential credential = new ClientCredential(Startup.ClientId, Startup.ClientSecret);
        authResult = await authContext.AcquireTokenSilentAsync(Startup.SearchAPIClientId, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
    
        //var callerIdentity = currentUser.Identity as WindowsIdentity;
        HttpClientHandler handler = null;
    
        //Setup async action
        Action action = () => {
    
            handler = new HttpClientHandler() { AllowAutoRedirect = true };
    
            //Setup for windows authentication
            var client = new HttpClient(handler);
    
            //Add common http headers
            client.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
            client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate");
            client.DefaultRequestHeaders.Add("Accept-Language", "en-US,en;q=0.8");
            client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36");
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
    
            results = client.GetStringAsync("https://myapi.azurewebsites.net/api/search/");
        };
    
        action.Invoke();
    
        resultSet = await results as string;
    

Вызов API перенаправляется на login.microsftonline.com, что означает, что мой токен не был понят.

  1. Веб-API защищен с помощью проверки подлинности Azure с использованием пакета OpenIdConnect в коде, точно так же, как код веб-приложения выше.

Я просмотрел несколько связанных сообщений, но ничего не работает нормально.

Обновление 1 — веб-API обновлен для использования аутентификации JWTBearer. Теперь токен носителя, полученный в веб-приложении, может успешно аутентифицировать меня в веб-API.

Ожидается, что мой веб-API вызовет другой пользовательский API, который также защищен аутентификацией Azure AD. Я хочу получить токен для того же самого, но для того, чтобы инициировать это, у меня возникает проблема при использовании токена приобретения для дополнительного пользовательского API. Он бросает Internal Server 500 без сообщения. Есть предположения?

Обновление 2 — Подробная ошибка. При попытке получить токен для третьего API я получаю следующее исключение: "AADSTS50105: приложение "идентификатор исходного клиента" не назначено роли для приложения "целевой клиент". идентификатор гида».


person Nitin Rastogi    schedule 23.08.2017    source источник
comment
Можете ли вы получить доступ к этому API от Postman после предоставления Authorization заголовка с токеном носителя?   -  person Venky    schedule 23.08.2017
comment
Нет, я не могу. Используя токен, сгенерированный в приведенном выше коде, я не могу позвонить с помощью Postman.   -  person Nitin Rastogi    schedule 23.08.2017
comment
вы получаете 401 или любое другое сообщение об ошибке? Если токен действителен, вы сможете позвонить от Почтальона.   -  person Venky    schedule 23.08.2017
comment
Я вижу ошибку 302 на login.microsoftonline.com   -  person Nitin Rastogi    schedule 23.08.2017


Ответы (1)


Проблема была исправлена, и это то, что я должен был сделать.

  1. Изменения аутентификации приложений API

    • Changed the authentication scheme to be through JWTBearer
    • Это позволило мне принять токен носителя из веб-приложения, и теперь аутентификация веб-приложения для приложения Api работает по мере необходимости.
  2. Изменения кода приложения API

    • As API app was calling another downstream API App, I had to use AcquireTokenAsync passing in following details - ClientId, ClienCredentials and Access Token received from Web App earlier. This token is used to construct a UserAssertion

С указанными выше изменениями вызов из веб-приложения --> приложение API --> приложение Downstream API работает нормально.

person Nitin Rastogi    schedule 25.08.2017