Web API 2, CORS, NTLM & OWIN / Katana with Angular 2

339 Views Asked by At

Massive amount of issues getting this to work.

Thought I'd put up the common issues and the solutions having wasted a day on this and being led down many false paths by other answers.

Setup :

  1. Web Api 2 Server
  2. Server configured for NTLM (Negotiate)
  3. Angular website hosted on a different machine or Port
  4. Website connects to API to do, well, stuff.

Issues :

  1. Basic setup and first time you run it you get no access-control-allow-origin header is present
  2. Setting Cors on the server and you still get the issue
  3. You eventually realise that Angular isn't setting WithCredentials on its calls and fix this, now GET works but PUT, POST & DELETE fail with something about pre-flights.
1

There are 1 best solutions below

0
On BEST ANSWER

And the solutions :

  1. Firstly your server needs to be enabled for cors and this must be the first line in your app config :

    WebApp.Start(_configuration.Url, app => { app.UseCors(CorsOptions.AllowAll);

    1. Enable Authentication, BUT not for the pre-flight OPTIONS calls :

    var listener = (HttpListener)app.Properties["System.Net.HttpListener"]; listener.AuthenticationSchemeSelectorDelegate = request => request.HttpMethod == "OPTIONS" ? AuthenticationSchemes.Anonymous : AuthenticationSchemes.Negotiate;

    1. Set your Angular code to send calls in with WithCredentials. There's many different ways to do this, but we used an authentication interceptor : intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const authReq = request.clone({ withCredentials: true }); return next.handle(authReq)

    2. If you want to do anything fancy for your Auth you can create your own middleware by extending OwinMiddleware and overriding the Invoke method. This can then be registerd in the pipeline with app.Use<MyMiddleware>(paramsToConstructor) in your override method you can access the Identity of the user with :

    var identity = new ClaimsIdentity(context.Authentication.User.Identity.AuthenticationType);