Preventing Duplicate Login Records - authentication

We have a a large set of users who use our web application fairly infrequently (i.e. they don't visit every day or every week). As a result, they often:
forget the password they used
forget which e-mail they used on signup OR
may have actually had their e-mail address change since the last time they signed in
Often, when facing the login signup form, they'll simply create a new login record with a new/different e-mail address.
This is a problem because it's important they stay linked to their previous records, and it can cause problems if there are duplicate records for a single person in the database (note that these are not duplicate records in a database sense; from a data standpoint they're not duplicates at all, but they are duplicates in the sense that they point to a single real human being).
Right now I have a check in place that sees if there is already someone with the last name and first initial, and asks them to confirm if they are or aren't one of these other people. Obviously this is very clunky and falls flat when dealing with very common names. Also, it's confusing to display a page to a user that says, "I think you're actually this other person. Please let me know if you are this person or not."
I'm looking to hear from other developers who have had to deal with this problem, and what they came up with. I'm also interested in solutions that gracefully merge two logins.

You could easily prevent the user from signing up if they entered a duplicate username or e-mail address from what already exists in your database. You could present the user with a page that asks them to recover their password for the existing account. If the user is going to sign up with a different username and e-mail, I'd argue at that point it may be out of your control to stop the user from creating another account (unless you are gathering some sort of unique identifier from the user (e.g. social security number, etc). I wouldn't do any filtering based on name as it's never going to work 100% of the time.
Otherwise maybe a simple UI change could help alleviate the problem as well (e.g. "Returning user? Login"). Make sure the user sees that they can login with their existing account, and on that screen make sure the user can easily see that they can recover their account information if they can't remember it.

Related

Auth0 database and social connections, unique email addresses

Maybe I am missing something here, or this is a flaw in Auth0? I'll give an example of my issue:
Let's say I have my Default App (client), hooked up to that I have Username-Password-Authentication (database connection) and google-oauth2 (social connection).
A user comes to my site, signs up via google-oauth2 (social connection) using joe#gmail.com. Once complete, he gets added to my users in Auth0, all great.
A few months later, Joe comes back to my site, and being a busy guy, he forgets he signed up to my site before. This time, he decides to sign up using my custom Email and Password form, that will add the user to the Username-Password-Authentication (database connection). so he signs up there using joe#gmail.com again, and everything goes well, he is now listed in my user's section in my Auth0 dashboard.
This is the problem, I now have two joe#gmail.com accounts, one with google-outh2 and one with Username-Password-Authentication. I really can't have this, I need a unique email address, regardless of the ID Auth0 supplies.
Does anyone know how I can make email address in my user section 100% unique? I'd think a rule would do this, but it appears rules only apply AFTER a user has been registered, so I can't run a rule before adding?
the only way I can see doing this right now is make my own checks and delete via the management API, but that is a really long and messy way to do it I feel.
Any help will be appreciated here!
Thanks!
Auth0's default behavior is to create a new account in the database for every unique entry. Since the user created using Google has a unique id (based on google-oauth2), and the user created using the sign-up form has a unique id - they will technically be considered two separate accounts. In order to resolve this disparity, you can establish a means with which the account data can be merged. In the documentation linked provided above, there are examples of three possible ways of doing this:
Automatic Linking - which involves creating a specific rule to merge users based on matching emails
User-Initiated Linking - which involves providing a UI for users to opt into merging users with matching emails
Suggested Account Linking - which involves setting up a rule that is linked into the UI
One important thing to consider is that the data returned from different social identity providers may not be normalized the way that data is normalized onto the Username-Password-Database. For example, while auth0's default for emails is to lowercase the information, google-oauth2 may return emails as Uppercased - creating the potential for non-matching emails when checks are made using strict equality
The option you are looking for is called account linking.
You can find more info at https://auth0.com/docs/link-accounts

What is a good practice when setting up a users table? Looking at some newbie tutorials, but not sure how to "really" do it right

