Интеграция Ocelot с аутентификацией Azure Active Directory .Net Core 3.1

Контекст. Моя компания переходит на шлюз API, чтобы управлять всеми нашими услугами или услугами в нашей сети. Каждая служба в настоящее время аутентифицируется с помощью лазурного AD. Все является одним арендатором и позволяет пользователям компании. Вопрос: Я правильно понимаю? Проблема: когда я вызываю http: localhost: 5000 / authResource / get, я получаю ответ 401 от Ocelot. После отслеживания ошибки я вижу, что возвращаю значение null, когда промежуточное ПО Ocelot Authentication пытается пройти аутентификацию с использованием схемы AzureADJwtBearer.

Я последовал совету из вопросов, связанных с Ocelot и лазурной рекламой, но даже после этого я не могу заставить что-либо работать. (В основном из этого ответа: Как настроить Ocelot Api Gateway с Azure Active Directory) Я думаю, что неправильно понимаю, как должна работать аутентификация. На данный момент я понимаю, что я говорю Ocelot пройти аутентификацию на одном из моих Apis с использованием схемы AzureADJwtBearer. В моей конфигурации у меня есть информация для этого конкретного установленного API (ClientId, TenantId и т. Д.).

Как только я вызываю маршрут, я ожидаю, что Ocelot позвонит в Microsoft, чтобы начать аутентификацию. На этом этапе я ожидаю того же потока, что и Apis, то есть я звоню и получаю страницу входа в Microsoft, которая затем перенаправляет меня обратно в приложение, как только я ввожу свое имя пользователя и пароль.

Я думаю, после перенаправления меня обратно в Ocelot (это та часть, в которой я не уверен), я ожидаю, что ocelot сохранит токен доступа, который Microsoft отправляет обратно ДЛЯ КОНКРЕТНЫХ РЕСУРСОВ, которые я ПРОСТО ЗАПРОСИЛ. Затем я ожидаю, что ocelot прикрепит токен к заголовку Auth, а затем отправит запрос на ресурс, который я изначально запрашивал.

Чтобы прояснить это, я включу код, который у меня есть для файлов запуска, и файл ocelot.json. Из Startup.cs

public void ConfigureServices(IServiceCollection services)
        {

            services.AddProtectedWebApi(Configuration)
                .AddProtectedApiCallsWebApis(Configuration)
                .AddInMemoryTokenCaches();
            services.AddOcelot(Configuration);
            services.AddControllers();
        }

Также из Startup.cs

 public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });

            app.UseOcelot().Wait();


            app.UseAuthentication();
        }

Мой файл ocelot.json для аутентифицированного ресурса выглядит следующим образом (имена изменены по соображениям безопасности):

{
      "DownstreamPathTemplate": "/api/Controller/Get",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 5003
        }
      ],
      "UpstreamPathTemplate": "/authResource/get",
      "UpstreamHttpMethod": [ "GET" ],

      "AuthenticationOptions": {
        "AuthenticationProviderKey": "AzureADJwtBearer",
        "AllowedScopes": []
      }
    }

Чтобы прояснить, как я это понимаю, я рассмотрю пример, использующий образец api, показанный в конфигурации ocelot.

Я хочу получить доступ к ресурсу http://localhost:5003/api/Controller/Get, который является защищенный API, означающий, что я могу получить ответ только в том случае, если я предоставлю заголовок авторизации с моим запросом на получение. Я делаю запрос через свой шлюз ocelot для URL-адреса http://localhost:5000/authResource/get (Я размещаю Ocelot на localhost: 5000). Ocelot видит, что для доступа к этому ресурсу требуется аутентификация, поэтому он делает запрос, используя схему AzureADJwtBearer. Я перенаправлен в Microsoft для входа в систему. После этого меня отправляют обратно в приложение Ocelot с токеном доступа на буксире. Ocelot берет это, создает заголовок Auth и, наконец, вызывает http://localhost:5003/api/Controller/Get и возвращает результат.


person CRamsey    schedule 15.02.2020    source источник
comment
Это именно то, на что я рассчитываю, прочитав об оцелоте. Я собираюсь начать работать над этим для своего приложения. Вы заставили его работать?   -  person Tony    schedule 23.04.2020
comment
Я в конечном итоге заставил это работать. По сути, следует помнить, что ocelot не отвечает за получение токена аутентификации, а просто проверяет его. В итоге мне пришлось получить токен для конкретного ресурса, который я хотел извне, а затем передать полученный токен обратно оцелоту, который его проверит.   -  person CRamsey    schedule 25.04.2020
comment
Я пробовал точно так же, но получаю эту ошибку. AzureADJwtBearer - неподдерживаемый провайдер аутентификации.   -  person Preetham Kumar P    schedule 22.06.2020


Ответы (1)


Рабочий пример для .Net Core 3.1

В итоге я получил эту работу с помощью библиотеки Microsoft.Identity.Web (текущая версия находится по адресу https://github.com/AzureAD/microsoft-identity-web/tree/master/src/Microsoft.Identity.Web)

Во-первых, мой файл конфигурации ocelot (ocelot.json):

{
  "ReRoutes": [
    {
      "DownstreamPathTemplate": "/myapp/api/{everything}",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "apphost.com",
          "Port": 443
        }
      ],
      "UpstreamPathTemplate": "/api/{everything}",
      "UpstreamHttpMethod": [ "GET", "POST" ],

      "AuthenticationOptions": {
        "AuthenticationProviderKey": "Bearer",
        "AllowedScopes": []
      }
    }
  ]
}

Обратите внимание, что AuthenticationProviderKey имеет значение Bearer.

Мой файл appsettings.json содержит мои лазурные конфигурации:

"AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "mydomain.com",
    "TenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "ClientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
  }

Наконец, мой файл Startup.cs содержит что-то вроде этого (сокращено для краткости)

public void ConfigureServices(IServiceCollection services)
        {
            services.AddProtectedWebApi(Configuration)
                .AddProtectedApiCallsWebApis(Configuration)
                .AddInMemoryTokenCaches();

            services.AddOcelot(Configuration);
            services.AddControllers();
        }

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                IdentityModelEventSource.ShowPII = true;
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });

            app.UseOcelot().Wait();

            app.UseAuthentication();
        }

Когда все это настроено, я могу передать токен-носитель, сгенерированный с использованием моих учетных данных Azure, и шлюз ocelot правильно его проверит.

person CRamsey    schedule 25.06.2020