I need to provide store's clients with a tool to check the status of their repair orders.
The clients don't have a user or password. They are only a record in the database. Yet I need to give them a way to log in to the webpage and check their status (ready or not). Forcing then to register is not an option.

I came up with this idea:

  • The user is asked for their email address.
  • The system checks if this email is registered in the database, generates a hash, and emails a special URL with the hash.
  • The user checks the email and goes to this URL.
  • When the system gets a request to the special address, it checks if the hash is in the database and retrieves the user_id.
  • If it's present, voila! "Hello John Doe. Your order #3454364 is ready for pickup"

The hash generation algorithm would be:


The hash/password is salted and Bcrypt(ed) in the server. I could add a timeout where the hash is only valid for 1 day or something.

Is there something horribly wrong with this idea?

What work factor should I use for Bcrypt? It seems that the general idea is to increase the number until it takes ~1 second.

I like the output of MySQL's PASSWORD for the hash generation because it's very URL friendly. But that's really the only reason. Any other suggestions?

  • 1
    If you already have the user's email address, why not just e-mail the user as soon as the order is completed?
    – Lie Ryan
    Commented Dec 13, 2016 at 10:03

2 Answers 2


The idea itself is fine; your users are performing non-critical actions using a special URL. However, there are two things that could go wrong here:

  • Your identifier is SUBSTRING(PASSWORD(UUID()), 2), the problem is that UUID() isn't very reliable to generate unpredictable and unguessable identifiers.

    WARNING: Although UUID() values are intended to be unique, they are not necessarily unguessable or unpredictable. If unpredictability is required, UUID values should be generated some other way.

    It's far better to generate random identifiers based on the output of /dev/urandom.

  • By not using SSL (HTTPS), the unique identifier will be transmitted in plaintext (and the order status for that matter), and thus it will be exposed for anybody sniffing your client's connection.

But all in all, I say it's a pretty good solution for your purpose.

  • 1
    I like the output of MySQL's PASSWORD for the hash generation because it's very url friendly (and uuid because RANDOM is anything but random). But that's really the only reason. Any other url friendly suggestion? (no need to be mysql based) Commented May 18, 2013 at 21:01
  • 1
    @TheDisintegrator It's already there in the second link. It's what Etsy are using for their password reset URLs.
    – Adi
    Commented May 19, 2013 at 0:27

For the level of security that your service sounds like it requires, I'd say that this sounds like a reasonable solution.

The risks are that someone will intercept a link and get access to the customers information, so you should make sure that access to the status page is encrypted via SSL.

For the timeout you could either go with the approach that you've got (time-based) which seems reasonable under the circumstances, or you could set each hash to only be used once (i.e. the hash needs to be re-created each time the customer uses it)

An alternative that I've seen used for this kind of system which is somewhat less secure but easier for customers to use, is to request information about the order (e.g. Order ID, customer surname, customer postal code). This gets rid of the e-mail step, but is susceptible to a brute-force attack.

How secure you want it largely depends on how sensitive the information is and how annoyed the customers would be if someone else gets access to it.

  • 1
    The information is not really sensitive. But I don't want to see this broken at all. Commented May 18, 2013 at 21:04
  • @TheDisintegrator You also want SSL to prevent tampering, not just to ensure confidentiality. It would not be great for a client to get phished ("Log in with Facebook" to see your order status) or run a malware script injected into your URL. Commented May 30 at 16:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .