1

I'm writing an account activation process from the ground up in Django, and here was my basic thought process:

Create a model like:

class UserAccountActivation(models.Model):
    lock = models.CharField(max_length=16)
    key = models.CharField(max_length=16)

Generate lock and key values when necessary using a function like this:

def generate_entry():
    """Generate a random alphanumeric string between 8 and 16 characters long."""
    ''.join(random.choice(string.ascii_lowercase + string.digits) for x in range(random.randint(8,16))

Compose a link like this:

r'^activate/(?P<lock>\w{8,16})/(?P<key>\w{8,16})/?$'

And send it out. When they hit the link, I activate the account and disable the activation key.

I was originally thinking of hashing the random strings as an extra precaution, but this seems unnecessary and it'd be pretty long to have two 32-length keys in my URL:

account/12345678/12345678
    or
account/12345678901234567890123456789012/12345678901234567890123456789012

Is this a safe and recommended way of handling account activation? Is it necessary to even have the random length on the strings?

Naftuli Kay
  • 87,710
  • 93
  • 269
  • 411

2 Answers2

1

Well, to answer that question you have to consider why you have protection on your account activation. Likely it is to prevent people from guessing the activation code, so they would be able to use a false email address. As email addresses are very easy to get anyway, the activation process doesn't need to be much harder than it would take to register an email account somewhere on the web. Anything more is wasted effort, as the attacker will simply shift the attack to another weak point.

Using random strings is perfectly fine for this.

If you need more security you can consider putting a hashed account id in there, so you can count and then stop multiple failed attempts to guess the activation code.

Rinze Smits
  • 810
  • 6
  • 5
  • A nice hack to make the random stuff a bit more secure would be to do something like this: `from random import SystemRandom` then `random = SystemRandom()`. – Naftuli Kay Nov 06 '11 at 06:50
1

It is a good thing to have variable length, lest it is susceptible to timing attacks.

Also, python's inbuilt random is not really cryptographicaly safe, so it is always preferable to use sha from hashlib or the system random generated via linux which you can obtain by making a sys call.

lprsd
  • 84,407
  • 47
  • 135
  • 168
  • Would something like `^activate/(?P\d+)/(?P\w{40})/(?P\w{8,16})/?$` be better suited? If I'm calculating a random value for `lock`, `sha1`ing it, then also including the unique id of the specific activation object (not the value of the user object), as well as a 8-16 character random string from Python, does that work? Is there a better Python library for random characters? – Naftuli Kay Oct 10 '11 at 18:16
  • Would using something like CRC32 still provide adequate safety for hashing the `lock` of random letters? It needs to be secure, but not _that_ secure, and I'd prefer a shorter URL if possible. – Naftuli Kay Oct 10 '11 at 18:20