Signup or Invitation Email Verification w/o Database
Thoughts:
Use true asymmetric cypher for the "cookie" to prevent bots creating accounts. Encrypt the "cookie" using public key, verify it by decoding with private key.
Rationale: If only a base64 or other algorithm was used for encoding the cookie, it would be easy to reverse-engineer the scheme and create accounts automatically. This is undesirable because of spambots. Also, if the account is password protected, the password would have to appear in the cookie. Anyone with access to the registration link would be able not only to activate the account, but also to figure out the password.Require re-entry of the password after activation through the link.
Rationale: Depending on the purpose of the site you may want to improve the protection against information spoofing. Re-entering the password after activation protects against stolen/spoofed activation links.When verifying the activation link, make sure the account created by it is not created already.
How do you protect against two users simultaneously creating an account with the same name?
Possible answer: Use email as the login identifier and don't require unique account name.Verify the email first, than continue account creation.
Rationale: This will minimize the information you need to send in the cookie.
There are some e-mail clients which break URLs after 80 letters. I doubt that you can fit all the information in there.
Some browsers have limitations for the URL, Internet Explorer 8 has a limit of 2083 characters, for example.
Why don't you clean your database regularly (cron script) and remove all accounts that haven't been activated for 24 houres?
I have done pretty much the same before. I only have 2 suggestions for you,
- Add a key version so you can rotate the key without breaking outstanding confirmation.
- You need a timestamp or expiration so you can set a time limit on confirmation if you want to. We allow one week.
As to the shortest URL, you can do better by making following changes,
- Use a stream cipher mode like CFB so you don't have to pad to the block size.
- Compress the cleartext will help when the data is big. I have a flag and only use compression when it shrinks data.
- Use
Base64.urlsafe_encode64()
so you don't have to URL encode it.