I'm tinkering around with building a rest API that connects to a database. I'm following tutorials, but the table set ups are all really basic and one of my issues has been that in the "real world" the way its done is a lot more complex and different :(
However, I'm wondering for my actual application (really small) how can I properly set up the User table?
For example, I have set the primary key to userid because that should never be changing. Is it fine to use long for the userid?
Also, is it fine to lump a bunch of things together that are related to the user.. in the User table? I know its a stupid question.. For example, I want to know if the user has signed up for the service, so isMember. Or, is the user signed up for fast service, so hasFastService. Or, should these things be put into a UserAttributes table by the userid?
Finally, I looked up UUIDs and I'm wondering where those fit in, in which scenarios, etc.
Thanks
I'll try to answer this based on my own experience of creating users table in a project recently. The things you have to take care are basically these:
Authentication: Determine your login process and things like credential fields, user types (admin/guest/normal), whether OAuth is required or not, etc. before creating the users table. For example, whether you need a username/password to authenticate or email/password or either "username or email" with a password. The modern practice is to do away with a "username" since its redundant - an email is unique and acts as a username for all intents.
OAuth: If you are giving facebook/google/twitter logins, make provisions for that in your users table. How will you determine whether the user was a normal signup or a social login signup? A field such as "login_method" or something is useful in this regard. A second field called "user_type" maybe created for identifying the type of user account: admin/guest/employee/etc.
Profile fields: Its upto you to determine profile variables. In my last project, I used a few fields like FirstName, LastName, Theme, Timezone, etc. for the profile, but your mileage may vary.
For user-ids, it is usually best to have an auto generated integer primary key which is available in all modern databases.
Needless to say, never store the actual password in the password field. Just has your password and store the has instead. When the user logs in, you can hash the user-input and compare with the user table value.
Finally, DON'T confuse the user table by including related data like clients, employees, etc. All clients are users, but all users are not clients! Keep your design flexible, so as to include all kinds of users like admins, employees, etc.

Best way to deal with creation of user account after successful purchase?

I'm wondering what might be the best way to create a user account once a successful payment is made, this is my app's flow at the moment:
User selects a package
User checksout via paypal express
On return I have the user's details including email address (and so a confirm order button will then finish the process)
Should I include a password and password-confirm field and use 'accepts_nested_attributes_for :user' in my Order model, or, would it be better to let them simply confirm the order (to keep things simple) and just generate a random password and then email that to them with their order confirmation/invoice via observers (and perhaps force a password change on first visit).
What do you think is better?
(I'm trying to keep in mind things like security/risk of emails going into spam folder etc)
Any thoughts on the matter? I guess both are ok - but posting just in case I'm missing something.
My personal opinion is that you offer both. Once you implement it you will see which way your users gravitate to and then you can select one based on their habits.
You want to make it the most enjoyable experience for your users so really you have to give them what they want. Depending upon your audience and product you could argue either way.
It might be as simple as having a check box that says "create user account automatically and email the details"
In the end it's the customer you have to satisfy so let them choose initially. The'll tell you what they want.
Good luck.

What are the best practices to prevent staff taking over user accounts by editing the email address?

We are building a CRM type app although this would apply to any application where there are "members" and "staff" e.g. a shopping site, dating site, facebook etc.
In our app, users can change their password the usual way, by resetting it with email confirmation. Users can also have more than one email address associated with their account.
What we are trying to work out is how to prevent staff using the system taking over the accounts. We want staff to be able to edit the email address (because someone may phone in and request a change); the issue then is they can simply change the email to one they control - and request a password re-set as a user.
Are there any recommended best practices for this?
You could require the user to also authenticate the action by other means, such as when the email address is changed the user is sent a confirmation code via text message that they must input somewhere.
Another means would be to only allow access to the account if certain information is inputted correctly. This could be address information or DOB. It is unlikely that this information could be guessed from something like a name or account number.
1) Add one of those silly security questions like "What is your favorite color?" and store the answer, encrypted, in the database. Staff could edit the email to their heart's content, but if they didn't know the answer to the secret question the system wouldn't let them change the password. If you have concerns about staff trustworthiness, then you need to introduce something outside their control that serves as a final gateway before you can change the user account.
I imagine a simple implementation would simply check to see if the user reset their password. If so, on login, it challenges them with the security question to "authenticate" them before allowing them to proceed.
2) Logging, monitoring, and auditing. Record which staff accounts accessed the email address change form, what address(es) they changed, what they changed them too, and when they changed them. Also record the connection information of the people accessing the accounts. If your logs show one IP address accessing 4-5 completely disparate accounts, you might need to look into that. (Yes, I know you can use proxies etc. to mask this. Not perfect but it'd weed out the chaff pretty fast).
3) Hire trustworthy people! #2 should really only need to be used as a "check" against abuse instead of the end all be all to stop it.

