store users and pass in single table or separate table - mysql

I want to create a user management system for my site ,
what is better for security and performance .
Type 1 :
table_user : user_id , user_name , user_email , user_password . user_phone ...
or
Type 2 :
table_user : user_id , user_name , user_email ...
table_pass : user_id , user_password .
table_phone: user_id , user_phone .
which one is better ?

Ideally:
Don't store passwords at all (even encrypted). Store hashes derived from passwords.
Salt the passwords to prevent rainbow attacks.
Put hashes on a separate database server, behind its own firewall and its own well-defined API1. This API should do only three things:
For given username, retrieve the corresponding password hash.
For given username, set the new hash (to support resetting the password).
Remove given username and its hash (to support user unregistration).
Do the same for salts: put them on their own server and behind their own firewall and API. This API should do only three things:
For given username, retrieve the corresponding salt.
For given username, set the new salt to a random value (to support resetting the password).
Remove given username and its salt (to support user unregistration).
Both hash and salt servers should be cut-off from the world (and from each other) and only accessible from the server that runs your Web application (i.e. PHP or ASP.NET or whatever...).
When user tries to log-on by entering username and password:
Make sure this is done through HTTPS so the entered data safely reaches your server.
Call the API that retrieves the password hash for the username.
Call the API that retrieves the salt for the username.
Salt and hash the password entered by the user and compare it to the retrieved hash.
If they match, user is granted the access.
By their nature, hashes are irreversible - other than the user, nobody, not even you, knows the exact password. In case the user forgets the password, you can't send the password to them, but you can allow them to reset the password assuming they pass some additional verification (i.e. have access to a particular e-mail address and/or answer a secret question).
BTW, log-on is a relatively rare operation, so it's unlikely to pose a performance bottleneck unless you completely disregard proper indexing.
1 E.g. implement a Web Service, then open only the port needed for that Web Service and nothing else.

I will go with option 1.
Think there are lakhs of users. So to get the user data you will have to deal with n tables instead of 1 table, which obviously add LOAD on server and finally you will have BAD PERFORMANCE.
So, I would go with option 1.
For tel. number, add field as landline_number, mobile_number, alternate_number as adding field in table won't make that much difference then adding table for the field.
And yes, as per Steve comment, store password using secure hashing mechanism.
So what option are you going to choose?

Firstly, as #Steve comments, you should store passwords using a secure hashing mechanism - storing plain text passwords is irresponsible - it means that anyone who can hack into your system knows user passwords which they may have re-used on other sites.
Secondly, there is no inherent security or performance benefit in either design - from a security point of view, you have to assume that an attacker who can get access to your database can run queries, and it would be trivially easy to retrieve data in both schemes. From a performance point of view, the cost of the joins in option 2 is unlikely to matter if you have primary/foreign key indices.
If you have requirements to re-set passwords after a certain period, and you need to store password history to prevent people re-using passwords (this is a feature Windows supports, for instance), you need to go have a "UserPassword" table, with valid_from and valid_until columns.

It depends. If you would like to keep password history and if user can have many telephone numbers then you create additional tables for passwords and phones. In other case one table is enough.

Related

How to query (hashed) Discord ID in MySQL and return user-defined name

I currently have a database of about 300 freely chosen names and corresponding Discord IDs.
I wish to make a discord bot that "checks" if a user already has a stored name on the database.
It should accept a Discord ID, and return the name that corresponds to the ID.
The problem is that the name is freely chosen and doesn't correlate with the discord tag or username.
For security reasons, the Discord IDs on the database are hashed. However, that poses one problem with salt.
Up until now, I mostly interacted with the database using PHP, where the same problem occured.
The main idea for logging pages seems to be:
SELECT password WHERE username = ?
comparing the hashed value with the entered password by hashing the latter
However, since the bot should return the username, this is troublesome. I cannot filter how many rows return since no filter can be applied, and performing every comparison would add up to minutes of waiting time.
Hashing the value and querying it also does not work, as the salt is randomised.
At the same time, somehow hashing without a salt would prevent this, since you can hash the id and literally compare it in a SQL query. But that of course causes a security issue with rainbow table attacks.
To sum up the problem, I have a list of IDs that should be hashed for security reasons, but they are not associated with any account, but simply correspond with a value. You should be able to enter an ID, and the database should return a username that corresponds to it (if it exists).
Is there a way to hash sensitive data, while also being able to compare it using a SELECT WHERE query, instead of being forced to SELECT everything and loop through every entry?
Some info that might help:
Mysql v5.7.23-23
The bot is created using discord.js#14.6.0
Performing queries with sequelize#6.25.3

Securing MySQL id numbers so they are not sequential

