Is it ok to replace clients username id with their email? - php

I want to replace username id with their email. Is it ok to do that?
For example in MySQL table:
client_id
som665
som881
som876
som887
I want to replace them with emails for future clients e.g.:
client_id
som665
som881
som876
som887
xyz123#gmail.com
xyy333#gmail.com
xcv5557#yahoo.com
Question-
Does replacing client_id like som881 with email make my software (or query) slow? When I use below query on emails instead of small id's like som881?
$sel_service = "select * from all_services where client_id='$client_id' order by sub_cat_name"
Right now my clients login with client id like som881 which is difficult for them to remember compared to an email address. I'm also unable to provide "forgot your password?" functionality.

The longer the string the more time it will take to query the users because it will match more number of chars,
so if you want to make it with the email ( and yes it easier for the user ).
you have to make this field as unique index .
in this way mysql will index the emails and it will find the user record without scaning the entire table.
but the drawback of it that it will take more space for the index. but it will be very fast
and if the user will have more than record( have more than service), then you have to make it just index not unique

Overall your question is very broad without details of the application you are working on.
I'd say that in general, yes, it'd be good idea to allow users to login using the email address. If are mainly concerned about the slowdown this shouldn't be an issue as this should only impact login which doesn't happen all that often.
From design perspective you probably should have two identifiers for the user:
User visible token. This can be username chosen by the user (user123) or email address (user123#example.com). This token is only used when user logs in to the application. You may even go as far as having two different columns to store the username and email address. In this case your login part needs to match the username against both database columns.
Internal identifier used in application. id INT PRIMARY KEY AUTO_INCREMENT column might do well, depending on your intended scale. This is what your application should use internally. You don't even need to show this to the user.
This would allow users to change their email address without having to recreate their account.
EDIT: based on your comment, you use client_id as both index value to reference data between the tables in the database and as a username user logs in with. My suggestion is to normalize the data as listed above.
If you don't normalize the data, you may end up with over-sized index columns in several tables. To store email address you need to use string (CHAR, VARCHAR) column with significant length. With normalized data you just need INT/BIGINT in each table. In this scenario allowing users to use email address may slow down as it may require client_id column to be resized.

well this is a very good use of emails because mail servers of companies doesnt allow clients to have same username so you dont even need to set a primary key constraint on this id field .
you know nowadays databases finds the best algorithm to search between records by their Artificial Intelligence so the only thing you should worry about is :
is it worth to provide your clients comfortability at the expense of complexity !?
if yes in my opinion there wont be any problem if the server responds a little slower
i suggest you to use at least one security server service layer using precreated classes between client and database server that accepts clients connections and created one way virtual connections to database server for searching login information instead of explicit SQL command to provide a higher level of security and rejecting SQLInjection

Related

Random ID Number when user created

I want to use a users unique id to save a cookie - so that I know which user is logged in, and then I can change their content to suit.
I am currently just using the usual auto id when a new record is created, but I have heard that for creating user accounts (specifically when you're going to use that ID to change content) that you shouldn't have them 1 after another; e.g. not 378, 379,380 and so on but more like this 138462193, 109346286, 982638192 so it's kind of like a random unique identifier.
How would i achieve this?
Is this a best practice?
You protect your data against attacks by using ACL, to limit which user has access to to what (and with what data). Foreign key relations to establish ownership between user and data, session ID regeneration at login, CRSF tokens to prevent attacks via other sites, and so forth.
Not to mention logging, to be able to find out what went wrong when things do go wrong.
Only in very special cases do you ever need to worry about the ID of users being sequential. Most of the time this ID will be available to other users, via the web site itself, anyway. As a part of normal operations.
Thus adding a random element to the user ID won't bring anything but a false sense of security. Even if you keep the internal ID different from the "external" user-facing ID, as long as you're using the external ID to identify and change content it's basically the same as the internal ID. Only valid reason for using a dual ID system, in most cases, is for human readability. If you're uncertain about whether your use case is one of the exceptions, it's not.
PS: I see in your comment that you say that the passwords are encrypted. Hopefully you mean "salted and hashed", more specifically by using password_hash () and it's associated functions.

How to check if an email address exists in a table, which contains encrypted email addresses

I have a table which contains encrypted email addresses of users. When a new user signs up, I want to check if the email address entered already exists in the table. I use the openssl_encrypt function in php to encrypt every email address. Since the function returns a different encrypted value even if the same string is passed as an argument, I cannot check if the email address already exists in the table . What is a viable, but secure way to encrypt and check if the email address exists in the table ?
Answered here: Indexing Encrypted Information in our paper on secure data encryption in PHP:
An uncommon problem that many companies encounter is, "How can we encrypt information in a database and still index it for fast retrieval?" For example, if you need to be able to retrieve patient records by social security number in a health care application.
If you have millions of records, decrypting each record one-by-one to perform a simple record lookup would be expensive for both the application and the database server. And storing such a sensitive record is a no-go (unless you enjoy apologizing to your customers and offering them one year of free identity theft protection).
Instead, create a blind index of this information for indexing purposes. First, encrypt the information and store it in one field (say: ssn). Then, store a separate HMAC of the plaintext with a separate key in another field (e.g. ssn_lookup) and create the database index on the second field. (This idea was proposed in an MSDN blog post by Raul Garcia. If you are developing a .NET / SQL Server solution to this problem, Raul's blog post is probably more relevant.)
The key for HMAC indexing purposes should be only available to the application server that needs to query the database, which should be on separate hardware, and never checked into version control.
Note that this only allows exact searches, not partial searches.
public function getAccountByEmail($email)
{
$search = $this->pdo->prepare("SELECT * FROM table WHERE email_lookup = ?")
->execute([
hash_hmac('sha256', $email, $this->searchKeys['email'])
])
->fetchAll(\PDO::FETCH_ASSOC);
return $search;
}

Minimum information to authenticate a user

I have a table who's PK is INT type (roughly 4 billion possible unsigned values, however, I will have at most 2 million). The table also has a CHAR(32) column which contains a random value (created using bin2hex(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM))), as well as a FK column indicated the userID.
I will send out some emails which will contain links in them, and the links will contain the above table's PK and/or random value, as well as potentially the userID. The links will also contain an answer (yes, no, etc). For instance, a link might look like:
Yes
I have a PHP page which will accept a GET request (initiated from the above mentioned emails of course) and update the appropriate record in the database with the provided answer if authenticated.
Is solely confirming the 16 byte random value exists in the database enough to authenticate that it came from the user who received the email? If not, why not and what would you recommend?
I would also use the user id as it is faster.
Your url will become: ckr.php?userid=1&rsp=eae8a14011e82cbf385f69b431a17e49&ans=yes
Then, when you check in database, you only check for userid. If the user exists, then check for the rsp code. If everthing ok, do your job.
Keep in mind, everything send over e-mail is unencrypted an thus not suitable for authenticating a user.
Some things you could do to make it a bit more secure:
Make the key only available for a short timespan. Maybe a 24h window?
Ask for the users password when receiving the get request.
Invalidate the key when an answer is received.

Database/Server Design (Cookies and Indexes) - Ints or Text?

This is a design question relating to a website I'm building.
I have a 'Player' table that will store names, passwords, last IP, dates of birth, links to avatars, locations, etc.
When the player logs in, the database will be searched for the username they entered, and their password will be checked out as well (yes, of course the passwords are hashed). Then, they will be given some cookie that will keep them logged in.
Every time they visit a new page, the correct player will be looked up in the database using the information in the cookie. If their current IP matches the last IP they logged in with (probably 10 seconds ago), the page is outputted with their name on it and whatnot.
Here's my question: should I have the primary key for the Player table be the player's name (a text field that I know will be unique), or should I create some arbitrary auto-incremented index for that?
Keep in mind that this also has an effect on the information stored in the cookie - whether to store an int or the user's name in text. As well, I want to do some sort of hashing on that value (just for a little added security), so that the cookie doesn't just contain the int or the username.
So, in terms of both efficiency and design, which is the better choice?
EDIT Using VARCHAR for the database would also be ok, and probably faster, I imagine.
EDIT2 This primary key will also be referenced by other tables.
As Marc's comment indicates, int will be more efficient for both memory and performance.
I'd recommend against tying logins to IP addresses, some users will have each request to the server come from a different IP address (onion routers, AOL, who knows what other kind of weird corporate NATs), and being logged out all the time will be super annoying.
You may also want to consider using sessions instead of setting a cookie saying who they are logged in as. Even though having a sig would make it a bit more secure, using sessions would be safer still, along with giving you more flexibility to track information about users before they log in (for example, what page they should be redirected to after a successful login).
Here's my question: should I have the primary key for the Player table be the player's name (a text field that I know will be unique), or should I create some arbitrary auto-incremented index for that?
The latter.
Names tend to change.
whether to store an int or the user's name in text.
As well, I want to do some sort of hashing on that value
Please make your mind first, then ask
is it going to be hash or a plain value finally? If the latter - what's the difference then?
So, in terms of both efficiency and design, which is the better choice?
Oh. This one absolutely doesn't matter.

Strategy for unique user-voting such as Stackoverflow's?

I noticed that for voting SO implements an XHR method which POSTs to a posts controller and sends the post ID and vote type through the URL, in addition a fkey parameter is sent, eg:
http://stackoverflow.com/posts/1/vote/2
I'm going to be implementing a similar technique, I'm wondering what logic I could use to prevent duplicate voting by the same user and prevent spamming, in addition to overall logic when implementing this.
The schema for the table I'll be storing them:
thread_id user_id vote_type
2334 1 2
So far I came up with these bullet points:
ensure the user is logged in
ensure that a valid post ID and valid vote type is sent
ensure that after POSTing, the user has not previously voted
the code that creates the hash can't contain dynamic information such as user agent, since a user could be on a different browser, different OS, right?
Update:
"SO is probably using the login cookie to identify the user." - Andrew
Could someone demonstrate how this would be done, or in other words more specifically provide an example of how the fkey, which is an alphanumeric 32-bit string, is generated?
Question:
since I'm not sending the actual user id anywhere with my XHR code, does this mean I have to update my table schema so that I can store the fkey instead of say, the user_id? The fkey will probably have to be unique to each user, and so I can probably query whether there is a row in the voting table that has an fkey of whatever.
Would appreciate any tips or insight on anyone who's implemented a similar technique.
create UNIQUE index on fields (thread_id, user_id) and DBengine will protect you from multy comments on one thread :)
You can just sign the URIs somehow in order to prevent users from manipulating valuse. For instance, you could hash parts of the URI with a secret and append the hash to the URI. When users copy the URI and change values, the URI and the signed part become invalid.
This is often done in RESTful APIs, and your current approach is similar to.
I think it depends on how badly you want to keep people from re-submitting or fiddling with your data. Nothing will be 100% (unless your budget is through the roof), but you can do a good job of keeping most people from resubmitting by:
check their UID - or generated ID from the UID (I will explain)
record their IP address, and check against the DB for the IP and the submission ID (along with the generated UID)
Using the IP solution alone, can be defeated by using a proxy of course, or a connection that changes IP's often such as the DSL carrier in my city (but even then, its every couple of days). I personally generate a unique key based on that persons UID, and pass that back and fourth if necessary. A salted MD5 hash usually works fine, or even an AES implementation if MD5 is viewed as too weak. Combined together, you should have a good starting place.

Categories