38

I want to create a random string (token) which can be used to identify a user whilst avoiding any potential conflicts with any other users' tokens.

What I was thinking of was an MD5 hash of navigator.userAgent + new Date().getTime() to generate the token but that requires a whole Javascript MD5 library to hash it which I don't really want to do.

It has to be made up of A-Z/0-9 characters and ideally no longer than 32 characters. I am open to all ideas. Thanks!

Just to clarify I'm not looking for any random string generator, the random string has to be generated from the users details available through Javascript and can also use time to avoid potential conflicts!

fire
  • 21,383
  • 17
  • 79
  • 114
  • as you have written, the only thing that comes to my mind is a hash function. you might want to try to google something like "hash function javascript" and maybe you will find sometihng lightweight – mkk Dec 16 '11 at 10:00

6 Answers6

142

You could generate a random number and convert it to base 36 (0-9a-z):

var rand = function() {
    return Math.random().toString(36).substr(2); // remove `0.`
};

var token = function() {
    return rand() + rand(); // to make it longer
};

token(); // "bnh5yzdirjinqaorq0ox1tf383nb3xr"
pimvdb
  • 151,816
  • 78
  • 307
  • 352
  • @fire: I think this doesn't practically cause conflicts. MD5 theoratically can also cause conflicts, but you shouldn't need to worry about that. – pimvdb Dec 16 '11 at 09:57
  • It could conflict, if the token was generated through someones own browser information + your method that would be better. – fire Dec 16 '11 at 09:59
  • 7
    @fire: I don't fully get your point. `navigator.userAgent` isn't unique for everyone, so it doesn't make it bulletproof. – pimvdb Dec 16 '11 at 10:03
  • 1
    Removing `radix` (`36`) parameter from `.toString` in `rand` function will give you numeric-only hash -- if someone would like for the one like that: `return Math.random().toString().substr(2);` – trejder Sep 28 '12 at 20:23
  • Man I love a sweet one-liner! – Grogu May 05 '22 at 20:45
12

This function allows you to set the token length and allowed characters.

function generate_token(length){
    //edit the token allowed characters
    var a = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".split("");
    var b = [];  
    for (var i=0; i<length; i++) {
        var j = (Math.random() * (a.length-1)).toFixed(0);
        b[i] = a[j];
    }
    return b.join("");
}

Simply call generate_token

generate_token(32); //returns "qweQj4giRJSdMNzB8g1XIa6t3YtRIHPH"
Kareem
  • 5,068
  • 44
  • 38
12

I use an approach similar to Kareem's, but with fewer function calls and built-in array operations for a big boost in performance.

According to a performance test, this method also outperforms the accepted answer by a small margin. Moreover it provides a parameter n to generate any size token length from a white list of acceptable characters. It's flexible and performs well.

function generateToken(n) {
    var chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    var token = '';
    for(var i = 0; i < n; i++) {
        token += chars[Math.floor(Math.random() * chars.length)];
    }
    return token;
}
ThisClark
  • 14,352
  • 10
  • 69
  • 100
11

//length: defines the length of characters to express in the string

const rand=()=>Math.random(0).toString(36).substr(2);
const token=(length)=>(rand()+rand()+rand()+rand()).substr(0,length);

console.log(token(40));
//example1:  token(10) => result: tsywlmdqu6
//example2:  token(40) => result: m4vni14mtln2547gy54ksclhcv0dj6tp9fhs1k10
Jasp402
  • 402
  • 3
  • 12
7

Checkout crypto.js project. Its a collection of cryptographic algorithms. The project has separate js files for each hashing algorithms.

Josnidhin
  • 12,469
  • 9
  • 42
  • 61
4

It is very unlikely, but Math.random() could return 0.0. In that case, the solution of pimvdb would return "" (empty string). So, here is another solution, which returns in every case a random base36 with 10 chars length:

function generateToken() {
    return Math.floor(1000000000000000 + Math.random() * 9000000000000000)
          .toString(36).substr(0, 10)
}
shaack
  • 171
  • 8