Secure users data in asp.net web api response - c#

I'm completely new to ASP.NET Web API. I've done some research but I haven't been able to find an answer to my problem. I am starting to become very confused about how to secure the data that is being responded to the caller.
My overall objective is to create an ASP.NET MVC web application and a Xamarain Android application that allow users to register and login into an account and their data stored in a MySQL database.
I thought that a Web API would be a good solution as both applications could call functions to get a collection of users, an individual user and put new users into the database through HTTPPost, HTTPGet requests.
So far I have created an ASP.NET Web API with one controller and one HTTPGet request which returns all the users from the database.
When I run it I get a response of all the user's details.
My Controller Code
public class UsersController : ApiController
{
// GET api/values
[HttpGet]
public IEnumerable<Users> Get()
{
using (NorthYorkshireContext context = new NorthYorkshireContext())
{
return context.Users.ToList();
}
}
}
My Response:
If I were to deploy this to a server what is stopping anyone from seeing all the users details? For example, If I deployed this to http://mydomain.co.uk what is stopping anyone from querying the API like http://mydomain.co.uk/api/users and seeing all the details?
P.S I understand passwords should be encrypted, sorry if this is a bad question.

This question reads as "I created a publicly accessible API endpoint that outputs my entire users table; why are APIs so insecure?". Why did you create this operation in the first place? What problem does it solve? When I make a human-sized hole in my house, can I rightfully complain that after a few days my computer and television are stolen?
For each API endpoint you must consider:
Do I need this? I really can't figure out why you would need a list of all users.
Do I need this to be publicly accessible, or should it be limited to localhost traffic (i.e. infrastructure)?
When publicly accessible, who may access it (authorization)?
When called, should it return all columns that are in its data source, or should there be some kind of mapping?
And no, passwords don't need to be encrypted, they need to be hashed. Use ASP.NET Identity for authentication, don't roll your own.

an API is a perfect solution for what you are trying to do.
When you build an API, that is exposed to the outside world, you need to secure it somehow. This is where something like OWIN, OAuth2 come into place.
A token based system (JWT) is usually a good solution to secure the API. I would start with some reading on the subject if I were you.
Once you secure you API from unauthorized access then you need to think what data you should provide to the users / apps who have the right to access it.
Having passwords in clear is a huge security risk, sending them to the app is an even bigger risk.
Normally you'd let the users authenticate, you would not send passwords to the app.
Make sure your API works over https and do not send anything private in URLs, use POST requests and put the sensitive data in the body.
Security is a big topic, I am afraid.

Related

Calling another API within an API gets timeout

I have quite a stupid question, but the environment I am working in forced me to use this solution.
We have a WebAPI providing data to an angular frontend.
For authentication we use an Azure AD B2C Tenant.
User sign into frontend and start to receive Data from the API as normal as it should be.
But: The users have to get different data regarding Groups in the Azure AD. So e.g. UserA is in GroupB and has to get other data than UserX who is in GroupY.
So within the api I need to verify that the Users are in the groups for the data they are requesting.
Normaly I would use Microsoft.Graph to communicate with Azure from the API. But as this is a special network I need to go through a proxiy using different User-Agents. This is all working fine when I call my Code from an executable.
But when I call the same Methods within the API I get a timeout and no Data from Azure. I tested the same routines with other APIs and there is no timeout.
I already checked the request Headers to verify that there is no mixed up information or anything, but everything looks like as it should be.
Has anyone had similar Problems, or has a solution regarding the User-Agent when creating the Request Token for API?
Thank you!
Cheers!
Case closed. The proxy denied the request and caused the timeout when called by the api. Don't ask my why. The same code and build is running on the deployed environement with no issues. Who would have thought that there would be the day when I say "But it wasn't working on my machine..."
Cheers!

Secure webapi 2 without authorisation or user login

