I have gone through many blog articles describing how to validate users in our web applications using [ValidateAntiForgeryToken] attribute. But this has limitations such as can be used only with HTTPPOST methods. My requirement is I have a MVC 5 application which returning sensitive data (Ex: bank statements) using HTTPGET methods. How to authorize/protect these action methods from anonymous users ?.
I want to write a token based authorization mechanism.
You are correct - the ValidateAntiForgeryToken mitigates against Cross-Site-REquest-Forgery (CSRF). It is specific to POST's, as it can correlate the a response issued by a server, and the HTML posted from a user. There is no concept of CSRF for GETs.
To protect GETS from anonymous users, use the [Authorize] attribute on any methods that you require users to be logged into the websites. If they are not, they will be redirected to the login section, as configured in your web.config.
Related
I would like to know that how [Authorize] attribute recognize that this user is authenticate?
If user is valid then we call FormsAuthentication.SetAuthCookie() method and as per MSDN this method:
Creates an authentication ticket for the supplied user name and adds it to the cookies collection of the response, or to the URL if you are using cookieless authentication.
Is [Authorize] attribute checks authentication ticket or cookies collection?
[Authorize] does not deal with any authentication mechanism itself. It merely looks in the users IIdentity for the IsAuthenticated flag. It will also look in the users IsMemberOf method, for authorization based on roles.
All the work to decode the authentication ticket is done in the early stages of the app pipeline, which sets those flags. By the time the Authorization Attribute methods are called, all that work has already been done and is stored in the users runtime data.
You can easily check the source code for the Authorize attribute, and you will see that it's quite simple in nature. It just returns true or false based on some simple lookups.
It's become more complicated in .net core, where it's based on policies and what not, but the original MVC implementation was quite simple.
My answer relates to ASP.NET Core I'm not sure if you asked about classic ASP.NET but this should be similar.
There's a middleware that you have to add for [Authorize] to work. ASP.NET Core provides this middleware out of the box and you can add your custom authentication handlers too.
You can check how it's implemented by reading: https://github.com/aspnet/Security/tree/dev/src
For example you want to use JWT bearer authentication, you have to add JWT bearer middleware, this is simply extension of AuthenticationBuilder: https://github.com/aspnet/Security/blob/dev/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerExtensions.cs which calls AddScheme under the hood.
You want to use cookie based authentication you just call AddCookie which is also extension that calls AddScheme under the hood: https://github.com/aspnet/Security/blob/dev/src/Microsoft.AspNetCore.Authentication.Cookies/CookieExtensions.cs
Usage of it is documented here: https://learn.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x?view=aspnetcore-2.1
See also Using the [Authorize] Attribute
Web API provides a built-in authorization filter, AuthorizeAttribute. This filter checks whether the user is authenticated. If not, it returns HTTP status code 401 (Unauthorized), without invoking the action.
If you are interested how this filter works under the hood you can check it here.
You must be authenticated before you can be authorized, this is the logic responsible for it: https://github.com/aspnet/Security/blob/644f34e90d35b369efdce9c11ab1db42e0a7f4a7/src/Microsoft.AspNetCore.Authorization.Policy/PolicyEvaluator.cs#L91
In summary
how [Authorize] attribute knows that this user is authenticated.
Authorize attribute alone doesn't know if this user is authenticated. This is handled by authentication middleware and depends stricly on the scheme it tries to authenticate with. It simply tries to authenticate with schemes you have added(cookie,jwt etc.) by calling HttpContext.AuthenticateAsync which is simply calling AuthenticationService.AuthenticateAsync under the hood and sets HttpContext.User from the result ClaimsPrincipal, which is simply result from schema handler like jwt handler for instance. I think this should give you more in-depth idea how this works.
Generally if you're starting new project I don't recommend using classic ASP.NET and prepare for the future with .NET Core as everything is now going in this direction. ASP.NET 5 ( I also refer to it as "classic") is pretty much dead now.
I have a ASP.NET MVC website.
I don't really manage users, but I do a login to an external API and then I store a "ASPXFORMSAUTH" cookie.
It's a WCF service. In my controller, I call :
MyWcfServiceClient.Login()
In the AfterReceiveReply, I store the response of the service in a variable :
cookie = httpResponse.Headers[HttpResponseHeader.SetCookie];
Then In the controller, I get this cookie and store it using :
Response.Cookies.Add(cookie);
I'm a beginner with ASP.NET MVC, but can I use the [Authorize] attribute to allow the access to the controllers methods only if the request contains this cookie ? And [AllowAnonymous] on the methods before the API login.
EDIT :
So it should work just adding the [Authorize] attribute ?
I'm calling the controller method using ajax, and the value of Request.Headers["Cookie"] is .ASPXAUTH=1D415AF723......
But I get the ajax error callback...
Am I missing something ?
[Authorize] will allow access to authorized users only.
You can either put it at the top of the controller so it applies to all functions on the controller or in front of individual functions. its more powerful than that though as you can allow only specific users or roles. documentation here
The allow [AllowAnonymous] is used when you have added some sort of Authorize to the whole controller but want to allow access for all to a function on the controller. its not required if the controller doesn't have an authorize attribute on it. example here I think the default MVC account in visual studio uses this on the account controller for password rest and login.
I'm not fully sure since I haven't tried it before. But if you set the correct cookies (the default aspx auth cookie) the AuthorizeAttribute should prevent you from reaching the controller if you aren't authorized. Have you tried using the authorize attribute on a controller and logging in using your external API? Because it might just work out of the box.
Another option is to extend the default attribute by making your own. See the following articles for more information about this.
Article from John Galloway
Another question here on SO about extending the Authorize attribute
MSDN Article about the Authorize attribute
I have a .Net MVC application. I use Asp.net Identity for login and roles.
Every controller I have is decorated with [Authorize]
I have not done anything else in the code to protect the application.
Is there anything Else that must be done in ordet to protect the site? And im not takling protection of the webserver. Only the website.
Thanks
Add MVC's anti-forgery support, this basically writes a unique value to an HTTP-only cookie and then the same value is written to the form. When the page is submitted, an error is raised if the cookie value doesn't match the form value.
It's important to note that the feature prevents cross site request forgeries.
How to use it:
Decorate every controller action used to post data with this: [ValidateAntiForgeryToken] and add the unique value to your form posting the data by adding the following to your form #Html.AntiForgeryToken()
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
Imagine I have a HTTP POST action with a method signature of:
RegisterUser(string email, string password)
The implementation of this method does some basic validation (e.g. to see if e-mail doesn't already exist in a user repository) and then stores this information as a record in the user repository.
Say I then go on to make an AJAX call to this action from a "registration" view. If some malicious user looks at the markup of that view on the client-side, they'll pretty easily be able to see the URL to the RegisterUser action and determine what they need to pass to it (email and password).
What is then stopping that user from writing a program that calls this action a 100 million times? What safe guards can I put into place? Is there something I should read up on in ASP.NET MVC that will protect me from such a POST attack?
Thanks
I would recommend you installing the Dynamic IP Restrictions module in IIS or implement a throttling solution in your application. This would prevent the same user from sending multiple requests to the controller action. It won't protect you against DDOS attacks though because in those kind of attacks the requests are coming from different IP addresses.
The most common form of prevention against a Denial of Service (DOS) attack which is what you are describing is to use some type of Captcha.
Although this question has been closed it should provide some useful information on implementing this within ASP.NET MVC