OTP-only authentication - authentication

I'm considering building a website user authentication system using only one-time-passwords: users would get one in the email each time a normal password is normally used e.g. for signup, sign-in, risky actions and account deletion.
Some problems that I see with it that don't seem critical:
Can't change password to invalidate all existing sessions - can work around by storing sessions server-side and having a way to invalidate them for the user
Anyone can check if a certain email is registered in the system - doesn't seem like a critical problem for a generic website
Anyone can request an OTP for any email - will be dealt with using API limits per remote connection and a limit of 1 unused OTP per hour
I'm not seeing this method mentioned or used in the wild though. Does it have any major drawbacks? Many thanks!

OTP-by-email only is safer than password-only (it's basically like forcing the user to change their password every X hours).
I want to both address some of your non-critical points, and highlight some drawbacks.
Non-critical
Invalidating sessions
You don't have to store all sessions, only the invalidated ones, and only for the max duration of a session.
Checking that a user (email) is registered
That actually is a problem - it tells you that the email owner uses this website, which is a privacy issue, however minor.
But moreover, it's an attack vector. An attacker can scrape your user list, or just go attack that user on other sites, presuming that this email exists and links to a real human. Moreover, they can issue excessive OTP requests on their behalf, which I'll address in a bit.
All that said, there's no reason which this problem would manifest just because of OTP. A user can request OTP, and you can always reply with "If the email address hello#world.com is registered, a one-time password has been sent to it". This only has a slight usability implication.
Anyone can request OTP for any email
If an attacker can flood your site (from different IP addresses) with requests for OTP for hello#world.com, either you block this user (namely, that user has been DoS'ed), or you the site will flood the user's mailbox, which can get that mail server to flag the site as a spammer.
This could also be done in normal sites with password-reset emails, but that's why you typically want your user list to be secret.
Bigger drawbacks
Usability
OTP-only login assumes that the device from which you're logging in is also logged into the mail account linked to this site. Otherwise, the user has to log into the mail account in order to log into your site.
Single-factor authentication
The security community is pushing towards multi-factor authentication, where password is usually the first factor. A good practice would be to at least allow 2FA to users who choose to.
Account lockout
If a user's email account is no longer accessible for whatever reason (e.g. they used their work or university email), they can't log in, or even change their email address to their new one.
Email activity
If the site is heavily used, then it will be sending a lot of emails, to various public email services, continuously, all the time.
This alone may cause the site to be flagged it as a spammer, or even ratelimited.
If it does get ratelimited, some users will not be able to log in.

Related

Logging in to website accounts using HTTP requests, e-mail and password

Suppose I have an account created on a website (in specific, a PS Network account or Google account), and I only know the login email, but not the password (with no access to the Google account in the PSN case).
Is there a way for me to verify if a given password is the correct one using only HTTP requests or something similar using code? This is to save me the time of trying multiple passwords and having to wait for a server response until I find the right one.
Details:
I'm not trying to hack into someone's account.
I tried to log in to a secondary PSN account I created years ago but I didn't know the password, only the email (I also created a specific google account/email for this purpose, so I don't remember its password either). Even though I don't remember the exact password, I know which combinations of specific words and numbers I might have used back then. But I want to run through "all" the possible combinations with code, instead of doing it manually, to save time and effort. Is there any URL to which I can make POST requests to try and log in using only email and password in the request body, and verify if login was successful? (either on PSN or Google, either one will give me my PSN account back)
Thanks in advance
I tried looking for REST API and URLs that allow me to do this, but it seems to me that Google in specific has gone strict on this, requiring more than just address and password. For the PSN account, I tried to sniff around using developer tools to watch which URLs are requested when I try to login using the Sony website interface, but I can't understand which requests are doing what.
What you want to do is a popular method for hacking account access. it is called bruit force where by the hacker you continues to try passwords over and over again until they gain access. A dictionary file is often used containing combinations of specific words and numbers
No system is going to have an endpoint that will make it easier for hackers to gain access to user accounts by force.
May I suggest using a reset password account recovery option available through most login services these days.
instead of trying to bruit force your way in. Most authorization servers will lock an account after 5 bad attempts.

Does forgot password routine mean passwords are not necessary?