I looked everywhere for an answer about securing my webApi but always i'm pointed to OAuth or openID, but i don't want the user to login or authenticate. This is my problem:
I have a webapi which is called via Javascript to get the data in Json. This data is used in the Html of that page. (deployed on Azure)
Now i don't want someone else to get that data via Javascript or with a simple GET request. Only my html page is allowed to do so.
I'm looking for something to secure my Webapi to be only consumed by the applications i want. If i look to the OAuth and Azure stuff, people always have to login, but i want this page to be public, but only the webapi needs to be secure.
I can't check on IP, because the call is done at client side in the browser.
It is not possible to authenticate and thus secure the API to be used by a specific client (run entirely in the browser - like SPAs) app. You cannot protect the data the app sends to the API. (see for more details Protecting REST API behind SPA against data thiefs)
You could build some modules server side and then use some token based server to server communication if you do not want to introduce users and end user authentication.
Of course it is also a question of how you interpret security.
If it is just that you do not want other web apps to use the data -
CORS policies will do the job. It is unlikely that there will be more
than some isolated cases of users using a browser other than the
popular once which respect CORS.
If it is you do not want data to be mass downloaded you could
implement some client filtering based on IP. This could even be done
on the networking layer so the API do not need to be modified in any
way.
As a suggestion, you can have it secured making sure the request has some headers defined by you. For example, you can set an Authorization header with a token that only you know. You can for example, create a token based on a key that you and the webapi share, encrypt it with the time you are calling the api. The web api receives the request and:
1 - Check if the request has the token it requires;
2 - if it does, it creates a token the same way your page did;
3 - matches its token with the requests token;
If you are calling the webapi via javascript, the method may be exposed. However, it's one idea
Take a look to CORS (Cross Origin Resource Sharing), it may be your solution.
In synthesis you can allow requests to the Api only from some specific websites. Most, nearly all browsers, support it.
This is how you enable and configure it in Web Api 2.

passing userId in Hub of SignalR

Greeting..!, I am making a asp.net chat webApplication using SignalR were I want to keep track of every user and store there actions is database. I use userId to keep track of them.
My problem is that I don't want to pass confidential data(like userId) from client form to signalR hub.And I know SignalR hub class does not support sessions.
so how can I do that.
I am new to signalR and I googled a lot about this problem but couldn't find any simple answer.
SignalR supports different ways to authenticate and authorize users:
Cookie
Windows authentication
Certificate
Connection header
You can find more information about SignalR and security here:
http://www.asp.net/signalr/overview/signalr-20/security/introduction-to-security
Keep in mind that even though some info might be transferred, there is often an abstraction that does not really let someone map a user to a token or vice versa on anything else than the server.
Authentication and authorization is only a small part of security which goes further by using SSL and to carefully think what you transmit as you already said., etc.
But on some point you need a link between relevant information on your server side application and the caller. This might be a session identified by the cookie after a classic forms based authentication, an hash based header or whatever you want to create. SignalR is flexible so you could think about something like authentication against a different system and pass only a delegation token.
You have different ways to map your userId and the connectionId.
Take a look at this tutorial on asp.net

Handling security in an ASP MVC application that uses JS to a REST API

