пересылка аутентификации веб-приложения в службу API

У меня есть приложение, которое разбито на веб-приложение (Asp .net MVC), которое общается со службой API, написанной на C # .net core 2.2. У меня есть веб-приложение, использующее встроенную аутентификацию AZure AD. Это отлично работает, поскольку запрашивает у пользователя идентификатор домена Azure и пароль и позволяет вводить только определенных пользователей.

Я сделал то же самое для службы API. Весь код startup.cs настроен правильно.

Я хотел бы использовать аутентификацию из веб-приложения и перейти к службе api, но не могу найти способ сделать это или даже получить к ней доступ.

Я пробовал добавлять разные схемы аутентификации (azureadbearer и jwtbearer), но они просто заставили веб-приложение не работать, никогда не запрашивали аутентификацию

В веб-приложении это использует Azure AD и требует аутентификации пользователей:

services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
  .AddAzureAD(options =>
  {
       Configuration.Bind("AzureAd", options);
  });

в службе API у меня есть

services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
      .AddAzureADBearer(options => Configuration.Bind("AzureAd", options));

но я не могу понять, как / что веб-приложение должно вызывать для авторизации или получения токена для службы api. Если я добавлю атрибут [Authorize] для контроллера api, я получу неавторизованную ошибку, вызывающую его из веб-приложения.

Я хотел бы иметь возможность использовать или получать токен, который был создан, когда пользователь авторизуется в веб-приложении, и пересылать его в службу api, но не видел в заголовках ничего похожего на токен jwt.

Я также попытался создать токен jwt в веб-приложении и установить заголовок авторизации (токен-носитель) и отправить его в службу api, а также изменил службу api, чтобы вместо этого использовать jwtbearer, но я все равно получу неавторизованный.

Я потратил дни, пытаясь найти примеры и заставить это работать безуспешно, любые предложения были бы очень признательны ... хотелось бы иметь возможность использовать встроенное промежуточное программное обеспечение AzureAD и не писать код, чтобы справиться с этим, если это возможно.

Это то, что я пробовал в службе api, но не проверял отправленный токен: s

services.AddAuthentication(AzureADDefaults.JwtBearerAuthenticationScheme).AddJwtBearer(cfg =>
  {
      cfg.RequireHttpsMetadata = true;
      cfg.SaveToken = true;
      cfg.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
      {
          ValidIssuer = Configuration["ServiceAd:Issuer"],
          ValidAudience = Configuration["ServiceAd:Audience"],
          IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["ServiceAd:ClientSecret"]))
      };
  });

person ebarke    schedule 02.04.2019    source источник


Ответы (1)


Я бы предложил использовать OAuth2.0 от имени потока. В соответствии с вашим требованием вы хотите аутентифицировать пользователя в веб-приложении и создать токен для веб-API и вызвать веб-API из контроллера веб-приложения.

Сначала создайте 2 принципала службы, один для веб-приложения, а второй - для веб-API. Затем перейдите к субъекту службы веб-приложений -> раздел разрешений, добавьте веб-API (субъект службы) и предоставьте разрешение.

После создания субъектов-служб вам необходимо использовать поток OAuth 2.0 от имени в контроллере веб-приложений. После запуска веб-приложения вам необходимо аутентифицировать пользователя с помощью имени пользователя и пароля, после аутентификации пользователя вы можете получить access_token с помощью HttpContext в методе действия вашего контроллера, а затем использовать поток потока от имени, чтобы получить другой токен для web api и вызовите web api для доступа к ресурсу.

Вы можете проверить приведенную ниже документацию для потока от имени потока: OAuth2.0 от имени потока

В веб-приложении -> HomeController.cs -> Метод Index () получает текущий токен (при первом входе в систему вы получаете токен доступа), используйте этот токен для создания другого токена для веб-API.

Ниже приведен код для потока от имени потока:

 private async Task<string> GetOnBehalfToken()
    {
        // Get User Assertion
        var authenticateInfo = await HttpContext.Authentication.GetAuthenticateInfoAsync("Bearer");
        string incomingToken = authenticateInfo.Properties.Items[".Token.access_token"];
        UserAssertion userAssertion = new UserAssertion(incomingClientToken, "urn:ietf:params:oauth:grant-type:jwt-bearer");

        string token = string.Empty;
        string authString = string.Format(this.azureAd.AadInstance, this.azureAd.TenantId);
        AuthenticationContext authenticationContext = new AuthenticationContext(authString, false);

        // config for oauth client credentials
        // Use Web app client id and secret key
        ClientCredential clientCredential = new ClientCredential(this.azureAd.ClientId, this.azureAd.AppKey);

        // App ID uri of web api service principal
        var resource = "https://<tenant>.onmicrosoft.com/45854ee0-608a-4dff-xxx-xxxxxxxxxxx";

        AuthenticationResult result = await authenticationContext.AcquireTokenAsync(resource, clientCredential);
        return result.AccessToken;
    }