For some less critical websites it seems common for a user to be able to reset their password if they have forgotten it. The fact that they can access the email account that they registered with is considered good enough.
In those cases the only advantage of the password seems to be that, if the user can remember it, they don't have to check their emails in order to access the website.
Although not having to check your email is a convenience it has to be weighed against the inconvenience of remembering a large number of passwords for all the websites that require them.
A user would register their email address and verify it by responding to a link sent to their email address. After that, every time they wanted to access the site they would enter their email address into the login form and then click the link in the email sent to them.
Is there an argument for less critical websites to allow access without a password in this way?

Secure strategy for staying logged-in when using OpenID

I have a website that uses OpenID to sign in users. The library I'm using, returnes a user profile when the user logges in. This profile contains user's email, name, a link to the avatar and an ID which the OpenID provider has returned.
My strategy for keeping the user logged in is this:
When the user logges in for the first time, I create a hash code based on the OpenID's returned ID
I store this hash code alongside the user's ID in 2 cookies.
When the user comes to my website, I check for these cookies, and if they're available, try to match the ID and the hash code, if it's correct, I log the user in.
Now the problem is this: if somehow this cookie information gets stolen from the user, the hacker can easily log in instead of the user himself. I could create a new hash code for each time the user logges in and update the user's cookeis but it'll make the information of other browsers/computers cookies invalid.
Since the StackOverflow website does not suffer from such problem, I would like to know what should I do to both secure my login strategy and add the functionality to stay signed in for the users.
The standard way to do this is to assign a meaningless session ID and send that as a cookie; in your database, you can store the user's credential information alongside that session ID. When a user logs out, you can invalidate that session ID.
Isn't this a problem with ALL mechanisms for letting the client stay logged in? If you log into your, say, gmail, and I steal your cookies, and put them in my own browser, there is no way to distinguish my browser from your browser and I get access to your gmail. There's no way to stop the kind of attack you're suggesting, I believe (other than the user keeping their computer free of viruses etc. that could steal the cookie)

How much user data should be required to grant a password reset?

I'm looking to add password-reset functionality to my site and have been browsing the numerous threads discussing various aspects of that issue here on SO. One thing I haven't really seen clarified is how much information to require from the user for confirmation before sending out the reset email.
is email alone enough?
email + account username?
email + account username + some other identifying value all accounts must input?
I don't want my site to seem like an old wrinkly nun with a ruler, but I don't want people to be able to abuse the password reset system willy-nilly.
Suggestions?
I use just an email and send an email to that person with an activation code in a link. That activation code expires within 2 days and once it gets uses it also is invalidated.
This means the person has to have access to that email account in order for it to work, and it can only be used once.
It is not uncommon to use the email + account username, but my email IS what you sign in with, there are no usernames. The decision is up to you.
I think email is enough without it becoming a nuisance.
First concern should be security. How bad would it if another person got a hold of a user's password? If this is unacceptable, I'd say what Babiker said - email and a security question of some sort, preferably something that's never communicated between the site and the user, with the exception of sign-up process or a security settings edit by the user. The assumption here is that the user's email account has been compromised.
If security is not a huge deal, i.e. there are no real privacy/financial/etc risks involved, I think email is enough. To minimize risk for nuisance, you could do what Kerry suggested - i.e. not reset the password automatically, but provide a verification link. Also, you might want to place some restrictions on how frequently the feature can be used by a given user to prevent someone from filling your inbox by repeatedly entering your email.
Email
Some other identifying value all accounts must input. Like a security question.

Implement password recovery best practice

