Security check an User to a access controller action - asp.net-mvc

Hello guys I have a MVC actions that have Authorize attribute set on them. For each one of these actions there is a password/ security pin which is only valid for that Action.
public ActionResult Action_1()// generic pin 1
{
Return RedirectToAction("PinCheck", new { returnUrl = "Action_1" });
...
}
[Authorize]
public ActionResult Action_2()// generic pin 2
{
...
}
[Authorize]
public ActionResult PinCheck(string returnUrl)// generic pin 1
{
// request three characters of the pin in random.
...
}
[Authorize]
[HttpPost]
public ActionResult PinCheck(string a, string b, string c, string returnUrl)// generic pin 1
{
// check the three chars.
...
// How do I store pin check for the controller was a success and don't ask the user unless he closes browser or logout
}
My plan of action is checking pins stored by the Admin for the particular User for that particular Action in the Database. So far I have achieved checking PinCheck() routine but the problem I face is that the User has to enter the pin every time he requests that particular action. I made a way around this by saving an encrypted cookie on PinCheck success. But is there a way to modify the Authorize attribute and the Authentication cookie itself to achieve What I am doing?

You can also represent each Pin verified as a claim stored as part of the ClaimsIdentity in the cookie so that you can just query against the user's claims looking for the appropriate PinClaim in each Action. If you are using the ASP.NET Identity, you can do something like so when you verify the pin:
await manager.AddClaimAsync(User.Identity.GetUserId(), new Claim("<mypinclaim>", "<value>"))
await SignInAsync() // And then resign the user in to regenerate the cookie with the claim

