Невозможно отменить защиту Azure AD в веб-API .NET Core 2.1. - PullRequest
0 голосов
/ 02 ноября 2018
  1. Я создал веб-API .NET Core 2.1 с анонимным доступом с помощью Visual Studio 2017.
  2. Я успешно внедрил защиту идентификаторов приложений Azure AD в своем API, используя этот и этот учебник.
  3. Как и ожидалось, я больше не могу получить доступ к API анонимно. Но я могу успешно вызвать его, указав соответствующее значение токена доступа.
  4. Затем я попытался отменить безопасность, которую я установил в API проект. Я закомментировал весь соответствующий код, ожидая, что я будет снова иметь возможность получить доступ к API анонимно.

Но вместо этого я получаю следующее исключение. Я неоднократно воспроизводил эту проблему (запускать проекты локально). Как только я впервые «аутентифицируюсь» по API, я больше не могу отменить эти изменения и сделать их доступными анонимно.

Это задумано?

Microsoft.IdentityModel.Clients.ActiveDirectory.AdalServiceException: AADSTS90002: Tenant authorize not found. This may happen if there are no active subscriptions for the tenant. Check with your subscription administrator.
Trace ID: b9285104-e24c-43cc-b3fa-6f843eef5a00
Correlation ID: e1d4a740-ccab-4ea4-9fb0-b12608d116ca
Timestamp: 2018-11-02 15:18:19Z ---> System.Net.Http.HttpRequestException: Response status code does not indicate success: 400 (BadRequest). ---> Microsoft.IdentityModel.Clients.ActiveDirectory.AdalException: {"error":"invalid_request","error_description":"AADSTS90002: Tenant authorize not found. This may happen if there are no active subscriptions for the tenant. Check with your subscription administrator.\r\nTrace ID: b9285104-e24c-43cc-b3fa-6f843eef5a00\r\nCorrelation ID: e1d4a740-ccab-4ea4-9fb0-b12608d116ca\r\nTimestamp: 2018-11-02 15:18:19Z","error_codes":[90002],"timestamp":"2018-11-02 15:18:19Z","trace_id":"b9285104-e24c-43cc-b3fa-6f843eef5a00","correlation_id":"e1d4a740-ccab-4ea4-9fb0-b12608d116ca"}: Unknown error
   --- End of inner exception stack trace ---
   --- End of inner exception stack trace ---
   at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Http.AdalHttpClient.GetResponseAsync[T](Boolean respondToDeviceAuthChallenge)
   at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Http.AdalHttpClient.GetResponseAsync[T]()
   at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenHandlerBase.SendHttpMessageAsync(IRequestParameters requestParameters)
   at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenHandlerBase.SendTokenRequestAsync()
   at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenHandlerBase.CheckAndAcquireTokenUsingBrokerAsync()
   at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenHandlerBase.RunAsync()
   at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.AcquireTokenForClientCommonAsync(String resource, ClientKey clientKey)
   at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.AcquireTokenAsync(String resource, IClientAssertionCertificate clientCertificate)
   at APIProject.Controllers.ExclusionRequestsController.Get() in C:\Users\Tracy\source\repos\APIProject\Controllers\ExclusionRequestsController.cs:line 61
   at lambda_method(Closure , Object )
   at Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable.Awaiter.GetResult()
   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
   at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
   at NSwag.AspNetCore.Middlewares.SwaggerUiIndexMiddleware`1.Invoke(HttpContext context)
   at NSwag.AspNetCore.Middlewares.RedirectMiddleware.Invoke(HttpContext context)
   at NSwag.AspNetCore.Middlewares.AspNetCoreToSwaggerMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
    ErrorCode: invalid_request
    StatusCode: 400

По-видимому, он все еще пытается аутентифицировать запрос, но я не уверен, почему, потому что весь соответствующий код аутентификации был удален.

Мое лучшее предположение - что-то меняется в Visual Studio и никогда не меняется обратно. Но я подтвердил, что ничего не меняется в файлах проекта VS после этой первой аутентификации.

Для справки, вот код в Startup.cs, который я использую для защиты API:

namespace APIProject
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }
        public static IConfiguration AppSetting { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            services.AddCors(options =>
            {
                options.AddPolicy("AllowAll",
                          p => p.AllowAnyOrigin()
                                .AllowAnyHeader()
                                .AllowAnyMethod()
                                .AllowCredentials());
            });
            services.AddSwagger();
            //Authentication
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) // sets both authenticate and challenge default schemes
                .AddJwtBearer(options =>
                {
                    options.Audience = Configuration["AppSettings:Audience"];
                    options.Authority = "https://sts.windows.net/[TenantID]";
                });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseCors("AllowAll");
            }
            else
            {
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            // Register the Swagger generator and the Swagger UI middlewares
            app.UseSwaggerUi3WithApiExplorer(settings =>
            {
                settings.GeneratorSettings.DefaultPropertyNameHandling =
                    PropertyNameHandling.CamelCase;
            });
            app.UseAuthentication();
            app.UseMvc();
        }
    }

    static class ConfigurationManager
    {
        public static IConfiguration AppSetting { get; }
        static ConfigurationManager()
        {
            AppSetting = new ConfigurationBuilder()
                    .SetBasePath(Directory.GetCurrentDirectory())
                    .AddJsonFile("AppSettings.json")
                    .Build();
        }
    }
}

А вот код, который я использую для аутентификации по API:

public async Task<JsonResult> OnGetSummaryView()
{
    try
    {
        HttpClient httpClient = new HttpClient();
        AuthenticationContext authContext =
            new AuthenticationContext("https://login.microsoftonline.com/[Tenant ID]");
        ClientCredential clientCredential =
            new ClientCredential("[App ID]", "[App Secret]");
        AuthenticationResult result =
            await authContext.AcquireTokenAsync("[App URI]", clientCredential);
        using (var client = new HttpClient())
        {
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            string requestUrl = $"https://localhost:44338/api/ExclusionRequests/GetSummaryView";
            HttpRequestMessage message = new HttpRequestMessage(new HttpMethod("POST"), requestUrl);
            message.Content = new StringContent("{}", Encoding.UTF8, "application/json");
            HttpResponseMessage response = await client.SendAsync(message);
            dynamic jsonContent = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result);
            return new JsonResult(jsonContent);
        }
    }
    catch (Exception e)
    {
        //Add exception handling here.
        return null;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...