I want to to implement password recovery in my web application.
I'd like to avoid using secret questions.
I could just send the password by e-mail but I think it would be risky.
Maybe I could generate a new temporary random password and send it by e-mail but I think it is as risky as the above point.
Can I send a url by e-mail for example http://example.com/token=xxxx
where xxxx is a random token associated with the user. So when the user navigates to that url he/she can reset the password.
When I was in the Air Force the security rule we had was: When setting or resetting passwords, do not send the user id and the password in the same email. That way, if someone is intercepting emails snooping for passwords, he has to successfully intercept BOTH emails, and be able to connect them, to breach security.
I've seen a lot of sites that use the "go to this URL to reset your password". Maybe I'm missing something -- I don't claim to be a security expert -- but I don't see how that is any more secure than just inventing a new, temporary password and sending it. If a hacker intercepts the email, why can't he go to that link and see the new password as well as the legitimate user could? It looks to me like extra hassle for the user with no security gain.
By the way, congratulations on NOT using security questions. The logic of this device escapes me. Since the dawn of computer security we have been telling people, "DON'T make a password that is information about yourself that a hacker could discover or guess, like the name of your high school, or your favorite color. A hacker might be able to look up the name of your high school, or even if they don't know you or know anything about you, if you still live near where you went to school they might get it by tryinging local schools until they hit it. There are a small number of likely favorite colors so a hacker could guess that. Etc. Instead, a password should be a meaningless combination of letters, digits, and punctuation." But now we also tell them, "But! If you have a difficult time remembering that meaningless combination of letters, digits, and punctuation, no problem! Take some information about yourself that you can easily remember -- like the name of your high school, or your favorite color -- and you can use that as the answer to a 'security question', that is, as an alternative password."
Indeed, security questions make it even easier for the hacker than if you just chose a bad password to begin with. At least if you just used a piece of personal information for your password, a hacker wouldn't necessarily know what piece of personal information you used. Did you use the name of your dog? Your birth date? Your favorite ice cream flavor? He'd have to try all of them. But with security questions, we tell the hacker exactly what piece of personal information you used as a password!
Instead of using security questions, why don't we just say, "In case you forget your password, it is displayed on the bottom of the screen. If you're trying to hack in to someone else's account, you are absolutely forbidden from scrolling down." It would be only slightly less secure.
Lest you wonder, when sites ask me for the city where I was born or the manufacturer of my first car, I do not give an actual answer tot he question. I give a meaningless password.
</rant>
First off, do not store a plain-text copy of the user's password, or even an encrypted version. You want to only ever keep a hashed copy of the user's password.
As for recover solutions, I find that the recovery link to change the user's password is the best solution in my experience. It will probably be a bit more convenient for the user, while being largely the same from a security point of view as sending a new random password to be changed after next login. I'd still recommend having the recovery url expire after a reasonable short period of time, as well as only being usable a single time.
Hard to say what you should do, as pretty much any solution to this problem will weaken security. Unless maybe you want to investigate sending an SMS, callback verification, one-time password generators, or other such schemes that take password recovery to a different medium.
However, what you should not do:
Send the password - because after all, as has already been mentioned, you don't have it.
Generate a new temporary password - not only is this as insecure as sending the password, it also leads to the possibility of a denial of service attack. I can go to the site, pretend to be you, request a new password and then (if you haven't checked your email) you can't log in, don't know why and have to request a new new password ...
The token is probably the way to go. Receiving it notifies a forgotten password request, but doesn't take any action unless you confirm. You would also make it a one-time token with a relatively short expiry time to limit risk.
Of course, a lot depends on the application. Obviously protecting financial and other sensitive information is more critical than preventing your account being hacked on mytwitteringfacetube.com, because while it's inconvenient, if someone wants to steal someone's identity on a social network site, they can just open their own account and masquerade with stolen information anyway.
Obviously, you can't send the original password by email, because you're not storing it (right?!). Sending a temporary password (that must be changed, because it only works for one login), and a link to reset the password are equivalent from a security point of view.
I don't unnderstand the attitude towards the secret question method. It's not like I am going to make my password "BlueHouse" and then make my security question "What are your two favorite things?" and the answer "Blue and Houses". The security question is not the magic key to get the actual password. It's usually a way to get a new password sent to the email address on file. I don't know how else you guys do it, but it sounds like you do one of two things.
1) The user clicks a "I forgot my password" button and the new password is sent to the user.
2) The user clicks a "I forgot my password" button and then has to answer a security question before getting the new password emailed to the address on file.
Seems to me that option number 2 is more secure.
Why is sending a token any more secure than sending the password? If an email account has been hacked, it's been hacked. It doesn't matter if there is a link to reset the password, a token, or a new password. Don't forget, most sites don't say "The new password has been sent to the following email address for you to hack into". A hacker would need to guess the email address that needs to be hacked.
I agree with Andy. Aren't security questions normally independent of the password? (mine are) Meaning they have a question and an answer and aren't related to the password. It seems like this is used to prevent spurious password reset requests and actually does have a use.
Imagine - someone could go to a site's "forgot password" utility and enter a zillion email addresses - or just one person they want to annoy. If the password is reset at that point, the people belonging to those email addresses would have to then notice in their email the password reset and login to the site with the reset password next time they went there. With the security question, this isn't as easy for someone to do.
I see Amazon sends a link to the given email. They also require you to enter a captcha to prevent DOS attacks. Because it's a link, I imagine that means they did not reset the password immediately and it would be reset once the user clicks the link. With the scenario above, the user would just see the email and note that "no I didn't do that" and go about their business not having to change their password needlessly. A security question might have prevented the attempt at the beginning and the legit user from getting the email in the first place.
Here's a whitepaper on it:
http://appsecnotes.blogspot.com/2010/09/latest-forgot-password-best-practices.html
This one actually recommends secret questions as a major part of the authentication process. And sending an authentication code via email and requesting it is just an add-on layer you can optionally include.
It really comes down to how much security you want to have. One the one end of the extreme is a password reset process that involves contacting and certifying that you are who you claim to be, e.g. via id, because your mailbox could be compromised as well. Actually, as people tend to use the same password everywhere this is very likely. On the other end there is the standard approach that involves just sending out an email with a random new password.
"Secret" questions and answers are just another form of username and passwords with the fatal flaw that they are usually incredibly easy to guess, so good that you don't want to use them.
To your point about the token, I don't think it makes a big difference in overall security. Whether you send out a token that allows a user to change the password or whether you send out a random password right away doesn't make a big difference.
Just make sure the token is only usable once and preferably only in a limited time span, e.g. +24h after requesting it.
And, as pointed out by previous answers, NEVER EVER store plain passwords. Hash them. Preferably add salt.
Here's how I resolved it:
I added retrieve_token and retrieve_expiration fields to my 'users' table.
The user requests a password reset by providing their email and filling out captcha. A random hashed value is generated for their retrieve_token field - i.e. md5($user_id.time()), while retrieve_expiration will be set to a datetime that expires in next 45 minutes. Email is sent out to the user with a link:
https://example.com/reset-password?retrieve_token=912ec803b2ce49e4a541068d495ab570
SSL should be mandatory when authentication is required. You can also add a table for logging reset requests that stores email and the IP address. It helps track down possible brute attacks and you can block attacker's IP if necessary.
You could implement security question for requesting password reset, but I feel captcha would be enough to discourage anyone from repeating the request multiple times.
#Jay. The reason why you go to a URL to reset your password instead of just sending someone a new temporary password is more than just security. Without something like a URL with a token, a person could reset another persons password. There is no need to gain access to the email. If someone had a bone to pick with someone, they could just keep initiating a new password reset. Then the poor target has to logon and change the password again and again.
By sending a token, the user's password does not change until they login with it and confirm it. The spam of reset emails can be ignored. Tokens are just as easy (if not easier) to generate as a new password by using a GUID, it's not really extra hassle for the developer.
Also, because the GUID is unique (a generated password might not be), a token can be tied to a username. If the incorrect username is given on the URL, then the token can be cancelled (i.e. when a different person initiates it and someone intercepts it.. assuming that the username isn't the same as the email).
#Jay. The proper use of security questions is to initiate a password reset email, not for actually resetting the password. Without a mechanism such as a security question, one could initiate a password reset. Althought seemingly beign, sending a reset email could be sent to an email that might no longer belong to the original owner. This is not rare. For example, when employees leave a company, often those mails are forwarded to another employee. A security question, adds a low level of obfucation to that scenario. It also reduces issues where one person keeps initiating a password reset on the wrong account causing some poor sod to get unintentionally spammed. Security question are really not meant to be truely secure, they are just meant to reduce scenarios such as those. Anyone using a security question to actually reset the password is doing it wrong.
Regarding security question/answer. As a user of websites I personally don't use them (I enter garbage in them). But they are certainly not useless or meaningless as some say here.
Consider this situation:
A user of your site has left his desk to go to lunch and didn't lock his workstation. A nefarious user can now visit the page for recovering/resetting password and enter the user's username. The system will then email the recovered/reset password without prompting for the security answer.
Here's an example of how someone did it with Node.js, basically generate a random token, an expiry time, send out the link with the token attached, have a reset/:token route that ensures a user exists with that token (which is also not expired) and, if so, redirect to a reset password page.
http://sahatyalkabov.com/how-to-implement-password-reset-in-nodejs/