Hot Towel/Durandal/Breeze.js: how to vertically secure data calls?
Asked Answered
V

2

7

I'm new to the whole client-side SPA world. I'm using the above technologies, which seem quite promising. However, one huge snag that I can't get over easily is the lack of built-in security. I had to manually roll out the user authorization, which IMHO should be part of the framework.

Now that I have that sorted, I'm getting major headaches with vertical security: where one user is logged in but can easily access other users' info by changing a few parameters in the browser console. I could pass the userId with every call and then compare it with the one on the server, but I was hoping that there would be an overarching solution that doesn't pollute the breeze data calls with user ids.

For example, let's say there's a call from the data service like this:

function getItems(){        
         var query = breeze.EntityQuery.from('Items').expand("Person");
         return manager.executeQuery(query);
}

this will get all the items, not good. So let's limit by userId:

function getItems(userId){        
         var query = breeze.EntityQuery.from('Items').where("userId", "==", authentication.userId).expand("Person");
         return manager.executeQuery(query);
}

in the second example, we get the userId from the authentication service, which stored the userId when the user was logged in. However, a malicious user can easily go the browser console and change that value.

Of course, I could pass the userId using withParameters(...) and compare it with the current one on the server, but I'd have to do that for every call, which doesn't seem right. Is there a better way to secure calls with the trusted user id?

Verbal answered 4/5, 2013 at 20:39 Comment(0)
K
12

@Ali - I understand your pain and your concern. You are right to fear any form of so-called security that relies on information passed in the URL. Fortunately there are excellent answers to your concerns and Breeze apps work well with them.

For example, have you studied the ASP.NET Breeze/Knockout Template? It uses Forms Auth for authentication and guards the Web API controller with an [Authorize] attribute. Only logged-in users can access any of the controller methods.

That authentication also sets the IPrincipal which the Web API controller makes available through its User property. You'll see User passed to the constructor of the TodoRepository. In that repository you'll find guard logic to restrict query and saves to just the Todo information belonging to the requesting user.

Look at the network traffic. You won't find any user identifying information in the URL or the request/response bodies. You will see an encrypted authentication cookie in a header.

An obvious flaw in the example is that the client/server traffic takes place in the clear. You must add transport level security (HTTPS) before you go to production. But this is a demo after all.

Kaitlin answered 5/5, 2013 at 23:6 Comment(2)
Hi Ward, thanks for your reply. Yes, I ended up doing something very similar to what you mentioned (minus the repository for now), so all the calls are scoped to the user on the server side. Keep up the good work :)Verbal
The link in the question no longer appears to work. It looks like there is still a knockout sample but I cannot see the Auth stuff @Kaitlin refers to. github.com/Breeze/breeze.js.samples/tree/master/netSacerdotal
O
2

Why not just do this in the controller? If the Web Api is secured with [Authorize] then you can get the users ID in the controller and make sure that the data returned is for the currently logged in user.

Overshoe answered 5/5, 2013 at 3:57 Comment(1)
As I was saying, I know that I can do that, I was just wondering if there are certain overarching techniques to secure the code better. However, working on the server side, it's probably not doable given that 'securing' the calls is really application-specific.Verbal

© 2022 - 2024 — McMap. All rights reserved.