ASP.NET 4.5 / C# / SQL 2012
I already have a well defined database with a users table and a roles/permissions column. The column contains a delimited list of roles. I was hoping to use ASP.NET's built in features on the back-end so I can be lazy and use things like the and filter by role. I'd like to read my roles from the database and tell ASP these are the roles my user is in. Custom...but hopefully simple. Here is what I have so far:
//create an identity
GenericIdentity objIdentity = new GenericIdentity("Matt"); //this would actually be the username/email of the newly authenticated user
//get roles for user
string[] strRoles = { "ADW", "USR" }; //this will get read from the database on authentication
//add identity and roles to a principal
GenericPrincipal objPrincipal = new GenericPrincipal(objIdentity, strRoles);
//add to current user
HttpContext.Current.User = objPrincipal;
//add the principal to the current context of the current thread
Thread.CurrentPrincipal = objPrincipal; //not sure what this does, doesn't affect my results/tests
If I execute the code above and then run the following:
Response.Write(User.IsInRole("ADW"));
Response.Write(User.IsInRole("xxx"));
I get a True/False as expected. However, this doesn't persist to the next page. I did a fair amount of reading on custom membership/role providers, but I can't find this specific use case. Most talk about setting up a DB specifically for this task. I also saw mention of the newer Simple Membership, but couldn't get any love from that end either. I'm hoping there is a solution that involves what I'm already doing. I'd love to execute this code when the user authenticates, but be able to reference this user in other pages. I could always call to the database for every page. I'm assuming that would suck, and that's not what the built in provider does.
Thanks all.
You are approaching it from the wrong side. You don't have to create identity and principal manually, assuming you are not creating a custom authentication module.
In any other case, you only choose the persistence mechanism and the corresponding authentication module sets the identity/principal according to the persistence.
A commonly used persistence mechanism is Forms Authentication, where you issue forms cookies. The forms authentication module makes sure the identity/principal is set early in the pipeline and takes the cookie as the source of information.
If you want to replace the cookie by your custom cookie (in other words - replace forms authentication with your own) - you have to think of a way to persist the security info, to the cookie for example.
Note, however, that this is probably not necessary. The very same forms authentication can be used with any custom membership and role providers. This is because these two have different responsibilities - membersip provider is for actual authentication whereas forms authentication module is for persisting the information for consecutive requests.
Edit: to add a role for a user so that it is persisted in the user database:
Roles.AddUsersToRoles( ... );
But first, you'd have to create users in the user database:
Membership.CreateUser( ... );
Note that Roles and Membership are facades for actual role and membership providers. While default providers use the membership database, you can easily create custom providers that persist the information anywhere at the server side.
Related
I would like to implement claims based authorization in a Web Api project. I understand the idea of claims and can manually add a claim to a user and authorize a request based on it. However, I don't know how I should manage the claims, assign them to users and update them in future.
For example, say I have a Product entity and ProductCreate, ProductRead, ProductUpdate and ProductDelete claims for the CRUD operations on this entity. So I have a few questions:
I can store the claims in the DB, but what is the best way to add the "default" claims to a user on registration?
If I add new functionality to list the products which is only authorized if the user has the ProductList claim - new users would get this claim, but how would I add this claim to all existing users in the system?
Should there be a limit on the number of claims associated with a user? In a larger system with many entities, a user could end up with hundreds of claims
As I said, I know how to physically add the claims to the user etc., but it's more the bigger picture of the process of how you would manage claims and users in a real world example.
Thanks!
UPDATE
Thanks Brendan, I appreciate your help! I don't know if I'm misunderstanding something fundamental or if the answer is staring me in the face - either way, I'm not getting it.
So I have web api and would like to give granular access to the different controller methods. As the Admin, I want to be authorized on all calls so I should have all claims. Registered users should have read access to some methods and you as a moderator should have update and create access to some. My understanding is that these claims should be stored in a DB (SQL server in my case) somewhere and "assigned" to the user when they register. Using Asp.Net Identity, each user's claims would be stored in the AspNetUserClaims table, so when they login they get all their claims in the token by default. Simples!
What I am missing is the process of how you would handle the claims that should be assigned to a user when they register, what claims should a Moderator get etc. and how would you add / remove privileges. It doesn't seem right to me to have this in the code as adding a new claim in the system would require a rebuild and new deployment.
Also, if I add new functionality which requires new claims for different types of user, how would I make sure that the next time an existing user logs in they get the new claims as well as the ones they were assigned when the first registered.
I hope I am making sense, I may be mixing up some of the Role-based thinking with some of the Claims-based thinking which could be the source of my confusion. I just haven't seen any examples of how you would manage an application with many, many claims in the real world.
Thanks again!
That's exactly the same question and issue i'm running into. All I found is info on how to create a claim using the manager classes but nothing on where to manage these claims.
There can be different combination of access to give to a user and if my UI is a disconnected UI from my API, I don't think i would want the ui to manage these claims for me.
Other than mucking and creating a claims manager class with a claims table did you figure anything built in that can be used?
I am working on a asp.net website and I am having trouble implementing a custom role provider using forms authentication.
I have a SQL Server database "MyBase" with a "UserRoles" table which contains UserRoleID, EmployeeID, RoleID, and UserName fields. I want to retrieve the roles for a user from this table when users log in using a custom login page (just a couple textboxes, labels, and a button).
I have searched/read several questions, scenarios, and examples but I'm still missing something somewhere so I'm reaching out for some assistance.
What I have done so far:
In web.config:
Set authentication mode to forms
Set membership provider settings
Set role provider settings
I have created the follow custom classes and listed sub/function/properties:
RoleProvider
--GetRolesForUser
--IsUserInRole
--ApplicationName
MembershipProvider
--GetUser
--UpdateUser
--ValidateUser
MembershipUser
In my login button:
I encrypt the user's password.
Call my custom MembershipProviders' ValidateUser MemProv.ValidateUser(txt_username.Text, encrypedPW)which returns true or false correctly.
Call FormsAuthentication.SetAuthCookie(txt_username.Text, False)
Call my custom RoleProvider's GetRolesForUser function: RoleProv.GetRolesForUser(txt_Username.Text) which returns a String() or roles correctly.
When I check my User.Identity, isAuthenticated = false and Name = "".
I'm pretty sure I am missing an implementation of IIdentity and/or IPrincipal, but I don't know where/how to implement them.
So my questions are:
Do I need to go through all of this just to keep my roles in a SQL Server table I created?
Do I need to incorporate IIDentity and IPrincipal? If so, how do I or where do I do that?
Re-create the MyBase database using the ASP.Net IIS Registration tool (Aspnet_regiis.exe). This will create the database necessary to store your membership information - properly.
Here's a link that gives more information: http://msdn.microsoft.com/en-US/library/k6h9cz8h(v=vs.100).ASPX
I created two classes that implement IPrincipal and IIdentity.
In the Principal's IsInRole function I make a call to my custom RoleProvider's IsUserInRole function.
I logged using my custom login page and was redirected to the correct form. The Identity and RolePrincipal both contain the correct information.
I use .net membership but everything what i work i want to be custom.
What i want to do is:
Create custom data table [Users] with custom fields
Import current data into new table
Create custom classes and functions about everything what i need for [Users]
I`m not sure how .net membership works, but maybe it send encrypted cookie then when i use
var user = Membership.GetUser();
.Net decrypt user cookie and know which user is.
Here is a screenshot how .net create user AUTH cookie http://prntscr.com/97043
But everytime user logout-login, this value is different.
So what i want to know is:
Lets say i want to make 100% custom website, how i can make custom login?
Can you tell me all security issues about going for custom membership?
None of this is necessary. You can create your own users table without the need to alter anything related to Membership or authentication. You just make sure that your users table has a column called AspNetUserID or similar of type uniqueidentifier (a guid) . You put the ProviderUserKey from the MembershipUser in this table and lookup any user in your Users table simply by getting the ProviderUserKey from Membership.
So, for example, you might do this:
var userid = Membership.GetUser().ProviderUserKey;
// lookup your record in users based on userid above
Implementing a custom backend isn't difficult. You simply implement a custom MembershipProvider that stores and retrieves the data from your users table as you see fit. see MSDN. Also, you don't have to entirely rewrite SqlMembershipProvider, you can subclass it and add the functionality you're looking for.
If you really want to start from scratch on the backend, here are some issues to note:
Don't store passwords in plaintext anywhere; hash them.
Salt your passwords
Log & monitor password resets
Also, you don't have to entirely rewrite SqlMembershipProvider, you can subclass it and add the functionality you're looking for, and most of the issues you might run into will be covered by the default implementation. You'd probably just have slightly modify the data access calls or stored procedures to map to your table structure. You can also subclass the SqlRoleProvider to provide role-based authorization for your site with little additional effort.
As for the front-end component, MSDN also describes how forms authentication works, but personally, I wouldn't mess with your own cookie scheme. Even big custom implementations like Oauth for asp.net still use forms. Check out http://msdn.microsoft.com/en-us/library/system.web.security.sqlroleprovider.aspx
I am developing an ASP.NET website. I am planning to use Forms authentication in order to guarantee authentication/authorization, but I am facing two problems regarding the authorization:
I know how to set in the web config that the authenticated users are allowed to visit a webpage (say myPage.aspx). But I do not know how to define that UserA is able to access myPage to retrieve his information, not UserB's information.
I was thinking about generating a token when the user authenticates, so I am able to check to whom this token belongs to and verify if this information is available to him.
What do you think about this approach? Does the Form Authentication generates a token like that? (I couldn't find any mention about it in my research). If not, could I adapt the Form authentication mechanisms in order to generate or would I need to write everything on my own?
I would like to access webservices, and these should only return information if the user is logged. For this reason, I would like to use the same token explained above. What do you think about it? Is it a good approach?
I am asking this because I have no experience on designing authentication/authorization mechanisms, any help/hint would be appreciated.
Regarding question one, after forms authentication occurs in an ASP.Net web forms app, the user's identity is exposed as a FormsIdentity object in the Page.User.Identity property. This object has a Name property which contains the username that a user use to log into your site. You can use this value to restrict what a user can access. For example, let's say you have a table in your database with user information containing the following fields:
userId int
userName varchar(25)
...more fields containing user information...
You can restrict a user to only access information from the row in this table in which the userName equals the Page.User.Identity.Name property, either directly if you are using direct ADO.Net or via your query to your ORM-mapped (i.e. nHibernate or EF) domain object.
Regarding question two, the FormsIdentity object exposed by Page.User.Identity has a boolean "IsAuthenticated" property. You can use this to restrict access to your web service as follows:
if(Page.User.Identity.IsAuthenticated)
{
//Call your web service in a secure manner
}
Our site has got two ASP.NET membership providers. The built in one, and a custom one (SqlMembershipProvider.
I am able to log into both no problems, but I don't necessary require the ability to have both logged in at the same time.
The issue I have is as follows:
User "person_a#site.com" logs into the built in provider. They then navigate to the section of the site where we require the custom provider.
On this page, I can check if they are authenticated, and get their username. I can then get a MembershipUser object form the custom providers GetUser method. (HttpContext.Current.User.Identity.Name)
It is possible (and very likely) that the username "person_a#site.com" could also exist in the users for the custom provider.
But, I don't want them to be logged in here, as they haven't authenticated against the custom provider.
So, is it possible to check which proivider HttpContext.Current.User was generated from.
Hope this all makes sense!!
Yes, if you notice on the RolePrincipal there is a property called ProviderName.
Typically when people roll their own providers they omit usage of this field.
In your case, simply modify your custom provider to identify itself, if it does not already, and check that property of the user.