ASP.Net MVC 4, Web API, and Passing Parameters Securely - asp.net-mvc

So I have been happily building my ASP.Net MVC 4 application for a month now. I have the security model in place, users can log in and secure information is being stored in the users session for subsequent page requests. This all works great. I then implement some ajax calls to get additional data into the page. I do this by making a call to a Web API interface. In the Web API call I try access Session and low and behold Session is null. Now I get that Web API is supposed to be "stateless". All the parameters for a web api call should be passed in. But what if some of those parameters are sensitive and can not be passed up from the client when making the ajax call?
I've read about the hacks to get access to session in WebAPI. I would prefer not to do this and violate the tenants of web api. ?
So do you store this information in the database and pull it out in the web api call? Seem like a PITA to do that.
So how would could keep certain parameters secure when making the web api ajax call?
Or do you break down and just get access to session?

Each service call could accept a user id.
The WebAPI controller method uses the user id to do further data look ups, such as looking up sensitive order details.

The way I do it is inheriting from a Base Class, and this base class has the following:
public string UserName
{
get
{
return User.Identity.Name;
}
}
The WebAPI can see this UserName and each UserName is unique, so you can do a user lookup based on this variable.
If you're wanting to send any further data to the WebAPI then you're going to have to send, say, an ID to the Controller and validate it against the UserName to see if they have access to it.
Psuedo...
I want a Policy!
Client side
Sends Policy ID (1234 to WebAPI, meaningless to a hacker if they can't get info from it)
This ID is validated against
User.Identity.Name to see if information can be retrieved

Related

Cookies based authentication in asp.net

I am working on a project which is based on asp.net mvc, jquery and web api.
Currently I am setting sessions which are being used to authenticate users.
When an ajax call to web api is made I check if the user is currently logged in then respond him with the data else with an error.
protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (SessionManager.IsUserLoggedIn == false)
{
return false;
}
return true;
}
The POCO I'm materializing from login stored procedure contains almost 10 GUID(UserGUID, DeptGUID etc) and int properties.
Now the problem is that I need to completely remove session from application and use cookies to do that authentication process. I've read some solution which propose by using web form authentication I should put all my properties in the cookie (can be encrypted) and send this authentication cookie within request header with every request to the sever. Although I am using GUIDs but some critical flags are in integer form. Will it be wise to put that information out there in client browser?
Also on front end scripts I am making some decisions based upon the values of the properties which are stored in cookies.
How to ensure that the cookie I am receiving has not been tampered with?
What will be the most efficient and secure way to implement cookie based authentication in my scenario (web api, asp.net mvc )

How to make WebAPI actions accessible only from my app?

A common use case for WebAPI would be to have shell views rendered by MVC controllers, which contain javascript that then hit your API to access data.
But let's say you have some expensive API operations and you don't want people remotely accessing those endpoints -- you only want your MVC views, delivered by your application, to access them. How could you go about protecting them?
In this case Request.IsLocal doesn't work, because javascript is invoking it from the client's browser on their machine. Even if it did work, you need to dig to get the real HttpContext in order to find this property -- and that solution wouldn't work in self-hosted WebAPI.
For API endpoints that require a valid IPrincipal, you could protect them with the [Authorize] attribute. But what about API endpoints that you want your app to be able to access for anonymous users?
I have tried a solution and will post it separately as an answer, because I'm not sure if it's the best (or even a good) approach.
If your MVC site uses authentication, you could enable forms authentication for your Web API methods. You could write a custom [Authorize] attribute that will check for the presence of a forms authentication cookie which will be sent from the AJAX call and if present construct the principal.
Another possible solution is to protect your API with tokens which is a more RESTful style. The idea here is that when a user authenticates on your MVC website you could generate and pass a token to the view which will be used when sending the AJAX request to the Web API which in turn will verify the validity of the token and its signature.
If on the other hand your site doesn't use authentication, then things will get very complicated because you have no way of knowing whether the request comes from a trusted client since you are using javascript to call your API methods.
Before you go harping about "what have you tried", here is what I have tried. It works. Just not sure if there is a better way.
Create an MVC action filter and add it as a global filter during Application_Start.
Create an Http (WebAPI) action filter and use it on actions that should reject remote requests.
The global MVC filter does this:
Looks for a specific cookie in the request. If the cookie is there, its value is decrypted. The decrypted value should be a string representation of a DateTime, so use DateTime.TryParse to get it out. If the value is correctly parsed to a DateTime, and that DateTime is less than a day old, STOP HERE and do nothing else.
If the cookie is not there, or cannot be decrypted / parsed, or is older than a day, write a new cookie to the browser. Use the current DateTime.UtcNow.ToString() as the value, encrypt it, and write it with HttpOnly = false.
The WebAPI filter does this:
Looks for a specific cookie in the request. If the cookie is there, decrypt its value and try to parse it out as a DateTime.
If the value is a valid DateTime and is less than 2 days old, STOP HERE and do nothing else.
Otherwise, throw a 403 Forbidden exception.
A couple of notes about my current implementation of this. First of all, I use AES encryption with a shared secret and a salt. The shared secret is stored as an appSetting in web.config. For the salt, I enabled anonymous identification and used Request.AnonymousID as the salt. I'm not entirely fond of the salt because it's tricker to get at in a WebAPI controller, but not impossible as long as it is not self-hosted.