I am working on a little package using PHP and MySQL to handle entries for events. After completing an entry form the user will see all his details on a page called something like website.com/entrycomplete.php?entry_id=15 where the entry_id is a sequential number. Obviously it will be laughably easy for a nosey person to change the entry_id number and look at other people's entries.
Is there a simple way of camouflaging the entry_id? Obviously I'm not looking to secure the Bank of England so something simple and easy will do the job. I thought of using MD5 but that produces quite a long string so perhaps there is something better.
Security through obscurity is no security at all.
Even if the id's are random, that doesn't prevent a user from requesting a few thousand random id's until they find one that matches an entry that exists in your database.
Instead, you need to secure the access privileges of users, and disallow them from viewing data they shouldn't be allowed to view.
Then it won't matter if the id's are sequential.
If the users do have some form of authentication/login, use that to determine if they are allowed to see a particular entry id.
If not, instead of using a url parameter for the id, store it in and read it from a cookie. And be aware that this is still not secure. An additional step you could take (short of requiring user authentication) is to cryptographically sign the cookie.
A better way to implement this is to show only the records that belong to that user. Say the id is the unique identifier for each user. Now store both entry_id and id in your table (say table name is entries).
Now when the user requests for record, add another condition in the mysql query like this
select * from entries where entry_id=5 and id=30;
So if entry_id 5 does not belong to this user, it will not have any result at all.
Coming towards restricting the user to not change his own id, you can implement jwt tokens. You can give a token on login and add it to every call. You can then decrypt the token in the back end and get the user's actual id out of it.

Creating a list of users who need to update their password

I would really appreciate it if y'all could help me solve this problem:
Im trying to figure out a way to determine whether a user needs to update their password. Previously there were no requirements for the strength of one of our users passwords however now my (fake) company is changing that (just self teaching my self for fun). We would like users to include at least 1 symbol, number, and capital letter in their password. We only want a list of user's emails who don't meet those requirements. How can I filter out passwords that meet that requirement? (I honestly don't have a cue where to start)
What I thought about is using ascii numbers to determine whether a password is valid or not and it would be easy for me to do in python or c++ however when it comes to sql, i'm oh so very lost...
Here is an example of my schema:
users
-----------
id
Title
First_Name
Last_Name
Email
Roles
Password
You can't get a list of such a criteria.
The main reason for that is you should not store user's raw password. Without the raw password you cannot apply such filters.
If you really wanna teach yourself, the way to do this is make all of the users update their passwords, then you can add a regex pattern or something to make them do what you want.
This is one of my database examples, as you can see all the passwords are salted and hashed using MD5 hashing mechanism.
I think this can be done with the not like and checking for the constraints as you can see below. Number, Uppercase, and then a special char
select Email from users where
password not like '%[0-9]%'
and password not like '%[A-Z]%'
and password not like '%[!##$%a^&*()-_+=.,;:~]%'
As Roshana states, its a good idea to not store any passwords in raw text. That can be a huge security issue.

What is the best practice to create a unique url for every user profile

In my every application i want to create a unique url for users profile as http://app.com/username .
I have the name of user is : 'Vijay Kumbhar' i can create http://app.com/vijay_kumbhar, but if there is another user registers with the same name then what will be better way of creating url for that user.
one way is to add vijay_kumbhar_1, but i dont think this is the proper way of creating a unique url
Can you please suggest me the better way of doing this.
Keeping in the User experience in consideration, firstly provide the user with unique id, through which you can identify the User easily. After that you can allow the User to opt for any new User Name (screen name), but there should be a check again that the user name has to be unique again. Depends upon your requirement. Do keep us posted what way you opted at last.
You can use the same approach as stackoverflow using
stackoverflow.com/users/unique-number/user-name
Usually user names must be unique. If you're using login in the URL, then they urls will be unique. It is common thing to prevent registering two users with the same login.
EDIT:
If you'd like to keep usernames not showing (e.g. for some security reasons), you can use in URL hashes from users logins, not the logins e.g.
app.com/mylogin > app.com/123123123
You keep your registered users most likely in some kind of a database. In SQL it is natural that every row has a unique ID. You could use such an ID as a part of the url, instead of an own running number for every name combination.
You definitely need to make sure you do NOT show the actual "username" in the URL if you have a publicly accessible URL.
If you use an ID number, just remember to avoid the error that Wordpress made - creating the user IDs sequentially, starting with the default admin user as "1".
That made it easy for hackers to query with something like
example.com/profile?author=1
That would return
example.com/admimuser
And show him the actual username of the admin... and then cracker starts pounding away trying to brute force the admin username's password.
And never show the login name to anyone or in any URL other than to the user or admins!

MySQL Users table separation (Ruby on Rails and Authlogic)

I was wondering if it would be better to have things like perishable_token (used for account validation and resetting of passwords), banned (boolean to check if the user is banned), email_verified (boolean to check if user's email has been verified) in a separate table in the database, as it will rarely ever be used.
Also, I have my applications set so that a user logs in with a password and email address. The email address will only ever be displayed on the User Edit page, and the password will never be displayed anywhere. As these two things will pretty much only be used when the user logs into their account, is it necessary to have them in the main User table in the database? Or would it be better (faster?) to have them in another table?
The user table will have -many- other things that will be displayed on all pages and will need to be checked often (things such as a user's "money" "credits/points" "logged_in?" "badges" etc).
Since your user table has many other things, it seems unlikely that you would get any performance improvement by moving those five columns (which seem not to contain much data) into a separate table.