ASP.NET Membership - Two providers on site - asp.net

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.

Related

ASP.NET Identity - Maintaining information about anonymous users

I'm just looking into ASP.NET Identity, which seems that it is the most preferable solution for user authentication in ASP.NET apps these days (replacing all the ASP.NET Membership stuff from the past).
I am looking for a solution that would allow to maintain information about anonymous users. Even if the user is not authenticated, we can collect and store most of the profile data that we could store if the user was authenticated.
Even if the user is anonymous, it makes sense to store data like:
shopping cart
comments he's written on the site (so that he can edit them as their creator)
various site preferences (his preferred language, and many other settings)
Then when the user registers, we can offer to copy some of this data into his new user profile (or copy it automatically) depending on what data it is.
Is it possible to achieve this scenario with ASP.NET Identity? It seems that when a user is anonymous in ASP.NET Identity, he cannot have any user profile data.
In order to use the same tables to store all this information as for authenticated users, we might need to create a new user in the system for every new visitor that comes to the site and does some action that requires storing of some user data.
After that, we'd need to pass some cookie identifier to the user, so that we can always connect the data to the user, which can be seen as some form of authentication (although invisible to the actual user). That way, the guest user could actually represent an authenticated user of the system (maybe he'd just have a special role?), even though to his knowledge he's anonymous.
What do you think about this approach? Are there any ways where ASP.NET Identity can help with this?
I found these two related Stack Overflow questions, but I haven't found my answer in them:
Does ASP.NET Identity 2 support anonymous users?
ASP.NET Identity - Anonymous profiles
Edit:
I discovered that there's a mechanism called Anonymous Identification in ASP.NET that seems to solve part of the issue.
https://msdn.microsoft.com/en-us/library/91ka2e6a(v=vs.85).aspx
Maybe it can be somehow integrated with ASP.NET Identity?
Edit2: As noted in the comments, the documentation for Anonymous Identification seems to be outdated and it's quite probable that Microsoft will not be focusing on this much in the future. Solutions that work with ASP.NET Identity or other OWIN-based solutions are preferred.
Asp.Net Identity has no such thing, and it will not be secure identify the anonymous user even through hip IP or a Cookie in his browser, you can ask the user to register with very minimum info or through FB or Twitter to make the registration process as short as possible, and later he can complete his profile, this way you will make sure the data is linked to an actual profile.
ASP.NET profile properties allow your application to track and permanently store user-specific information. For example, users can specify a postal code or a favorite color scheme, and your application can store that information and retrieve it from anywhere in the application. ASP.NET automatically matches the current user — whether the user is anonymous or logged on — with the personal information that is stored for their user account.
Configuring Profile Properties
You will begin by configuring your application to enable profile properties. You will then define the first property that you want to track for each user. This property is named PostalCode and will be tracked for both anonymous and logged-on users.
Source: https://msdn.microsoft.com/en-us/library/taab950e.aspx

Assistance with Forms Authentication and Custom Roles

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.

Is it possible to validate a querystring ID, for ownership, in FluentSecurity?

Just discovered FluentSecurity. Looks very interesting.
My Web Application is written in MVC3, C# and Razor.
I am worried about the URLs being tampered with. So on top of checking for authenticated users, correct roles, I also need to ensure that the user is not trying to tamper with the URL to view data that he/she has no access to.
ie He/She owns #10, so
Order/10
is fine,but not:
Order/100
With the standard [Authorize] one could write a custom authorisation class that inherits from the Authorize class which thens check the ID which is okish... and works.So if ID is owned by user then return true. How would this be implemented in the FluentSecurity environment?
Many thanks.
I can't tell you how to implement it but I can point you in the right direction.
What you need is a custom policy. You can then set up a security context modifyer to provide you with the querystring/route data you need.
Custom policies are covered here:
https://github.com/kristofferahl/FluentSecurity/wiki/Custom-policies
Security contexts are covered here:
https://github.com/kristofferahl/FluentSecurity/wiki/SecurityContext

Another ASP.NET custom membership/role provider

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.

Roles for white-label service access

Okay,
I know I'm doing something wrong - but can't figure out a better way.
I am developing a website which is going to allow users to setup their own mini-websites.
Something like Ning.
Also, I have only 1 basic login and access to each mini website is provided (right now) via roles.
So the way I am doing this right now is:
Everytime a new mini website is created - say blah, I create 2 roles in my application.
blah_users and blah_admin
The user creating the mini website is given the role - blah_admin and every other user wanting to join this mini website (or network) is given the role - blah_user.
Anyone can view data from any website. However to add data, one must be a member of that mini site (must have the blah_user role assigned)
The problem that I am facing is that by doing a role based system, I'm having to do loads of stuff manually. Asp.Net 2 controls which work on the User.IsAunthenticated property are basically useless to me now because along with the IsAuthenticated property, I must also check if the user has the proper role.
I'm guessing there is a better way to architect the system but I am not sure how.
Any ideas?
This website is being developed in ASP.Net 2 on IIS 6.
Thanks a tonne!
I afraid standard roles-related stuff of ASP.NET is not what you need. You can try to change authentication module so it will:
Log you in with cookie.
Determine what roles does your visitor have. Perhaps you will use some special table that corresponds user and site.
Make custom principal with user roles enumerated and assign Identity and Principal to the current request.
I also don't think that making special roles for each site is good idea. When you would have hundred sites, you would also have two hundred roles. Pretty unmanageable, I afraid.
When we were solving similar task, we were just not using standard controls. We had single set of roles used on all sites. Membership of concrete user is determined according to current site and his relations to this site.
Addition: Another possibility to investigate is Application that exists in ASP.NET authentication system. Maybe it's possible to isolate each subsite into separate application?
Update: Method that works for our application.
Do not make a lot of cloned roles. Use only two: users and admin. If your sites are public then "users" role could be just global - user on one site doesn't differ from user on another site. If "users" and "everyone" are different roles, then of course "users" should also be bound to a site.
Use standard ASP.NET Membership users, but do not use standard role mechanism.
Make a mechanism for storing relation between site and user. It could be simple table that holds site id, user is and role.
What you have to override is IsInRole method. (Methods to be exact, i'll cover it later). This method is in IPrinciple interface, so you have to make your own principal object. It's quite simple.
Method IsInRole of this type should look take current site (from HttpRequest) look into the site-user table and get roles
Then you have to associate your principal with a request. Do it in PostAuthenticateRequest event.
There is also RoleProvider. Honestly I'm not sure when is it used, but it also have IsInRole method. We can override it in the same way. But other methods of this provider are harder. For example AddUsersToRoles. It accepts array of user names and roles, but to what context (site) should it be added? To current? Not sure, because I don't know when this method is called. So it requires some experiments. I see (Reflector helps) that RopePrincipal by itself uses RoleProvider to fetch list of roles, so maybe it's implement only RoleProvider, using standard principal. For our application this is not a case, so I can't say what problems could be hidden here.

Resources