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.
Related
I need to achieve to authenticate users with their domain user/password, if they're are in the domain controller, but the application should be available for other users as well, who should be authenticated with their own username/password; this should be stored in the application database, and their username/password to be checked against the DB.
So far i started with new asp.net template in vs2015, choosing Individual User Accounts.
I'm able to authenticate users agains domain controller, but if that is succeeded I'm unable to store the user to HttpContext.User property.
In SignInManager i call PasswordSignIn and return Success or Failure depending on AD check.
public SignInStatus PasswordSignIn(string userName, string password, bool isPersistent, bool shouldLockout) {
if(AuthenticateAD(userName, password)) {
//
// to create identity/principal and assign to HttpContext.User
//
return SignInStatus.Success;
}
else {
return SignInStatus.Failure;
}
}
public bool AuthenticateAD(string username, string password) {
using(var context = new PrincipalContext(ContextType.Domain, "domainname")) {
return context.ValidateCredentials(username, password);
}
}
thanks for any hint!
The only way this really works is if you create proxy users in your application for users in AD. Essentially, you just set up a script that populates new users/updates existing users based on the data in AD on a schedule (nightly, etc. based on your needs). Then, you're dealing with just one type of user whether they're part of the domain or external. The only change you need to make is to selectively authenticate via AD or via the standard password authentication. Either way, the same user principal is in play.
You can use ADFS and allow users to choose where to authenticate. It is quite trivial to implement using default template. Just like usual login mechanics with Sign-in via google and local account.
I think this is most correct way of doing things, because domain users may end up with Kerberos/Ntlm, if they want, and it lowers complexity of your system.
Here is a WS-Fed example: Using Claims in your Web App is Easier with the new OWIN Security Components
For other stuff you can create app with default template. This app will have external authentication stuff as example.
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
}
}
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)
I need to verify whether the authenticated user has an active membership to my site. For example, if the user's membership is active they are freely able to browse the "members only" area of the site, whereas if their membership is inactive or expired they are automatically redirected to the billing area of the website. They would only be able to view certain restricted pages.
I am thinking of approaching this by storing the user's membership expiration date in the FormsAuthentication cookie. I am using a custom MembershipProvider and already storing the user's ID in the cookie, so this would be easy to do. The authentication cookie is set to expire in 24 hours. Then I would check whether their membership is active using a custom AuthorizeAttribute, like so:
public class MembershipAuthorizeAttribute : AuthorizeAttribute
{
private readonly bool authorizeMembership;
public MembershipAuthorizeAttribute()
{
this.authorizeMembership = true;
}
public MembershipAuthorizeAttribute(bool authorizeMembership)
{
this.authorizeMembership = authorizeMembership;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (this.authorizeMembership)
{
// Code to validate the membership hasn't expired
}
return base.AuthorizeCore(httpContext);
}
}
Then I can just decorate my controllers as such:
[MembershipAuthorize]
public class ActiveMembersController : Controller
{
// Only users with an active membership can access this controller
}
[MembershipAuthorize(false)]
public class BillingController : Controller
{
// All members can access this controller
}
Is this a good approach to take or is there a cleaner/more preferable method to validate whether a user's membership is active? I would prefer not having to hit the database on every request just to retrieve the user's membership expiration date or status, which is why I want to store this value in a cookie. Also, is it fine to store this value in the FormsAuthentication cookie, or should I be storing this in a different cookie?
Storing that information in a cookie does not strike me as the right approach. The reason, as it is pointed out in this answer https://stackoverflow.com/a/706874/2168278 is that cookies are stored in the client's machine. So it's possible that they can be tampered.
Storing this information in a database seems more appropriate. If you are concerned about performance you can always cache your queries.
I would approach this differently. I would have a background process to check for memberships that are expiring and disable those accounts.
If users attempt to login I would check if the account is disabled and then act upon that.
In my application I have a top level entity called Organization. The relationship between User and Organization is many-to-many.
Because of this I could have the following scenario:
UserA has role ROLE_ADMIN for OrganizationA
UserA has role ROLE_USER for OrganizationB
I need to ensure that when UserA accesses resources for OrganizationB he is not doing it as an ADMIN. So I need an additional check that the user has the correct roles at the organization level. Is there anything built into Spring Security that allows for this? If not, does anyone know what the best way would be to about solving this?
UPDATE: A bit more information...
A User logs in and chooses which org they want to work with. That is stored in the session. Beyond that, URLs are locked down with the Secured annotation. What that means is that if UserA were to log in and select OrgA, they should be able to access /admin/user/create however, if they log in and choose OrgB they should not have access to that URL.
The long way is to add additional checks in every method where this matters. So call some service method that says "ok, you're an admin for OrgA but not for OrgB and you're logged in using OrgB, so deny this request".
I'm hoping for a more grails / spring-security way of handling this.
You can probably do this by using a custom AccessDecisionVoter. The vote method will supply you with the "configuration attributes" for the resource (method or URL), which will typically be the required roles, and you can obtain the current user's roles/authorities either directly from the Authentication object, or by reading the current org and selecting the appropriate roles for the user.
I'm assuming that you have some way of differentiating the user's roles, based on the org they've selected.
Essentially, you'd be writing an extended version of the standard RoleVoter, which takes the organization into account.
I think I'm little late here but this is what worked for me:
When an organization is selected, you can set a new Authentication object with new roles in your session(The previous Authentication object gets invalidated). Something like this:
#RequestMapping(value = "/org-a")
String orgA(HttpServletRequest request) {
request.getSession().setAttribute("org", "org-a")
Organization org = new Organization("org-a")
reloadRolesForAuthenticatedUser(org)
....
}
private void reloadRolesForAuthenticatedUser(Organization org) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication()
List<String> newRoles = getRoles(auth.getPrincipal().getUsername(), org)
List<GrantedAuthority> authorities = getAuthorities(newRoles)
Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(),auth.getCredentials(),authorities)
SecurityContextHolder.getContext().setAuthentication(newAuth)
}
private List<GrantedAuthority> getAuthorities(List<String> roles) {
List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>()
if (!roles.isEmpty()) {
for (String r : roles) {
auths.add(new SimpleGrantedAuthority(r))
}
}
return auths
}