3

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.

Shaun Wilson
  • 8,727
  • 3
  • 50
  • 48
  • http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/ 5 part article which covers AngularJS token authentication with ASP.Net Identity, CORS, OAUTH Refresh, External Logins, and more. – Claies Feb 18 '15 at 23:42
  • I read that article earlier today. It does not explain how to prevent unauthorized views returning to the client when Angular is handling routing while using the back end. MVC and Web API are circumvented during this process. I read that I need to inject roles into the front end, and that is out of the question. – Alexander Li Feb 19 '15 at 00:39

2 Answers2

3

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.

Shaun Wilson
  • 8,727
  • 3
  • 50
  • 48
  • Both Web API and MVC require authorization in the app. However, when AngularJS is handling routing, it hits neither layer. Instead, when Angular handles routing, the server just gives the view, by passing MVC and Web API authorization. – Alexander Li Feb 19 '15 at 00:01
  • @AlexanderLi when building up the SPA for delivery (ASP.NET Routing and MVC Controller) you would want to perform security checks to include/exclude partials. It seems inappropriate to constantly contact the server to authorize access to SPA content which has already be delivered to the client, I would never do this in a Live scenario, it would eventually fail to scale. – Shaun Wilson Feb 19 '15 at 00:12
  • I don't think I understand. At the moment, MVC is handling all routing. Web API handles posting to the database. Shouldn't it be wise to require authentication and authorization for both? – Alexander Li Feb 19 '15 at 00:28
  • Yes. :) That's precisely what I said, sorry if it was unclear I've tried to restructure my answer. I've also updated my answer based on the updates to your question and tried to explain a bit the pattern I typically use for ASP.NET MVC based SPAs. – Shaun Wilson Feb 19 '15 at 04:42
  • Specifically in my comment what I identified what "I would never do" was "to constantly contact the server to authorize access to SPA content which has **already** been delivered to the client." Any other security checks you 'need' to perform should be done from within your web apis, and your front-end should be implemented to properly handle a 401 error from your XHR (typically by displaying a dialog to let the user know they just failed an auth check.) – Shaun Wilson Feb 19 '15 at 04:46
0

As you are developing SPA using AngularJs you probably use angular-route extension. In this case your views are just placeholders for your data. So I'd say your biggest concern should be data (Web API). You should definitely use some Authentication for it.

For the rest of views that need some very specific auth you can still use ASP.NET MVC in conjunction with AngularJs. MVC partials would be a good solution I think. You can return rendered partial view from angular controllers. And of course you can request it with Ajax.

Andrei
  • 42,814
  • 35
  • 154
  • 218
  • 1
    A colleague of mine did suggest returning a partial via AJAX, and then injecting into the layout. However, is this more efficient than letting MVC handle routing? I am aiming to decrease bandwidth consumption while keeping a SPA. – Alexander Li Feb 19 '15 at 00:16