Extending MembershipProvider - c#

Scenario:
Building an application for companies to enter information into.
I need to extend the built-in membership provider in asp.net. My unique situation is that I already have demographic information for each company, but NOT userid's and passwords for a web app. I want to prepopulate the DB with the demographic information, send each company a unique pin number, and ask them to register with my application. I want them to create a userid, email address and password, after they've "validated" who they are by entering the pin number that they received in the mail. Yes, we'd be sending them, via snail mail, a unique pin number.
Problem:
Not quite sure where to start. The problem centers around the fact that we already have demographic information for these companies and right now, it's not possible to use this new web application to update the demographic info, so we really don't want them to change it. We also don't want just anybody being able to register an account and entering demographic information.
Questions:
Am I thinking about this the wrong way?
Is extending the membership provider the right way to go?
What is the best way to handle this situation?

Extending or implementing a membership provider is quite straightforward actually, and sounds like a good approach for your problem.
The only functionality of membership providers that most applications even use is the ValidateUser method. In your case, you would simply override this method to fetch the customer name and pin from the database and match it with the user's input. If it matches, return true, otherwise, false.
Create a new class, inherit MembershipProvider. Right click the class name and implement the abstract methods, and you're off to the races. There are lots of walkthroughs and examples if you google for them as well.

Related

Restrict users accessing other users' data

I'm having a problem of designing a common functionality of hiding information created by a user from other users. As an example,to edit Products created by USER1, normally we use one of following.
/Product/Edit/Id/1
/Product/Edit?Id=1
My concern is, if USER2 got the Id, 1, he also able to access Product with Id=1, which was created by USER1. How to restrict USER2 accessing USER1'S data? This may needs to apply for every module in the project. Is there a common way to achieve this? Thanks
If you are keeping state of what user is accessing the data. You can add a "WHERE CreatedBy = {YOURLOGGEDINUSER}" to this query and throughout your application. Then even if he gets the ID correct no data would be returned.
Assuming that you have enabled some sort of ASP.Net Authentication (The user has proved who they are) then you now need to think about the Authorization (what the user is allowed to do).
It doesn't help that these two terms are often combined or used interchangeably. In MVC a custom AuthorizeAttribute is often used to do both.
For managing records, the current logged on user is accessed via the IPrincipal from HttpContext.Current.User.
The user id is usually set at HttpContext.User.Current.Identity.Name although you may need to do a null check if not every route is authenticated.

MVC5 WebSecurity, use secondary database temporarily