Как только вы получите токен для веб-api, добавьте его в заголовок авторизации http-клиента и вызовите api.

Если вы хотите только аутентифицировать свой веб-API с помощью Azure AD. Используйте приведенный ниже код при запуске и посмотрите, работает ли он для вас:

public static void ConfigureAuthentication(IAppBuilder app)
    {
        app.UseWindowsAzureActiveDirectoryBearerAuthentication(
           new WindowsAzureActiveDirectoryBearerAuthenticationOptions
           {
               Tenant = Configuration["AzureAD.TenantId"],
               TokenValidationParameters = new TokenValidationParameters()
               {
                   ValidateIssuer = true,
                   ValidIssuer = Configuration["AzureAD.Issuer"],
                   ValidAudience = Configuration["AzureAD.Audience"],
                   ValidateLifetime = true
               }
           });

        app.UseJwtBearerAuthentication(
            new JwtBearerAuthenticationOptions
            {
                AuthenticationMode = AuthenticationMode.Active,
                TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidateIssuer = true,
                    ValidIssuer = Configuration["AzureAD.Issuer"],
                    ValidAudience = Configuration["AzureAD.Audience"],
                    ValidateLifetime = true
                }
            });
    }

Также убедитесь, что значения Issuer ({tenant-name} .onmicrosoft.com) и Audience (идентификатор приложения для субъекта-службы) должны быть правильными.

Надеюсь, это решит вашу проблему.

person MohitDhingra-MSFT    schedule 05.04.2019
comment
Я не совсем следую вашему образцу ... это идет в веб-приложении или API? Я уже смотрел эту статью раньше, и это совсем не то, что мне нужно. Я хочу использовать Azure AD, который у нас есть для аутентификации пользователей в веб-приложении. В настоящее время это работает нормально, но я также хотел бы использовать эту аутентификацию для защиты / доступа к службе api. Первая строка кода (при запуске в веб-приложении) вылетает без обработчика аутентификации, настроенного для Bearer - person ebarke; 08.04.2019
comment
Вы хотите получить доступ к веб-API из своего веб-приложения. В этом случае приведенный выше код будет в веб-приложении. Вы можете аутентифицировать пользователя в веб-приложении, и вам нужен токен для вызова веб-API. В этом случае будет использоваться поток от имени пользователя. Если вы хотите независимо аутентифицировать свой api, я бы предложил создать проект веб-API с шаблоном Api по умолчанию и выбрать «Аутентификация как рабочие или учебные учетные записи» и проверить файл startup.cs с вашим файлом api - ›startup.cs. - person MohitDhingra-MSFT; 08.04.2019
comment
Мое веб-приложение и api настроены с аутентификацией как рабочие или школьные учетные записи, веб-приложение правильно авторизует вошедшего в систему пользователя, но я не могу понять, где / какой токен сгенерирован из этого, и ваш образец кода делает ничего не найти (нет жетона на предъявителя). Кажется, это должно быть довольно просто, но я уже несколько недель бился головой, пытаясь защитить сторону api, даже не могу заставить его авторизоваться с помощью схемы jwtbearer ... просто либо получите схема по умолчанию не найдена или просто возникла несанкционированная ошибка, но нет возможности отладить, чтобы увидеть, что происходит. - person ebarke; 09.04.2019
comment
изменил мой ответ, добавил фрагмент кода, вы можете использовать этот код в startup.cs веб-API. Надеюсь, это поможет. - person MohitDhingra-MSFT; 09.04.2019
comment
Не помогает, я думаю, это тоже из более старой версии .net? Не знаете, что / где вызывается этот метод ConfigureAuthentication? Если вы создаете веб-приложение и устанавливаете аутентификацию мастера для работы или учебы и выбираете рекламный домен, он правильно настроит веб-приложение и потребует аутентификации. Теперь сделайте то же самое для нового веб-API и выберите тот же AD для аутентификации этого проекта. Как создать токен для API из веб-приложения, желательно с использованием аутентификации из веб-приложения? - person ebarke; 11.04.2019