I have an ASP MVC4 web site. Originally, most of the content was served via controllers as one would expect. I have moved the data storage from SQL Server to MongoDB. I have also added a lot of ajax to update data client side, without a full refresh. This is working fine, but my controllers now have lots of methods that take json and return json. I was able to build a Node.js server that hits the database and exposes exactly the same functionality, without lots of going to and from C#.
My javascript client-side is now calling a Node.js REST API, this works great. My 'secure' code (like adding a new user) hits the same REST API from the server side.
My question is this: How can I handle security properly with this? I have three scenarios:
GET api/messages: No need for security, I want to expose my site's messages to anyone who is interested via a Json REST API.
GET api/my/messages: I need to allow access to this only if the user is logged in (it gets the user's messages).
POST api/users: This is a function that should only be called from the server, and nothing else should be able to use it.
As the user is already logging in to my ASP website, how can I use their logged in credentials to authenticate them with my REST service? While the user is logged in, the pages client side will hit it regularly for updates.
Is there any sensible/standard way to do this? The core idea is that the client side code uses a REST API that is at least partially open to the public, and that in fact that API offers all of my business logic - only parts of it (like creating a user) are locked down to super-admins only.
Thanks in advance!
Create two authentication middleware handlers. One you add to all your "my" routes and another which you add to your POST routes.
The "my" authenticator takes the asp.net auth cookie that is present in the request and makes a http call to your asp.net mvc site with it.
You'll need an action which either returns a 401 if the cookie is invalid otherwise it returns some info about that user's permissions perhaps.
If the request into node doesn't have a cookie, return a 401 again.
In addition, to prevent excessive calls to your mvc site to check the cookie, you could use the cookiesession middleware to set a cookie on the client with a flag of authenticated. That will result in 2 cookies for your client, but that shouldn't be an issue. Just make the node one expire before the aspx one.
The POST authenticator middleware can use any shared secret you like between your node and mvc server. e.g. a special header in the request.
If the user is required to login you can use [Authorize] on your controller actions. Autorization will be handled like any other webrequest.
Furthermore you might consider to add a key to your api requests which you can provide in the initial page load. A autorized user will have a GUID which he will sent with the api call. You can check if this key was issued by your app to a valid user.
As you said all the secure calls already go through your MVC server code which in turn calls the Node.js code, am I right? Basically you need a way to block calls to this Node.js from other clients that are not your MVC code.
Thinking out loud, these are the ideas that pop into my mind:
Use SSL only between MVC and Node. You can set up client and server certificates so that the Node code will only respond after authentication (I don't know how Node handles SSL so you will need some documentation here
If you want, the Node server could also check the call origin and so you can filter based on IP and only allow IPs where your MVC code is sitting
Use an encrypted authentication token on the secure methods on the Node code. Again I'm not really a Node expert but I can imagine it has ways of decrypting a token, or you can simply base it on a random number with a common seed... If noone has access to your server code ideally noone should be able to guess this token. Again, SSL will help against traffic sniffing
I am quite sure that people will come up with other ideas. For me, the most basic thing is anyway ensure that the secure methods are only accessible through an SSL connection and on this connection you can exchange all the info (token, passwords, etc.) you desire.

Authentication & Authorization with WPF Client to MVC 4 Web Api

I have created a MVC 4 Web Api using Entity Framework Code-First and a WPF-Application as a client in VS 2012.
The problem I'm struggling with at the moment is that I have to enable Authentication from the client and authorize users for access to the Api (for example: Every authenticated user can access GET methods but only admins can use POST or DELETE). I used MVC 4 Internet Application because of Forms Authentication already being included, which worked fine until I tried to login from my client application. After spending some time researching my problem about I realised that Forms Authentication is mainly supposed to work with webbrowsers. I even found some possible solutions to get it working with HttpClient using CookieContainers (e.g.: How do I set a cookie on HttpClient's HttpRequestMessage), but nothing works for me.
After spending some hours researching ways to accomplish what I'm trying to do I feel completly stuck..
I've read about SimpleMembershipprovider, BasicAuthentication, OAuth and someone mentioned Thinktecture.Identitymodel, but wasn't really able to decide which would work best.
If there is really no way to use Forms Authentication when connecting with a client other than a webbrowser then what is the best Authentication/Authorization method to take?
I would be very happy if anyone could provide me with a hint on what works best in this case, because after researching for hours I only get more and more confused.
Thanks in advance for any help!
You should be able to do this easily enough, but you haven't said what your problem actually is. Are you
unable to get access to your web api actions because you aren't logged in; or
unable to make it enforce authorisation (i.e. you can get anonymous access to actions)
For the second scenario:
There is a very good overview of using Authentication and Authorization in ASP.NET Web API on the server side, and the various ways you can enforce different roles on Actions.
There is also another approach that is appropriate for machine-to-machine (i.e. where you don't have a user who will type their login details into an appliation dialog box) in Making your ASP.NET Web API’s secure, but it doesn't focus on using SimpleMembershipProvider. Instead of using the framework auth&auth components it uses tokens (take care with this approach - rolling your own security is very very hard to get right).
For the first scenario:
From the client side, it sounds like you have some a C# application that user's interact with. If this is the case (rather than the machine-to-machine scenario) then your Forms-based approach is still suitable, and you are doing the right thing with your cookies. The approach would be:
Ask the client to type their username and password in to your application
Send a request to your LogIn action on your AccountsController, this will return your authentication cookie, session cookie etc.
Store the cookies that are returned from this (successful) login (or notify the client if the response was "login failed"
Then use those cookies in the request to the web api
As you are already talking about using HttpClient, I'm guessing you know what you are doing for this, so haven't provided code samples. I wouldn't use HttpClient, for what it's worth, but HttpWebRequest which allows you to keep a common CookieContainer through the HttpWebRequest.CookieContainer property.

Categories

Resources