I am a relatively inexperienced programmer.
I have managed to build a web api which uses basic authentication as per the following:
https://weblog.west-wind.com/posts/2013/Apr/18/A-WebAPI-Basic-Authentication-Authorization-Filter which is working very nicely (forced over ssl obviously). Inside the OnAuthorizeUser i check the un/pw against an mssql database, via a call to an internal class called "DB" where all my database interaction occurs.
So all Controller methods are filtered by the Basic Authentication ("decorated" at the Controller level) however, access to certain Controller Methods also needs to be limited depending on the user - so there is a need to understand the user permissions. Based on my limited former ASP.NET experience I think I would have stored the relevant user details in a Session (or possibly cache) however I have so far steered clear of this based on wanting to stick to the concept of having a RESTful application etc
Rightly or wrongly, in playing around I realised I could use a private static (instance?) of my User class inside my internal DB class and populate it at the time of initial authorisation. I also added a public method (public User getThisUser()) to return the private User. From within my Controller methods I create an instance of DB and am able to check the values etc.
I was very worried that I would have issues with the "scope" of this "static" User, so to test, I created a Controller method to simply return the User information from DB.getThisUser(). In doing so I have found that I can log in as multiple different users (using different browsers concurrently for example) and each one consistently returns the correct user information (as logged in).
I'm still not entirely convinced this is "safe" however reading through the details of implementing something like ASP.NET Identity as a possible alternative makes my head spin and really seems like massive overkill in this case - I'm not using Entity Framework and after much searching I could not find a single example of NOT using an ORM (I need a solution to work with an existing DB).
Is this destined to fail? Do I go back to considering session or cache? Something else? I would really appreciate any feedback / advice on this from all of you who are more experienced than me. Thanks in advance for any help.
i think you're getting a bit confused.
an API is supposed to be stateless, meaning no session. Yes, you have a controller which translates into an endpoint.
You can hit an endpoint with all the information required to satisfy the request and this is it. Don't think of an API as an actual application where all requests are linked somehow. Instead, think of it at an application where each request is separate and can come from anywhere and any user.
How does the application know which user sent a request? Well, it doesn't unless you pass that information in.
You don't fire a request saying GetMeUserDetails. The api has no idea what you want. Instead you would say GetMeUserDetails for userId 12345. Now, since your request contains all the information required to satisfy the request, the API can now give you what you expect.
If some calls require authentication, you might use some sort of tokens to identify the user, but again, the information is passed in via the token.
You probably realize what static means and how it works. you are not going to see problems until you try to send two or more requests at the same time and then you'll realize that the first call now contains the details of the second request because well, static ...
Related
I am building an API where users and admins can interact with the same data, but with different needs.
A user can also have access to the admin panel, if he has the "admin" role.
Let's see for example we have a resource like Badges. A Badge is simply a reward when you achieve some actions into the app.
GET http://localhost/api/v1/badges
An authenticated user can call this endpoint and it returns the list of all badges, if they have it or not, with progress details.
GET http://localhost/api/v1/badges?user_id=2
with user_id parameter, we can see these details of another user (if he allows it).
But from the admin scope, I just need to see the list of all badges, without achievement details (CRUD operations).
So I have 2 options in mind:
Create "admin" endpoints: GET http://localhost/api/v1/admin/badges.
Adding custom header "X-App-Scope" to identify if I am in admin or user.
I don't like the second one because I think I will have so many if statements and behavior in the same endpoint, depending of the scope.
Because I have lots of use cases like this, I want to make sure my API architecture is good to handle user/admin needs.
Do you guys have any idea/example to manage stuff like this?
Thanks!
My personal preference is to separate admin API routes from user ones. i.e. having two routes
/api/v1/badges
/api/admin/v1/badges
You will have two unique documentation, one for each route, which makes it easier to maintain and understand
It will be easier to tell the difference between the user and the admin versions
There is no need extra code to check for request headers or url params.
It makes your middleware less complicated, especially if authentication and permissions are handled there.
It is more scalable for teams as there is only one kind of request and response format per API.
TL;DR: REST is designed in the expectation that you would use two different resources here.
The core problem is this: how would a general purpose component, like a browser, know that your special resource needs to have this custom header added?
In particular, consider the case where I send to you a copy of the URL for this resource, and nothing else. How are you to know to add the customer header to the request?
On the other hand, if you use different resources to share this information with each audience, everything just works.
The only way I found to stay as simple/clear as possible is to make multiple endpoints, for each use case:
GET http://localhost/api/v1/badges to get all badges in raw data
GET http://localhost/api/v1/users/badges to get all badges with user stats (progression, achievement...) in a transformed format
GET http://localhost/api/v1/users/{uuid}/badges to get all badges with user stats (progression, achievement...) in a transformed format for the specified user, if his profile is public
Now I have a lot of /users/XYZ endpoints, but my code seems easier to read & maintain, and I don't really need to see the code to guess what data will be returned, the conditions, etc...
I keep wondering how the other APIs are written when you have an admin section, because having /users everywhere isn't really "pretty", and I don't see that anywhere else.
I'm currently working on a iphone/android project where the mobile talk ta java backend server through REST API calls.
The Java backend is done using Spring and its Authentication system (with a JSESSION ID token)
I'm not an expert in security but I can see that if not implemented correctly there could be quite a lot of issues.
One of my biggest concern would be user creation for example.
When the app creates a user it simply makes a POST request to (url.com/rest/create)
How can I avoid, server side, that a malicious user puts this url in a loop and create thousands of users ?
What are common best practices to secure API calls ?
Is the Spring Authentication token enough ?
Thank you!
It's not really possible to prevent a client from making many calls to your server. A malicious user can create a script or application firing requests to your server.
The solution is to authenticate and authorize the calls to the server. You give certain users (for example administrators) the privilege to create users. You trust those users to behave in a correct manner. You have your users authenticate before they call the APIs on your server. Then, on the server side your check who the user is and what he/she is allowed to do.
If you are still concerned about privileged users not behaving, you can assign quota to each user on the actions they are allowed to perform.
The hightech solution (with as much framework fuctions as possible) would be
first: have a created-by and created-date field at the entity you want to protect (I recommend to use Spring-Data-JPA Auditing for that).
second: create a custom spring method (or web) expression method that is able to check how many items the current user has created in the (for example) last 10minutes and if this are more then (for examle) 20, then return false (or make them parameters of the method).
Then you can protect your method (or url) with that expression (#PreAuthorize("createsNotExeced(10, 20)"))
But this is the high tech solution - it would be quite intresstion implementing them when one wants to learn spring security. (and you would need to add some caching, but this is also a Spring feature).
The lowtech solution would be: put an list of timestamp in the users session, and add an new item to that array whenever the user creates an new item. When the last (for example) 20 timestamp enties are within the last (for example) 10 minutes, then throw an TooMuchHeavyUseRuntimeException or somthing else.
Ok, I'm new to web development, so I might be getting some of these terms wrong. I apologize in advance.
I am having trouble understanding the different elements of authentication. Every method seems to be advised against by someone, though not always with clear reasons. I am building a web app for a company that will have access to a database, so I would like to make sure it is secure.
So the there are three places I have seen commonly used to store information.
FormsAuthentication.SetAuthCookie(). This stores a session cookie that will exprire with the browser, and nothing sensitive is on the client. However, it can only store one value. This stackoverflow answer shows a method of storing multiple values here, but the guy who gives it says not to use it, though not why.
FormsAuthenticationTicket. I don't know where this information is stored, but it allows for a simple method of storing multiple values. Securing it, according to the documentation requires calling Encrpty() to store, and decrypt() to retrieve. This seems wasteful, but what do I know.
Session["SomeRef"] = new CustomObject(). The second answer in this question explains how to do this, but a comment to it calls it dangerous because it can be stolen. This looks like the best method to me, because the information is still stored on the server, and can store multiple values.
I cannot find any comparisons for these methods, or good explanations on the "best practice" way of storing multiple pieces of information after authenticating a user. The information is just the User's name and their userId.
Here is some further clarification to help you decide.
SetAuthCookie can be implemented in a way to store multiple values. In practice, however, you usually can't store enough to avoid a database lookup. It's best to store the user name (unique identifier) and load more information during the request. As your question suggests, you shouldn't store sensitive information on it. You should assume that all information sent in a cookie can be decrypted and read and you should take precautions that that information can't be used maliciously. All session cookies can be stolen and I'll explain why in a moment.
FormsAuthenticationTicket is the same API as SetAuthCookie but at a lower level in the Framework. With SetAuthCookie, Encrypt() and Decrypt() should be happening anyway (it's the default configuration.) It's not wasteful but use method 1 instead because it's easier.
Session has some limitations. Notably, by default it's process-dependent. That means that when the server restarts or more than one web server is involved, your session is lost and you have to authenticate again. It is the easiest to use and fastest when using the default memory session storage (InProc). You can use sql storage or a dedicated session server to overcome the process-dependency.
All three methods are considered dangerous for the same reason all cookie-based authentication systems are dangerous: because the cookie's value can be sniffed over wireless and reused to take over a session. This is known as sidejacking and it also applies to scenarios 1 and 2. The way to prevent this is to implement HTTPS. Then, the cookie transimission (and everything else) is encrypted at the network level and can't be stolen.
TLDR; Use SetAuthCookie and HTTPS
NOTE this answer has been edited several times for clarity.
Here's the issue at hand: I have developed an ASP.NET MVC3 application using Razor. I have also implemented a custom membership provider and overridden the ValidateUser() method. Within, I query my db and get a lot of user information in addition to the password auth.
At the moment, I am pushing this information, i.e. companyId, to static properties of a class. This works and I can display/use this information throughout my app. The problem arises when a user closes their browser tab. Upon re-opening the app, the user is authenticated via a cookie, so they don't need to re-login; however, those static variables are blown away.
So guys and girls, how would/do you conquer this issue? Should I append the extra info to the session cookie? Or perhaps a better solution?
Use the ProfileProvider in ASP.NET.
For application level variables, they are going to be subject to application pool recycles and similar "simulated" restarts related to users starting all over. These variables should be completely independent of user usage and should be able to be recreated easily. If you have variables that are user dependent or that can't be restored easily without some sort of outside intervention then you will definitely need a different method of storage.
If the data is user specific, storing it in the session cookie is probably the best idea. If the data is user-related but branches multiple users it should be stored in a database or a flat file somewhere. If the data has nothing to do with users specifically then it should just be in a database or configuration file.
On a website I am building I need to allow users to edit their orders. Easy enough. But how do I ensure that a user cannot edit other users' orders? Do I perform checks in the model or in the controller to verify that the order belongs to the authenticated user?
Put checks in the view (yes, the view) for rapid response to user errors.
Put checks in the controller to ensure data integrity.
For example, in a web based app, you might have browser javascript to check all fields, including username, so the user gets rapid response to fix erroneous transactions. However, back at your server, you can not rely on the browser to really validate the data, since the browser is outside your control -- it might be corrupted, either intentionally or accidentally, and not doing validation as you intend. Thus you need to revalidate everything on your server to ensure integrity.
Well hopefully your site doesn't have any way for a user to even attempt to edit someone else's orders. But if it's still possible to try, you could put that logic in either the model or controller. It's a matter of opinion. Some people will say that the controller should do things like access checks, and the model only knows how to modify itself. Others will say "fat model, skinny controller" and say that the security checks need to be reusable across controllers and so they should go in the model. It's your call.