4

I'm totally stuck on implementing Windows authentication for one of my .NET Core apps that uses Aurelia for client side.

The Aurelia application is hosted on port:9000 and the .NET WebAPI is hosted on port:9001.

The idea is to serve static pages from my .NET app once the app is published but now in development I use port:9000 because of the BrowserSync provided by Aurelia.

When I use port:9000 it's all fine and dandy and I have no issues posting or getting.

If I switch to port:9001 I can still get but not post. Posting results in 401 Unauthorized.

If we look at the headers for port:9000 requests..

Get(success):

enter image description here

Post(failed):

enter image description here

You can see that there are multiple headers missing in the post for some reasons, most importantly the authentication cookie..

Base-Repo.js

import {inject} from 'aurelia-framework';
import {HttpClient, json} from 'aurelia-fetch-client';
import {AppSettings} from '../infrastructure/app-settings';

@inject(HttpClient, AppSettings)

export class BaseRepo {
    constructor(http, appSettings) {
        http.configure(config => {
            config
                .withDefaults({
                    credentials: 'include',
                    headers: {
                        'Accept': 'application/json'
                    }
                })
                .withInterceptor({
                    request(request) {
                        console.log(`Requesting ${request.method} ${request.url}`);
                        return request;
                    },
                    response(response) {
                        console.log(`Received ${response.status} ${response.url}`);
                        return response;
                    }
                })
        });

        this.http = http;
        this.baseUrl = appSettings.api;
    }

    get(url) {
        console.log('BaseRepo(get): ' + url);
        return this.http.fetch(this.baseUrl + url)
            .then(response => { return response.json(); })
            .then(data => { return data; });
    }

    post(url, data) {
        console.log('BaseRepo(post): ' + url, data);
        return this.http.fetch(this.baseUrl + url, {
            method: 'post',
            body: json(data)
        })
            .then(response => response.json())
            .then(data => { return data; });
    }
}

Why is GET working but not POST when using BrowserSync port?

Edit 1

Post(success) for port:9001:

enter image description here

Edit 2 Console message post error:

OPTIONS http://localhost:9001/api/MYURLS 401 (Unauthorized)

Fetch API cannot load http://localhost:9001/api/MYURLS. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access. The response had HTTP status code 401. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Edit 3

Startup.cs

public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables();
            Configuration = builder.Build();

            env.ConfigureNLog("nlog.config");
        }

        public IConfigurationRoot Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options =>
            {
                options.AddPolicy("CorsPolicy",
                    builder => builder.AllowAnyOrigin()
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .AllowCredentials());
            });

            services.AddMemoryCache();
            services.AddMvc();

            services.InjectWebServices();

            services.AddOptions();

            //call this in case you need aspnet-user-authtype/aspnet-user-identity
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

            services.AddSingleton<IConfiguration>(Configuration);
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            app.UseCors("CorsPolicy");

            loggerFactory.AddConsole(Configuration.GetSection("Logging"));

            loggerFactory.AddDebug();

            app.UseMvc();

            app.UseDefaultFiles();

            app.UseStaticFiles();

            //add NLog to ASP.NET Core
            loggerFactory.AddNLog();

            //add NLog.Web
            app.AddNLogWeb();
        }
    }
Reft
  • 2,333
  • 5
  • 36
  • 64

2 Answers2

1

You will need to enable CORS in your ASP.NET Core project. There's information on how to do this here: https://learn.microsoft.com/en-us/aspnet/core/security/cors.

You need to call AddCors in ConfigureServices:

services.AddCors();

And then UseCors in Configure:

// Shows UseCors with CorsPolicyBuilder.
app.UseCors(builder => builder.WithOrigins("http://example.com"));

When you're using port 9000, you're on a different origin to the API, but with 9001, you're on the same origin and therefore CORS will not apply.

The OPTIONS requests are known as "preflighting". There's more information on those here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests.

Kirk Larkin
  • 84,915
  • 16
  • 214
  • 203
  • It can't be a problem with CORS. I'm already allowing all origins please see my last update – Reft Aug 15 '17 at 12:14
  • Did you also call `AddCors` on `IServiceCollection` and ensure that `UseCors` is **above** `UseMvc`? – Kirk Larkin Aug 15 '17 at 12:16
  • Also tried same implementation as this: https://weblog.west-wind.com/posts/2016/Sep/26/ASPNET-Core-and-CORS-Gotchas – Reft Aug 15 '17 at 12:33
1

enter image description here

I enabled "Enable Anonymous Authentication" in project properties and voila...

Before I only had "Enable Windows Authenticaiton" enabled, now both ports work!

When application is deployed this wont be enabled anyway because by then I will use the real IIS.

Update 1

After upgrading to .net core 2.0 I was no longer able to enable both Windows Authentication and Anonymous Authentication. After some research I found out you have to add:

services.AddAuthentication(IISDefaults.AuthenticationScheme);

in your startup.cs in order for it to work.

More info can be found in comment section and docs.

Update 2

You need Microsoft.AspNetCore.Authentication package for authentication builder.

Reft
  • 2,333
  • 5
  • 36
  • 64