I have a solution with two MVC projects. The first is a management system, the second is a portal for contractors. I want to manage the contractor login of the portal via the main application.
The membership database for both projects is identical in schema (the default). My thought was to hijack the main system's Register action, swap out the connection string, register the contractor user in its' own database, then swap the connection string back to the main one.
I'm guessing this won't work, namely based on the fact that WebSecurity.InitializeDatabaseConnection() can only be called once.
Thus my question: if I want to call the WebSecurity.CreateUserAndAccount() method but point it to a different database than what it was originally initialized for, how would I do so?
I looked at the built-in InitializeSimpleMembership filter for clues, but am not seeing the path I'm looking for.
Is this even a feasible approach?
Alternatively, if I can get the password hashed per the same way it's done by default, it looks like I can enter the required data to the db manually.
It appears I can manually work this out. According to the msdn docs for WebSecurity.CreateUserAndAccount():
This method creates a new entry in the user profile table and then a corresponding entry in the membership table. The ID of the membership entry is based on the ID of the user profile entry. (The IDs of the entries in the two tables match.)
(https://msdn.microsoft.com/en-us/library/webmatrix.webdata.websecurity.createuserandaccount(v=vs.111).aspx)
Inspecting the database schema shows that I only need two tables for this, and the fields are straigtforward.
To hash the password according to the same way the SimpleMembershipProvider does, I can use the System.Web.Helpers.Crypo.HashPassword() method.
This simplifies the basic account creation considerably as I don't have to piggyback off the AccountController and can just write these directly to the db and call it good (for my purposes, anyway, not requiring verification tokens and having seperately handled email notifications). On the portal side, the built-in SimpleMembershipProvider should be able to handle everything as usual.

Is it possible to implement user profiles without using SimpleMembership?

I need some advice. I'm currently using MVC 4 & SimpleMemberhip with LDAP to authenticate users. The issue is, I don't want to store their usernames and passwords in the
webpages_Membership table due to security concerns. The second issue is I want to provide user-editable profiles.
Here's what works so far:
User logs for the first time and a new entry is created in webpages_Membership
An individualized link to edit the user profile is displayed on the homepage
Username is added to the UserProfiles table when profile is accessed for the first time
Certain user details are fetched from LDAP server and written to profile
Users can then customize their profiles
I'm currently using SimpleMembership with an override to the ValidateUser method. Everything works as it should but I don't need to store the LDAP usernames & passwords. Can this be done?
p.s. I know there is a better way to create new users & profiles besides on first time log in but I'm still working on it.
If you don't want to store the passwords (which SimpleMembership would do by default), you are better off deriving your own custom provider from ExtendedMembershipProvider (or maybe from SimpleMembership, but that would get complex) and write the LDAP implementation, or using one of the ones on NuGet. There's no built-in LDAP support in SimpleMembership, so any approach you do would be a nasty hack which will probably bite you later on.
As for the UserProfile, it doesn't sound like your requirement is that different to the usual UserProfile use case - create custom properties on the UserProfile model, update the database accordingly, and build a UI to allow the user to edit whichever of those properties they should be able to directly edit.
(edit)
Footnote. In my answer to "How do I use my own database with SimpleMembership and WebSecurity? What is MVC4 security all about?" I examine the history of membership, how ExtendedMembershipProvider fits into this, and how the new classes such as WebSecurity work on the basis of a provider being a concrete implementation of ExtendedMembershipProvider (which SimpleMembershipProvider is, for example). For anyone looking to derive their own provider to use with WebSecurity, that answer is worth reading.
I've managed to bypass storing user details in the Membership provider by creating the required tables with Code First. I'm now able to create new users and store them in the UserProfile table.

ASP .NET Membership customizing

After I was learning about ASP .NET Membership built-in framework I have decided that this stuff is almost suitable for me. But there are couple features and edits I would like to have:
Two step registration: after user have typed all account information, verification letter should be send to typed email. Before email address is verified it impossible to log in (some message should appear, telling user that email verification is needed before it's allowed to use account).
Membership DB Scheme:
There is no need to store user question for restoring password.
Illegal attempts to login is uneccessary.
Default aspnet_ prefix is likely to be changed.
... and so on
For the first item I know that I could use own class derived from SqlMembershipProvider. Am I right about this? Could you point me at some good post where I could get learned.
For the second improvement it's seems like a trouble. In this book I have read that isn't so easy:
• The built-in SQL storage providers need direct access to your database, which
feels a bit dirty if you have a strong concept of a domain model or use a particular
ORM technology elsewhere.
• The built-in SQL storage providers demand a specific data schema
that isn’t easy to share with the rest of your application’s data
schema.
The biggest problem I've encountered with subclassing SqlMembershipProvider is it doesn't give you the connection string to work with. You have to hack the class to pieces to get anything useful for the way most modern login systems work.
I'm not sure about the database tables names - I don't think that's controlled by the SqlMembershipProvider but is actually inside an ASP.NET installer class.
My advice would be to create your own from scratch, and use the built in FormsAuthentication helpers. It's really not a big task compared to hours of annoyance having to conform to the providers. I did this with Roadkill after going down the Membership Provider route, and discovering it a cul-de-sac particularly for Active Directory support.
You can completely control your membership DB schema by Implementing Custom Membership User (of course you also need to implement Membership Provider for the User).
Customize user creation steps by configuring CreateUserWizard control. You will change its' template and handle events, I don't think you need to override it.

ASP.NET: Custom MembershipProvider with a custom user table

I've recently started tinkering with ASP.NET MVC, but this question should apply to classic ASP.NET as well. For what it's worth, I don't know very much about forms authentication and membership providers either.
I'm trying to write my own MembershipProvider which will be connected to my own custom user table in my database. My user table contains all of the basic user information such as usernames, passwords, password salts, e-mail addresses and so on, but also information such as first name, last name and country of residence.
As far as I understand, the standard way of doing this in ASP.NET is to create a user table
without the extra information and then a "profile" table with the extra information. However, this doesn't sound very good to me, because whenever I need to access that extra information I would have to make one extra database query to get it.
I read in the book "Pro ASP.NET 3.5 in C# 2008" that having a separate table for the profiles is not a very good idea if you need to access the profile table a lot and have many different pages in your website.
Now for the problem at hand... As I said, I'm writing my own custom MembershipProvider subclass and it's going pretty well so far, but now I've come to realize that the CreateUser doesn't allow me to create users in the way I'd like. The method only takes a fixed number of arguments and first name, last name and country of residence are not part of them.
So how would I create an entry for the new user in my custom table without this information at hand in CreateUser of my MembershipProvider?
I think you should go on with your approach and add a new function in your implementation, I mean, overload the CreateUser method and have a CustomMembershipUser (that extends the MembershipUser) as a parameter.
In that way, before using the provider, cast it to your CustomMembershipProvider and use the overloaded method.
I agree with your analysis that you should keep both membership and profile information in the same table. Since you are correct that you are restricted by the number of parameters that CreateUser takes, you will need to design your field so that non-membership profile attributes are nullable. This does not mean that you will have required fields that are null in the database, however. Instead, you can you the below snippet:
string username = .../ retrieve username here
Membership.CreateUser(username , password, email);
ProfileBase newProfile = Profile.Create(username); //since the user has just been created, all properties will be blank
//set all entered properties
newProfile.SetPropertyValue("MyProp1", myProp1Value);
...
newProfile.SetPropertyValue("MyPropN", myPropNValue);
newProfile.Save();
In this way, you leverage ASP.NET's membership providers to create the user and save profile data, but to your end user it is a single atomic operation.

Categories