One ways of doing this is by creating a custom role provider. You could create one by inheriting from RoleProvider. Then override IsUserInRole and optionally FindUsersInRole, GetAllRoles, GetUsersInRole to reflect your pin management logic.
Once done, register the custom role provide via the web.config.
A good article on custom role providers (http://bojanskr.blogspot.com.au/2011/12/custom-role-provider.html)

Related

ASP .NET Core Custom Authorize Attribute for viewing users own data

Scenario: User1 with "View" permissions can see all other user profiles in a list and when they click on a profile they will be directed to that profile page.
User2 with no permissions can see a list of user profiles but can only click on their own profile to view otherwise they are redirected to forbidden.
Not sure of the best method to implement this Authorization check. Currently trying to use the answer from this question: Adding .Net Core Policy with variable Parameters on Requirements
but I don't know how I could send the id parameter from this controller method and also check first if the user does have the "View" permission
[HttpGet("{id:int:min(1)}")]
[CustomAuthorizeAttribute(id)] // doesnt work
public async Task<ActionResult> GetUser(int id)
In that solution, The parameter is a certain value in development, not obtained from routing. [CustomAuthorizeAttribute(id)] is scanned when project starts, it is different form the [HttpGet("{id:int:min(1)}")].
In this scenario, I think you don't need to define the CustomAuthorizeAttribute. If one user can view all the profiles, the user need to be added the claim View when generating token.
new Claim("Permission", "View")
When in GetUser, you only need to judge whether the user has the claim.
[HttpGet("{id:int:min(1)}")]
public async Task<ActionResult> GetUser(int id)
{
if(User.Claims.Contains(new Claim("Permission", "View")))
{
//...
return View();
}else if(User.Claims.Contains(new Claim("id", id.ToString())))
{
//own id can view own profile
return View();
}
else
{
return Forbid();
}
}

Determining ASP.NET Identity's authenticated user within MVC controller JsonResult method

I am using MVC 5 and have a View that contains a jQuery Ajax call to the controller and retrieve some data. Previously I was unable to make this Ajax GET because the controller is marked [Authorize], so I marked the method as [AllowAnonymous].
At this point I have a need to determine the authenticated user, but User.Identity shows IsAuthenticated = false. This makes sense, but I am needing to know how I can obtain the user's identity within this method. Here is the method:
[AllowAnonymous]
[AcceptVerbs(HttpVerbs.Get)]
public JsonResult GetDesignParams(string countrycode)
{
ApplicationUser user = UserManager.FindById(User.Identity.GetUserId());
if (user != null)
{
... do something ...
}
... do something else ...
return Json(rules, JsonRequestBehavior.AllowGet);
}
Is there a way of obtaining the user's identity within this routine without passing the user id from the client side Ajax GET?
You need to go through bearer tokens in order to make your API-like method secure
See this: Secure a Web API with Individual Accounts and Local Login

In asp.net mvc when updating data how does one know that the data beeing manipulated does really belong to the user making the call?

In asp.net mvc when creating, updating, deleting data how does one know that the data beeing manipulated does really belong to the user making the call?
[Authorize]
[HttpPost]
public ActionResult Edit(Model model)
{
// edit data in database
}
If a user is only to manipulate his own data but can see and easily find out information of other users witch is public to manipulate.
How can i be sure that the user is really who he says when for example Edit is called?
The Authorize only makes sure that a user has logged in.
I'm thinking about using controller.User.Identity.Name in the update to make sure the user how created the data is the one that changes it.
But then comes the question could it be possible for a user to go around this by manipulating controller.User.Identity.Name ?
How can one know that a user is who he says he is with regard to this?
There are two kinds of authorization.
One, which is very "vertical", has helpers provided by the framework (such as the Authorize attribute). This "vertical authorization" determines if a user is allowed to make a request or perform an action. It knows nothing of the data of the request or the action being performed, just the request/action itself.
The second, which is more "horizontal", doesn't have built-in helpers in the framework because it's subjective based on the business logic of your application. This one is up to you. This "horizontal authorization" determines if a user is permitted to manipulate specific data elements (specific records in the data) under specific conditions.
To put it simply... If a user submits a request to your application (invoking an edit action on a record for example) then while the framework can tell you if that user is permitted to invoke that action you need to manually determine if that user is permitted to edit that specific data.
For example, let's say two users create records in a table. In that table there should be a column indicating the user which created that record. (Username, some identifier, however you want to link it to a user.) This value isn't provided by the user when inserting the data, it's provided by your code when you build the record. You'd probably pull this value from the logged-in identity of the user (however you track username/id in the application).
Later, when a user attempts to edit a record in that table, you would need to validate that the user performing the action (again, based on their logged-in identity) is the user who originally wrote that record (based on the data that's in the table). Or an admin, or in some other way authorized to manage that data based on your business logic. None of this is based on values being sent from the client, it's all entirely server-side.
So while the client-side code may store an identifier for the record being edited, that value can be changed by any savvy user. That value isn't to be trusted. If a user requests a page, edits values, and submits that page then your server-side code would use the page-provided identifier to know which record the user is attempting to edit, but would use the logged-in user identity to determine if the user is allowed to edit that record. In the event that the user has manipulated the form values to edit somebody else's record, the server-side code should just respond with an error or friendly message denying that action.
This is a loaded question. You could do this with roles (if only Admins can edit). You can do this via user IDs (if you only want them to edit their own personal data).
It seems your question on more based on personal user data so lets go that route.
[Authorize]
[HttpPost]
public ActionResult Edit(Model model)
{
var userId = WebSecurity.CurrentUserId;
var previousRecdord = //Logic or service call to get previous record
if (previousRecord.AUthorId != userId)
{
//Do Something
}
else
{
//Edit something
}
}
You could even throw all of this into a service method and have a validate method that is called before the actions on the service are run. something like
[Authorize]
[HttpPost]
public ActionResult Edit(Model model)
{
var userId = WebSecurity.CurrentUserId;
var profileEntity = //some mapper that maps profile to entity
_UserService.EditUserProfile(userId, profileEntity)
}
and then in some service method:
public void EditUserProfile(int userId, profileEntity profile)
{
validateProfile(userId, profile);
saveProfile(profile);
}
private void validateProfile(int userId, profileEntity profile)
{
var previousRecdord = //Logic or service call to get previous record
if (previousRecord.AUthorId != userId)
{
//throw exp of some sort
}
}

Securely passing data between pages

I am looking to create a new Web App that will allow the user to first enter the users id then navigate around the site based on that user's id. So, first the user would search for an ID, select that user and have options available based on that ID.
Currently I am using the Query string to store the ID, so... /AddProduct/2222.
This works fine but I'm not too sure about the security aspects. I've thought about sessions and cookies but I don't think they are suitable for this scenario. Or do I encrypt the ID for the query string?
Does anyone have any thoughts?
Thanks
Edit
I forgot to mention, the users will be authenticated and have specific permissions on each page on the site. The data is also stored in a database. So, the site will be querying and editing/adding to current data.
So basically here you seem to be afraid that some user might modify an item belonging to another user. Alright, this sentence tells us already that you have users and items in your application and that there are some roles associated to those items. And you have a mechanism to identify those users. So you are probably using some sort of authentication such as the built-in FormsAuthentication for example. So now the question becomes: how to ensure that the currently authenticated user is not modifying the product that belongs to another user.
OK, so you have items that belong to users. I suppose that this information is stored somewhere on the server, presumably a database or something. One approach I would recommend you is to write a custom authorization attribute which would check if the requested resource id actually belongs to the currently authenticated user.
For example:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var isAuthorized = base.AuthorizeCore(httpContext);
if (!isAuthorized)
{
// The user is not authenticated or authorized => no need to continue further
return false;
}
// At this stage we know that the user is authorized => we can fetch
// the username
string username = httpContext.User.Identity.Name;
// Now let's fetch the id of the resource he is trying to manipulate from the request
string id = httpContext.Request["id"];
// All that's left is to verify if the current user is the owner
// of the account
return IsOwnerOfItem(username, id);
}
private bool IsOwnerOfItem(string username, string id)
{
// TODO: query the backend to perform the necessary verifications
// about whether the user has permissions to work with the resource
// pointed by the id parameter
throw new NotImplementedException();
}
}
and now all that's left is to decorate your AddProduct controller action with this custom attribute:
[MyAuthorize]
public ActionResult AddProduct(int id)
{
// if we get that far we know that the currently authenticated user
// is the owner of the resource pointed by the id parameter and we
// could proceed respectively
...
}
With this approach you don't need to be using any sessions or encrypting anything. The encryption is already built into the ASP.NET framework under the form of a Forms Authentication cookie which holds the currently authenticated username in a secure manner. This cookie cannot be manipulated -> the user cannot impersonate as another user. So once you've got the guarantee about who the current user is, all that's left to you is to perform the necessary authorization whether he can access the requested resource.

How can I assign a value to HttpContext.User in ASP.NET MVC?

I write a controller like below:
public class AccountController : Controller
{
public ActionResult Login(/*---*/)
{
GenericIdentity identity = new GenericIdentity("userName");
GenericPrincipal principal = new GenericPrincipal(identity, new string[] { "role1", "role2" });
this.HttpContext.User = principal;
/*---*/;
}
}
After login, I can get user name by User.Identity.Name in other controller.
But User.IsInRole("role1") always return false.
How can I assign a value to User, I don't want to use Membership...
You need to persist the user data somewhere so that all subsequent page requests have access to it. Usually you would create an authentication ticket and store it in a cookie. Then for each request you extract the data and create your IPrincipal. This can be done in the Application_AuthenticateRequest method of Global.ascx,
MVC - How to store/assign roles of authenticated users has more information on a simple way to do what you want.
Hm.
Using membership?
At least the lower level API. You need to assign it a principal in some event (which basically turns into a cookie and is deserialized with every call).
Details are in http://support.microsoft.com/kb/306590
Or also in http://msdn.microsoft.com/en-us/library/aa302399.aspx

Resources