How to save claims used in a MVC site using Thinktecture IdentityModel - asp.net-mvc

I am working on a MVC web site with Claims Authentication and also using Thinktecture IdentityModel.
Each user has a set of CLAIMS: City, Username, Email, Roles, Birthdate.
I have 3 tables in the database: USERS, USERS_PROFILES and USERS_CLAIMS.
USERS contains the columns Username and Email;
USERS_PROFILES contains the columns City and Birthdate.
I am saving these values in these tables ... And I save the Roles in the USERS_CLAIMS table.
When I load a user I fill the ClaimsIdentity with the data from these tables.
THE QUESTION IS:
When I create a user should I, for example, save the email both in USERS table and in USERS_CLAIMS table?
It seems data replication but I am not sure ... Or should I save in only one of them?
What is your approach to this? And what kind of claims, beside roles, do you have that don't fit in a USERS or USERS_PROFILE table?
Thank You,
Miguel

As you're using MVC (Model View Controller), why don't you use Models ?
Your ClaimsIdentity is a model, just create a ClaimsIdentityModel.cs in your Model folder, and use it like this :
public class ClaimsIdentityModel
{
public string Username { get; set; }
public string Email { get; set; }
public string City { get; set; }
public Datetime Birthdate{ get; set; }
}
Then, when you load your user, just fill a ClaimsIdentityModel. And you're done.

As name of each table suggest, the values shall represent those only.
Users are identified as by usernames. Email is one of the claim done by the User.
Roles are also claims, so as City.
If you are creating profile table and adding city in profile, it shall be avoided to add it in Claims table. But you need to handle requirement of City as claim by queries Profile table and providing value as claim as needed.
ClaimsIdentity is System.Security.Principal.GenericIdentity type that is used to identify the user in claim based approach.
(Making Model will be helpful in the View)

Related

Extend ASP .NET Identity with custom List<property> and access it in the View

I am using ASP NET Identity 2.0. I need to extend the identity model with an ApplicationOrganization class (many-to-many with ApplicationUser).
So I created new class, ApplicationOrganization with;
public virtual ICollection<ApplicationUser> Users { get; set; }
public virtual ICollection<ApplicationOrganization> Organizations { get; set;}
to ApplicationUser class to create a many-to-many relationship.
I would like to add some combo (html select tag) with available organizations into _Layout.cshtml View. That's a problem for me. In the View I can accces current UserName, UserId or any other string property using Claims. But I don't know how to acces List of ApplicationOrganization connected to User in the View. I would like to avoid creating some new login Session. And I don't want to hit database in every view call.
No answer. Ok, one way I know now is I can serialize list as a string (xml, json or whatever) and store it as Identity claim. When I need it I can parse it back.

Information about form sender - ASP.NET MVC

I would like to create a group in my app. In model that group has a field Admin_ID to specify who is the owner. How to include that information in a form? With hidden field? I don't think this would be safe enough solution... Any other ideas?
In model that group has a field Admin_ID to specify who is the owner.
Then apply authentication (see the tutorial for your MVC version) so you know which user is logged in, use authorization to restrict access to admins only and in the controller assign the creating user's ID to the model when it is created:
[Authorize(Roles="Admin")]
public ActionResult Create(SomeModel modelToCreate)
{
// get user, depends on how your project is set up...
var user = GetLoggedOnUser();
modelToCreate.Admin_ID = user.ID;
}
If hidden field is not enough for security - don't include it there, but have a separate action that only does operation on your Admin group.
Sorry, can't give more details, as your question does not contain enough information.
You can always save the Admin_ID in the Session.
To better understand:
public class Group
{
public int A { get; set; }
public string B { get; set; }
public string C { get; set; }
public string ID_Admin { get; set; }
}
where ID_Admin should be automatically generated when someone who is logged in want to submit that form (he need to fill only A, B and C fields). So let's say currently logged user has ID 42, and he want to submit that form (without any knowledge of that additional field of course) - and I want to include that information about his ID in final model submission.

