0

I've been working on my first project, and my initial registered users haven't been particularly sticky. I'd like to send them an email with some news and information and have them be instantly logged in when they hit the call-to-action link. I was thinking about generating an auth code with PHP's random_bytes(), and storing it in a table with their corresponding user_id.

So basically, the email would be:

Hey oldUser2017, newUser2018 sent you a message! Click <a href="http://mysortofokproject.com/message/20992?authCode=657f8b8da628ef83cf69101b6817150>here</a> to see it instantly and not even have to log in or reset your password or anything annoying!

And on the backend

userId = getUserIdFromAuthCode($get['authCode'])
if(userId){
 $session = getUserDetailsFromUserId(userId)
}

Given that this is how we authenticate an email address and activate an account:

  1. What would be so bad about me doing this?
  2. Is PHP's random_bytes() good enough, and what length would you use?
  3. Should it expire?
  • Refering to your second Question: Yes its enought to use this function in PHP. As you can see in the specs it generates ryptographically secure pseudo-random bytes which means it can´t be guessed even if you got much information. Your length should be more than 80 bits. This is considered as secure. – CD Rohling Aug 21 '18 at 9:55
  • As a user, I wouldn't even bother to register if you do this. Imagine as a attacker, i can simply learn the "marketing email" contains something that allow me to collect user data, guess what happens next? – mootmoot Sep 20 '18 at 9:04
1

I have personal experience of a system that did pretty much this. I didn't develop it, I just had to handle the fall-out when the "instant login" went horribly wrong :)

The problem we encountered was that some users forwarded the emails to other people, not realising that the email effectively had a credential embedded in it. So when the person who got the email forwarded to them clicked the link, they were logged in as the original user.

You could argue that it is the fault of the original user, but to me, it's not at all obvious that clicking a link will automatically log you in as someone, so it's not reasonable to expect users to be particularly careful when forwarding.

Referring to the comment on @ideaman924's answer. I think users are more likely to recognise the risk of forwarding a password reset link to someone, than an opaque "instant login" link.

A better solution in my opinion would be to have a normal login page, but then have a session cookie that lasts a reasonable length of time, including after they close their browser or navigate away from your site. Then if they return within the cookie expiry time, either by clicking the email link or by any other route, they will be already logged in.

0

I don’t think this is a good idea. First, emails are sent in plaintext, which means they’re neither secure or private. Even though some of the hops may be TLS encrypted (no guarantees), it’s currently fairly easy for a node on the path to MITM the email anyways, or for any of the intermediate (or end point) servers to read the plaintext email. This is very similar to sending a user’s password through email and is a bad idea.

Also your example uses http and not https, so you’ll be leaking this password in server logs and to anyone passively monitoring the network.

More importantly, this completely bypasses your login code, adding more potential security vulnerabilities. For example, you probably limit the number of login attempts, but do you also limit the number of login attempts using these new secondary passwords you’re generating?

If you did decide to do this, the code should definitely expire after either the user follows the link, or after a short period of time. It would be better to not log the user in at all, and maybe use this code to display the message only (although it’s probably still not a good idea).

0

Proposal: What if you create a separate page and service which displays the message to a user following that link, but then simultaneously invalidates that authCode, so that it can only be used a single time? (You could also place a time-limit on it`s validity).

This will let you show the message with no hassle, while still keeping your users safe. You can always provide a form for logging in (or resetting a password) below the message on the same page; if your user is already on that page, and has accessed it from a link in his or her e-mail, chances are the extra work required for them to actually log in will seem minimal.

Perhaps you can retain more users this way without circumventing your security entirely?

  • 1
    Agree with the comments. Although if you do invalidate the authCode after one visit then be aware that if the user is running something like McAfee link scanner, which checks email links by scanning the the pages it finds ... that will invalidate the authCode before the user gets there. So you may need to account for that in your solution. – Chris Lewis Sep 20 '18 at 9:07
0

I can't speak for PHP, but

  1. What would be so bad about me doing this?

A lot of websites use hash codes embedded in a link to figure out where to send users once they click on a link. However, sending an auth code along is quite risky. Of course, if you follow good practices and make sure connections between your server, your mail server, and the recipient's mail server is encrypted, you don't necessarily know if the recipient has an encrypted connection between his mail server and whatever client he or she uses.

And this is a central assumption you have to make - users are dumb. They may untick "Use SSL/TLS" in Thunderbird because they don't know what it does. They might forward the wrong email to the wrong person. Minimize the risk and try and not to send authentication codes unless you absolutely have to (think password recovery.)

For reading messages or other trivial information it's usually best to let the user authenticate once he or she reaches the landing page.

  1. Should it expire?

Yes, definitely. If you decide to send authentication codes, then make it expire within a few hours (or maybe 30 minutes or less, even!) If you send link codes that redirect users to authenticate on your server, then the expiry could be set even longer because there is less chance of auth information leaks.

  • so to be clear, sending auth codes in a url in an email is risky, but this is a risk that's essentially taken every time a password reset email is sent? – user3238414 Sep 20 '18 at 21:03
  • Yes, it's equally risky, but you're minimizing the risk by not sending auth codes in promo emails. Whereas password reset emails essentially require auth codes, promo emails asking to check content shouldn't, because they don't really require the use of auth codes. To minimize the risk, most password reset emails set a timeout so the code expires. – ideaman924 Sep 21 '18 at 22:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.