Alexander Li Alexander Li - 3 months ago 34x
AngularJS Question

AngularJS, .NET Web API, and back-end authorization when returning views in a SPA

So I want to write a SPA using AngularJS and .NET Web API. I want Angular to handle most of the routing. But how do I prevent unauthorized users (regardless of authentication) from getting certain views? I want to do this on the back-end, without involving .NET MVC because MVC returns an entire view, which defeats the purpose of a SPA. Also from my understanding, Web API has no role in returning views to the client. Given that this is correct, authorization in both Web API and MVC become useless in a SPA when returning a requested view. I thought about writing some OWIN middleware to exam the headers of an incoming AJAX call, then determine whether or not a user is authorized to receive a view. But I have no idea where to start. If writing OWIN middleware to handle authorization is realistic, where do I begin?

Does any of this seem reasonable? Or am I just crazy and I should just let .NET MVC handle returning views?

Follow up: Both MVC and Web API have the [Authorize] decoration, and a token is being passed around. Authentication is fine. The problem lies with Angular. When Angular handles routing, it requests a view from the server. But the server does not go into either .NET MVC or Web API, circumventing authorization in both MVC and Web API. It just gives back the view. There is front end authorization, but that isn't ideal. Hence I need the back end to handle returning views when a user is authorized to receive that view.


There are valid cases for securing "Web APIs", and you should not forgo basic authorization on your Web APIs (because even without a View, an API can still be accessed by malicious users.) Thus, you will ultimately want to authorize access to both front-end Views as well as back-end APIs.

However, to prevent users from gaining access to specific templates you need to apply an Authorize attribute on the "MVC Controllers" or "Action Methods" you wish to protect which will serve your templates. It sounds as though your client-side framework is fetching files directly off the web-server (as opposed to activating an MVC Controller Action to receive a View.)

If you are not serving your templates via an MVC Controller, you would require some alternative means of securing templates (such as OWIN Middleware, yes.)

Personally, I would suggest using the MVC facilities for sheer convenience and continued support in the future. However, OWIN would be a more appropriate solution if you didn't have any MVC Controllers (e.g. no need for MVC when all logic occurs between SPA and APIs.)

To that end:

When I am creating a Single Page Application (SPA) using either knockout or angular I typically move ALL of my templates into partials. I then use MVC Views and Controller Actions for delivering those partials.

This allows me to authorize access to my templates. This also allows me to modify the emitted template content based on server-side-only knowledge, be it security or other data. For example I sometimes use User.IsInRole() to include/exclude content within the templates based on user role (for example, emitting a template that provides Admin actions for admin users, and emitting the same template but without Admin actions for regular users.)

Depending on the size and complexity of an SPA I generally deliver the entire SPI in a single page load (a single MVC View.) This is incompatible with frameworks which assume templates come per-diem from the server (rather than, say, an element in the current DOM), however it provides a very snappy experience to the user, and in my experience the size of fairly complex SPAs are still smaller than some of the most common javascript frameworks.

If the complexity or SLA of an application demands it I may deliver sections of the SPA in batches (multiple MVC Views, pulled into the browser on-demand as part of regular app navigation). For example, ~/Home/Index may itself deliver all shared templates used throughout the app, but ~/Account/Index may deliver account management views, and ~/Uploader/Index may deliver asset upload views. I don't actually need to pull these additional Account and Uploader templates into the app unless and until I intend to use those features.

TL:DR? Use MVC Controllers to deliver MVC Views which contain your templates and apply the [Authorize] attribute to any Controllers or Actions which need to be restricted to authorized/authenticated users. To keep things simple, consider using an MVC View to deliver your entire SPA, and further consider using MVC Partial Views to help organize your markup, you should have something like ~/Home/Index which is nothing but a collection of Html.Partial calls (no actual markup.)

That said, now you've got my gears turning on a pure OWIN solution. I will try and update within the next week or so with a pure OWIN approach if one doesn't already exist on SO.

Hope that helps.