How can I store user data after login without having to query the database to show this data?

I need to store the user ID, his company ID and name, in a way I won't have to query the database on every postback.
I know I have options like: ViewData, TempData or auth cookie, but, are there any better solution?
Best regards,
Juliano Nunes
This sounds like a classic use of Session.
ASP.NET session state enables you to store and retrieve values for a user as the user navigates ASP.NET pages in a Web application. HTTP is a stateless protocol. This means that a Web server treats each HTTP request for a page as an independent request. The server retains no knowledge of variable values that were used during previous requests. ASP.NET session state identifies requests from the same browser during a limited time window as a session, and provides a way to persist variable values for the duration of that session. By default, ASP.NET session state is enabled for all ASP.NET applications.
ASP.NET Profile Providers mechanism looks like a thing you're looking for - especially if you're already using Membership/Role providers.
More generic article on Profile properties: MSDN

ASP.NET MVC 3 Web API - Securing with token

I'm trying to find the simplest way of implementing token based authentication for a number of ASP.NET MVC actions.
The Api controllers sit alongside a web app, so I need to be able to specify which actions/controllers are subject to Api authentication.
I already have a membership provider that is used for forms authentication so I'd like to reuse this to validate the user and build the returned token.
I've read several articles on implementing OAuth, but most seem really complex. I've seen several examples of using an API key, but I want to request a token and then pass it back as a parameter not necessarily as a value in the HTTP header.
Essentially process needs to be:
User requests token from auth action passing in username and
password.
Service returns enc token
User passes enc token to future calls as a parameter to auth
What's the typical way this is done, does the client (say ajax call) need to compute a hash of the user name/pass in 1)? or plain text ok over TLS/SSL?
Any advice appreciated.
What are you concerned about with what you described?
The process you described seems viable. Typically systems will have an expiration on how long the token will be valid for, after which they need to get a new token. There are many variations for expiration though (fixed time, sliding time, etc..).
To your question regarding the username / password, the client shouldn't hash them. Just make sure they are transmitted via a secure method (SSL).

how to limit visitors to an api end point to those that are visiting my site

My website does not require login. And actions that the user takes end in calling ASP.NET MVC Controller Action Methods. Any other company can call those endpoints at this time and use my APIs in this way. I want to make sure that only users who are on my site can access these APIs.
How do I achieve that?
Adding clarification:
Say my site is consoto.com. I want my methods to work only if the end user is on consoto.com. Now if another company or hacker builds a site say hackland.com and in their javascript calls my methods, I want it to fail because their users are not on consoto.com and instead are on hackLand.com.
Many sites these days offer paid official API access to their core functionality. If they don't implement a mechanism like this, others will have the option to call the methods the actual site uses instead of going through the paid API. What would prevent a hackland.com to just use the methods used by consoto.com and end up not paying for the service?
I'm not %100 sure I understand you but, it seems like you only want to give active users on your website the ability to call certain action methods. If that is the case you can decorate the action methods with [ChildActionOnly]. This will force ASP to only allow actions that are called with HTML.Action() in the view code.
controller code
[ChildActionOnly]
public ActionResult someAction()
{
//return whatever you need
}
view code
Html.Action("someAction")
That should prevent people that aren't actively viewing the site from calling an action on the server.
There's no reliable way to achieve that if you don't require authentication on your site a then allow only authenticated users to call server side actions.
One way to do it would be to use some sort of time sensitive token that the client must supply to your Controller.
Implement a web service that takes some credentials from the user, and if the credentials are valid, return a time sensitive token that is hashed based on your server clock. This service should be called through SSL so the credentials are protected in transit.
Each of your protected controllers will expect this token in addition to whatever other inputs they currently expect. You will then validate the token by de-hashing it to obtain the time stored within. Here you can decide how long you want the token to be valid for and choose a time interval to accept. For tokens that do not de-hash property or are expired, return some error result. For tokens that are valid, return the correct result. Rather than the tokens being time sensitive, you can also implement a use count scenario, but the time sensitive approach is easier.
This way, your API controllers will not require login or SSL. Your valid users will just need to obtain the token from you before hand and then use it to call your services. Anyone else can intercept these tokens but they won't be any good after a possibly very short period of time.

Resources