Storing a Windows SID in a Database for Lookup

I have an ASP.NET MVC application where I need to allow to customers configure MembershipProviders based on their environment, but still be able to map that MembershipUser to a concrete User model in our database.
Membership.GetUser() will give me access to the logged-in user's Membership.ProviderUserKey. I can use this to relate to a User record. Our custom SQL provider will just return the User.Id, but AD is a different story. In that case, ProviderUserKey is an IdentityReference.
These lookups will happen very frequently, as you can imagine (although caching can assist in reducing the lookups at the database level).
I can't decide which route is better to go: Storing the SID as a varbinary or varchar column. This column would not be a primary key and would not have a clustered index. Knowing that I can index strings pretty well, and reading a SID in string format is certainly nicer than binary. Anyone willing to share how they solved such a situation?
Update
I don't know how I missed this SO question when I was searching before I posted, but it seems pretty clear that ActiveDirectoryMembershipProvider and ActiveDirectoryMembershipUser are not quite cut out for the task at hand, as they exist today.
An answer in that SO question linked the following article, where the following was stated:
The relative identifier portion of a
SID is unique relative to the domain,
so if the domain changes, the relative
identifier also changes.
Thus when a User object moves from one
domain to another, a new SID must be
generated for the user account and
stored in the Object-SID property.
However, each group and user has an Object-GUID, which will never change, even if the account is moved. Therefore, it would behoove me to use Object-GUID in my User class, and not Object-SID. Otherwise, someone's User record will be abandoned if they are moved and therefore breaking the relationship between their principal and the data they created.
Unfortunately, ActiveDirectoryMembershipUser doesn't let me get at Object-GUID. So, I'll either have to translate the SID to a GUID after ActiveDirectoryMembershipUser does its work, or create my own MembershipProvider that does everything I need on the spot. Unfortunately, this means I might have to duplicate effort already done for me by ActiveDirectoryMembershipProvider.
Microsoft stores SIDs as varbinary(85) in sys.server_principals
This is also a unique column, so it must have an index...
username is the LAST thing you want to index on.
SIDs only change in an AD when you change a user from one domain to another. RIDs are split into 2 groups - inbuilt (< 1000) and user RIDs. Pre-defined users such as Administrator, Guest etc always have the same RID.
If you want to handle movement of users etc, then GUID is the way to go.
username can be changed at any time in Users and Groups management.
this is different to the object name, which is invariant, but I don't believe is mandated unique across a forest. You can have any number of John Smith users.
I'd look into the ADSI objects. These are COM objects which should be accessible from ASP. MSDN explains pretty well. an ADSearch object can be used to return user attributes (e.g. including DN) from a GUID.
Sounds like you're making this a lot more difficult than it needs to be. What do you need a SID or GUID for? You already have a unique, perfectly readable identifier for the users account maintained in ActiveDirectory.
It's called "the username". Hopefully it's the same username as stored in your apps "user" table.
Your app just needs to know if that username successfully authenticated with ActiveDirectory. So if they successfully log in - you just store the fact that they are authenticated in your Session variables.
If they are configured to use the db user login, if successful set the same Session variable indicating that they successfully logged in.
No fancy GUIDs or SIDs ... simple.