ASP.NET Identity User and Roles in Multisite [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I am trying to create a permissions system in an ASP.NET MVC Application. I have been learning the newest Identity framework - here are my requirements:
A set of Hierarchical Roles for each set of functionality. So, for instance, there might be the following roles:
Inherit
Reader
Editor
Manager
Administrator
Each user would have one of those roles for each module (e.g. Events, Pages, etc.)
Users can be members of a security group. Each security group can be assigned a role directly and then all users in that group (who have not been explicitly assigned that permission) will inherit that role.
Multi-tenant site: each user has a set of sites which they are a member of. In the context of each site, they have a complete set of permissions which can be assigned by the site admin.
Through extending ASP.NET Identity, is it going to be possible for me to accomplish all of this? Or should I be building something custom from the ground-up?
9,999 times out of 10,000 implementing your own authentication system is the wrong way to go. Anything is easier than that, and it's a deceptively difficult thing to do right. ASP.NET Identity is actually pretty customizable, as it was created specifically for that purpose. You might need to do quite a bit to bootstrap your custom requirements fully, but it'll almost certainly be quicker and more secure using ASP.NET Identity.
UPDATE
UserManager's constructor takes an implementation of IUserStore. When working with Entity Framework, you typically just feed it Microsoft.AspNet.Identity.EntityFramework.UserStore, but this is your tie in point for extensibility. So, you can simply subclass UserStore and then override something like GetRolesAsync to do whatever custom role logic you need to implement. Then you'd just feed UserManager your subclass.
In version 1.0 of ASP.NET Membership, the IRole interface must have a string primary key. However in version 2.0, released March 2014, they added an IRole<TKey> that allows you to specify a role's primary key, as long as TKey implements IEquatable<TKey>.
That said, out of the box MVC integration points for authorization still depend on roles being ID'd by a single string. So if you are going to do authorization there, via attributes like Authorize, then you may need to write your own custom authorization attributes.
One way to achieve hierarchical roles would be to handle it in your application instead of in the model. I assume by hierarchical, you mean that Administrators have all the privileges of Managers, Managers have all the same privileges as Editors, and so on. You could achieve this by adding users to multiple roles, instead of having to walk through a modeled role hierarchy. Something like a db trigger could do it, but you can model it as a business rule in code too. Then if you restrict a page to Editor, Admins & Mgrs would have access to it as well.
Another way would be to just authorize certain actions for multiple roles:
[Authorize(Roles = "Administrator, Manager, Editor")]
public ActionResult Edit()
[Authorize(Roles = "Administrator, Manager")]
public ActionResult Manage()
[Authorize(Roles = "Administrator")]
public ActionResult Admin()
I disagree though that you would want to id roles on a composite key. If you want to protect MVC actions using the Authorize attribute, the ID of the role needs to be a constant value, like a string literal, int or Enum value, etc. If you keyed role on more than one of its properties, the number of properties you need to set on the attribute multiplies by the number of values in each component of the id. You would have Manager/SiteA, Manager/SiteB, and so on.
Instead, it sounds like it might be a good idea to just add properties to the gerund that tracks users in roles (the in-between table in a many-to-many relationship). To do this, you wouldn't be able to simply override and extend methods in the UserManager class as #Chris Pratt suggested. But that doesn't mean you have to throw out the baby with the bathwater. You can still use Microsoft.AspNet.Identity for authentication, and just write your own methods for role management, augmenting them to take an additional parameter:
AddToRoleAsync(TUser user, string roleName, string siteId);
public class Role : IRole<int>
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<UserInRole> Authorizes { get; set; }
}
public class UserInRole
{
public int RoleId { get; set; } // part of composite primary key
public int UserId { get; set; } // part of composite primary key
public string SiteId { get; set; } // part of composite primary key
public virtual Role Role { get; set; }
public virtual User User { get; set; }
}
public class User : IUser<int>
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<UserInRole> Authorized { get; set; }
}
Given the above, say your URL's look something like this:
/sites/site-a/admin
/sites/site-b/manage
/sites/site-c/edit
/sites/{siteId}/do
...you could write a custom authorization attribute that checks the URL and authorizes the principal both against the role name in the attribute and the siteId in the URL. To get access to the db from the attribute, if you are using IoC for EntityFramework, you can property inject an instance of your DbContext (or whatever interface you have wrapping it).
Following steps can solve your problem
Create granular level of roles...typically for each action
Group them up into GroupRoles...so that admin can easily manage it
Add individual level claims to user for specific permission
Some good examples of the same are below
http://www.3pillarglobal.com/insights/granular-level-user-and-role-management-using-asp-net-identity
http://bitoftech.net/2015/03/11/asp-net-identity-2-1-roles-based-authorization-authentication-asp-net-web-api/
Hope this solves your problem

User groups management

