There are several drawbacks to this two phase registration method:
- Increased complexity in handling account activation
- Unconfirmed users are persisted and need to be cleaned up from the database from time to time
- If the user is let in temporarily right away, there have to be additional measures to guard against bots and to authorize actions that are reserved for actually confirmed accounts.
- It is very inconvenient for the user if she first gives all her details and then somehow fails to confirm the account, e.g. due to a typo in the email address.
A much simpler, yet secure way of registration starts by confirming the email address. First the user gives her email address and the system sends her an email containing a unique registration link. With a properly constructed link, nothing needs to be persisted on the server side at this point. Only when the user follows the link, is she requested for other account details. The account is then created directly into an active state and the user is let in with full access rights.
The trick is in the link itself. It should be constructed to be a) hard to guess and tamper with and b) expiring by itself after a fixed amount of time. This can be achieved easily by adding a timestamp and the email address itself as parameters to the link and using a Message Authentication Code (MAC) to ensure that these parameters are not tampered with:
https://yourdomain.com/registerin which the MAC is constructed using a hash function like SHA:
sha(123456789;email@example.com;SECRET)Here the SECRET is a long random phrase that is only known by the server. Even if one knows the building blocks of the link, one cannot fake it unless one knows the secret phrase.
Before even showing the user a registration form, the MAC is to be checked by comparing the supplied MAC with one calculated from the other message parameters.
Once we know that we can trust the link parameters we know that the given email address exists and is accessible by the user. Expiring the link is simply a matter of checking whether the timestamp is not too far in the past (e.g. three hours).