Jump to content

Expiring Token


Staggan

Recommended Posts

Hello

 

I am looking to create an expiring token for use with our password reset system. We want tokens to be valid for a set period, let's say 24hrs.

 

Currently we md5 the username and userid, and send this as a token to the users registered email... It's OK, but means that token is valid indefinitely. I am not keen on adding more fields to the database to store the time the request was made, so wondered if anyone had a suggestion?

 

Is there a way I can encrypt a token including a timestamp and then decrypt it to separate the elements out to check the timestamp?

 

Thanks

 

 

Link to comment
Share on other sites

Add a column in your token table to store a timestamp of when the token was requested

 

Then when the the token is used just compare the current date and time, to that of the timestamp in the token table

 

You can then use a conditional statement to see if the condition - say less than 24 hours - has been met. Otherwise throw an error

Link to comment
Share on other sites

Hi,

 

a hash of the username and the user ID? How is this secret data? And what is the hashing supposed to do?

 

You need a secret token. That means you need to read, say, 16 bytes from the random number generator of your operating system:

$raw_token = openssl_random_pseudo_bytes(16);
$encoded_token = base64_encode($raw_token); 

If the OpenSSL extension isn't available on your system, you can also use mcrypt_create_iv() or read directly from the system device (typically /dev/urandom). 

 

 

Encryption doesn't help, no. This is not about keeping the timestamp secret. You need to prevent people from altering it, so this is a problem of integrity and authenticity. The theoretical solution is a message authentication code (MAC)

 

But, frankly, don't do it. Getting MACs right is very difficult, and it will make your system much more complex and fragile. For what? Only to save two database columns?

 

The proper solution is to send the encoded token to the user, store the timestamp and a hash(!) of the raw token in the database and then check them on request.

Edited by Jacques1
Link to comment
Share on other sites

Thanks for the replies.. 

 

I think I have a solution, but would like some comments.

 

When a user requests to change their password we ask for the username for their account...

 

We then get the users email address, userid and current time from the database, and generate a token as below.

 

md5 the username and userid, and then append the timestamp.

 

We then use MCRYPT to encrypt the whole thing.....

 

So now we have a token with an md5 of the username and userid, with the timestamp appended and all encrypted.

 

This token is emailed along with a link to the user.

 

 

The user then clicks the link and opens a page...

 

This page, using MCRYPT, decripts the token, and removes the MD5 part of the token.. as all MD5 are 32 characters long...

 

What we are left with is a valid timestamp....

 

We can then test the timestamp against the current server time and decide if it has expired...

 

Thoughts?

 

 

Thanks 

Link to comment
Share on other sites

As I've already said, this makes no sense.

 

You can't just throw a bunch of cryptography at the problem and hope that it will somehow magically make the site secure. You need to use the right tools in the right way.

 

Hashing the username and the user ID is utterly useless. What is this supposed to do?

 

And again: Encryption does not help you at all in your case. The purpose of encryption is confidentiality. It generally does not prevent people from altering the data. So what are you trying to hide from whom? And how does this solve the problem?

Link to comment
Share on other sites

You haven't incorporated either of our comments into your solution

 

As Jacques says, hashing the username is pointless - you only need to hash the password

 

As I said previously but in more detail....

 

1.a - Add a column in your token table to store a timestamp of when the token was requested

1.b - At this point a new row will be inserted into the token table, along with the new token, user id, and current timestamp

1.c - An emai will be sent to the user with the token link

 

2.a - The link is followed, compare the token to the database and see if they match

2.b - Find the current date and time

2.c - Compare this to the timestamp in the row, and if it meets your criteria (ie 24 hours) allow then to update the password

 

Edited by paddyfields
Link to comment
Share on other sites

Do not store the plaintext token in the database. It's equivalent to a password, so you may only store its hash.

 

But apart from that, yes, this is the standard way as used by hundreds of thousands of sites around the world.

 

And only to clarify: The token must be unpredictable. Anything other than a bunch of random bytes does not work.

Link to comment
Share on other sites

Sorry,

 

I am a little confused.

 

We are not talking about passwords here, or overal site security, we have that. What we are talking about is an easily created and timestamped token to allow us to validate a request to change a password, without the need to store additional data in the database.

 

Using the username and userid for a hash made sense as these are two known quantities that we can easily get once we have the username. Unless someone knows the userid for a specific user they will, hopefully, be unable to replicate the token and therefore be unlikely to use this to reset someone's password.

 

Adding the timestamp then allows us to know when a request was made, and allows us to decide if it has expired. 

 

Encrypting the whole lot, using MCRYPT as Jacques suggested, then just makes the whole process of cracking the tokens to be able to reset someone's password that much harder...

 

What am I missing?

Link to comment
Share on other sites

We are not talking about passwords here, or overal site security, we have that. What we are talking about is an easily created and timestamped token to allow us to validate a request to change a password, without the need to store additional data in the database.

 

I realize that, and the bottom line is: This is nonsensical.

 

I don't know why exactly you need to save database columns, but this results in a much higher complexity, much more work and much more problems. That's hardly a good decision.

 

 

 

Using the username and userid for a hash made sense as these are two known quantities that we can easily get once we have the username. Unless someone knows the userid for a specific user they will, hopefully, be unable to replicate the token and therefore be unlikely to use this to reset someone's password.

 

The user ID is not a secret. Those are just sequential numbers, right? Then it's not exactly hard to guess the ID of other users, is it?
 
Even worse: This “token” is valid for the entire lifetime of the user account. Once an attacker has gotten hold of it, they can use it as often as they want.
 
And hashing the user ID does not help you at all. If an attacker knows the user ID, they can simply calculate the MD5 hash from it. Nothing prevents them from doing that. And if they know the hash, well, then they already got the token. So the hash does absolutely nothing. You might as well append the letter “x” to all IDs.
 
Long story short: This “token” does not work.
 
 
 

Encrypting the whole lot, using MCRYPT as Jacques suggested, then just makes the whole process of cracking the tokens to be able to reset someone's password that much harder...

 

It did not suggest encryption. You're putting words in my mouth.

 

I specifically adviced against encryption and explained exactly why it does not work for your case. It's as useless as that MD5 hash.

 

Sorry, but I think this discussion is pointless. You don't even seem to read the replies, let alone take the advice. We posted two valid solutions, one of them involving database columns, one of them not. If you stick to your approach no matter how broken it is, go ahead. But you don't need us then.

Link to comment
Share on other sites

Thank you... 

 

And sorry, I misread your original answer.

 

I wanted to understand the reasoning, which you have now explained, so I will have to bite the bullet and amend the database to store the tokens for validation.

 

Thanks again.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.