I am trying to implement user management functionality for a web site.
I am using ASP.NET MVC 3, Entity Framework 4.1, MvcScaffolding.
Let's consider the entities:
The user entity:
public class User
{
public int Id
{
get;
set;
}
public string FirstName
{
get;
set;
}
public string LastName
{
get;
set;
}
public virtual ICollection<UserGroup> Groups
{
get;
set;
}
}
The user group entity:
public class UserGroup
{
public int Id
{
get;
set;
}
public string Name
{
get;
set;
}
public virtual ICollection<User> Users
{
get;
set;
}
}
As you see, there is the many-to-many relationship between the user and the user group entities.
So, I would like to have the following UI for editing an user group:
There are two grids:
1. Users grid contains current state of the user group which is being edited.
2. Browse users grid contains all users (except the users which already belong to the user group). When the user row of this grid is clicked, the user will be moved to the users grid. Also, this grid should support paging, filtering and sorting to provide nice user browsing.
So, the user picks users for the user group and then clicks the "Save" button. User group controller class should save the changes.
Now the question: how can the functionality be implemented? Is there any good example for the such many-to-many relationship problem?
If there is no simple solution, what UI for the user group management could you advise me to use?
P.S. I am quite novice with ASP.NET, so I don't realize how to implement such dynamic grids.
Update 1:
I have looked through the jqGrid examples. link
See Advanced -> Multi Select
There is the problem, the checkboxes' selection is reset when you change the filter. How to store all selected IDs despite the filter change?
Telerik has great grid: http://demos.telerik.com/aspnet-mvc/grid/detailsajax.
I could not understand your whole scenario, especially this: "Browse users grid contains all users (except the users which already belong to the user group). When the user row of this grid is clicked, the user will be moved to the users grid".
I think scenario could be this:
If user is at concrete group, two grids are shown:
a) users existing in group, where each row contains user info and button remove
b) users not existing in group, where each row contains user info and button add
In such case, all logic is quite straightforward, you don't need any fancy logic, as everything is on same page.
In user page, there could be a grid with groups, and if user is in that group, in that row is button remove, and if user is not, there is button add. With well chosen user dto for edit view, that will be also quite straigtforward to implement.

Remote attribute in asp.net mvc – in some situations restricts our model

I’ve got an unexpected situation when using Remote Attribute in ASP.NET MVC3.
The model type I used:
using System;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;
namespace dTweets.Models
{
// at first time, user should create his account with unique username
// as in twitter.com, user do
public class UserMetadata
{
[HiddenInput]
internal int Identity { get; set; }
[Remote("IsUserExist", "Account")] // at any HttpPost, username should
// be unique – not appropriate if
// updating/editing this model later
[Required(ErrorMessage = "username should be unique")]
public string UserName { get; set; } // user cannot change it, later
[DataType(DataType.Password)]
public string Password { get; set; } // user can also change password, later
[DataType(DataType.MultilineText)]
public string About { get; set; } // Optional field – user can edit it later
}
[MetadataType(typeof(UserMetadata))]
[Bind(Include="UserName, Password, About")]
public partial class User
{
}
}
Remote attribute validates user unique name at account creation time. But when later user wants to update/change his account, Remote attribute did not allow to update model if keeping user unique name the same one.
This is not appropriate result because rarely user changes their unique user name. They just change other fields like About field or password etc.
[Note: at account creation time, I want to check user unique name so I used Remote attribute here, but at later time when updating user account I no longer need Remote attribute]
I must remove Remote attribute for updating this model later.
I want to update/change this model without changing user unique name (remote attribute is applied to this unique name).
one way to do this is to send ID value of this record in AdditionalFields named parameter like
[Remote("IsUserExist", "Account",AdditionalFields = "Identity")]
and then you can check for uniqueness across all rows except the ones that belong to current user. and don't forget to change signature of IsUserEsists action result to receive Identity like
public ActionResutl IsUserExists(string UserName, int Identity)
{
}
Can't you just change server side validation method to something like:
public ActionResult IsUserExists(string userName)
{
if (!UserService.UserNameExists(userName) || (CurrentUser.UserName == userName))
{
return "Yeah. Is it valid.";
}
}
You have current user, because he is logged in. As long as user can only edit his data, this will work.
This is one place where buddy metadata falls short.
Edit/Add scenarios require their own view models. One size fits all scenario validation attributes only work in very trivial business CRUD apps. Add and Edit actions happen in totally different contexts and are only transiently related. This concept is very similar to the DDD bounded context idea.

Resources