Old question, but since the question is about security and not convenience I feel that all of these answers are lacking one important aspect: enumeration attacks. I agree that passwords and/or another second factor is what is being used to authenticate the users as user2428118 mentioned earlier and not the username/email, so I am not going to discuss that at all. Also, in the event of a database breach, neither username nor email is any more or less secure since they are both stored in plain text.
However one security aspect that none of these questions address is username/email enumeration. In application security, our goal is minimizing or eliminating the knowledge that a hacker has that would help them break into the system. If they can determine the username or email used for an account, that account is less secure than an account that the hacker has no knowledge of.
If we use usernames for authentication then we need a way to tell a user that their desired username is taken already when they are signing up. This can be exploited by a hacker to determine if a given username exists already. That's a bad thing because if they know the username, they can then try to log in with the most commonly used passwords from previous database breaches. These common passwords are readily available online.
However, if we instead use email addresses for authentication, when adding a new account and the email exists already, just send a password recovery email to the user instead of a new sign-up email. However in the UI, simply tell the user to check their email address for further instructions, but give no indication whether that address is valid or not.
Email
- Hacker can guess based on your name by using yourname@company.com or other commonly used addresses (e.g. admin@company.com, info@company.com, etc) or by filling out web form and using the address in the email reply to attempt authentication. However users are generally free to choose any email address they want, even personal addresses, and the users signing in may not necessarily be affiliated with or employed by the website they are logging into, so in this case they wouldn't have a @company.com email address logging into the company.com website.
- Enumeration attacks can be prevented.
Username
- Sometimes displayed online (e.g.
"This post was created by {{username}} on {{date}}"
) whereas emails should hopefully never be displayed in plain text.
- Enumeration attacks cannot be prevented
- More vulnerable to dictionary attacks as people often choose simple usernames (e.g. their first name).
Bonus: With that said, one other (more difficult) way a hacker can determine whether a username or email exists in the system is by attempting to log in and looking at the page response times. Best security guidelines show that we want our passwords to be hashed with a slow hash, however if a username or email does not exist in the database, we won't have to verify the password hash because there is no matching user. If our hash takes 100 ms to perform and the database query takes 5 ms, the response times for a request for a valid user will be, on average, 95 ms slower than an invalid user. The way I get around this is to always hash the provided password, even if the user doesn't exist in the database, or if the user does exist, then I just verify the hash in the database.