1

I am developing a sign-up system where the users can create a random string by just hitting a button.

They can then send this string to a non-user so s/he can use it to sign-up. The new user inserts a username and a password of his/hers choice and the string s/he received.

To implement this scenario, I am looking for a javascript function that can create a random string. You can feed a string to the function and can recognize if it created it or not -throws an error.

Any tips for creating such a system and where can I find such a function?

Thanks

Edit

This is a closed group of back-end users. I am already a member. I can create a string and send to my friend Jake by e-mail, skype, fb chat, whatever. I tell him, "put whatever username/password you want, but put the code I send you to the 'Your Code' field of the signup form, otherwise the system wont let you sign up". After Jake signs up, the string is no longer useful, because Jake created his own password and that is used by the system for identification. That's the scenario.

I insist on Javascript because I am going to use node.js/express.js , so I guess whatever I make , it have to be written in Javascript.

I guess I could use something like the javascript version of php b-crypt if this exists. Or not. I dont even know how to begin, so any guidelines would be useful. Thanks

jonny
  • 3,022
  • 1
  • 17
  • 30
slevin
  • 4,166
  • 20
  • 69
  • 129
  • tip: start up a code editor and start writing code. where to find this function? look in your code editor after you're done writing code... – Marc B Sep 11 '15 at 16:36
  • @MarcB Sorry, I dont get you. I am just looking for a function – slevin Sep 11 '15 at 16:37
  • 1
    `Math.random().toString(36).slice(2)` and also `crypto.getRandomValues` – dandavis Sep 11 '15 at 16:37
  • 2
    Also, not sure how you will save these random strings? And, are there any rules - string length, characters (any, or limited number of characters)....? http://stackoverflow.com/questions/1349404/generate-a-string-of-5-random-characters-in-javascript i have feel that creation of random string is smallest problem in this concept.... :) – sinisake Sep 11 '15 at 16:38
  • 2
    It sounds like you need two functions. One that creates a random string, this is simple. And a second that determines if a random string was generated by your previous function, this is harder and not possible strictly in javascript. Functions cannot store state, you need a database on the back end to store created strings. – Matt R Sep 11 '15 at 16:39
  • @MattR credit card numbers can be checked for validity, OP might think about some check like this – Hacketo Sep 11 '15 at 16:40
  • @Hacketo, this is true, but it depends on whether he wants to guarantee that only authentic users can generate a key or not. Most functions like that will be easily gamed. – Matt R Sep 11 '15 at 16:46
  • 1
    The "you can feed a string to the function and can recognize if it created it or not" doesn't sound safe for your application. – Arnelle Balane Sep 11 '15 at 16:47
  • @nevermind See my edit, I added info. Please explain the problems you see. Thanks – slevin Sep 11 '15 at 16:58
  • @MattR Can you please help me and be more specific ? I added more info in my OP. Thanks – slevin Sep 11 '15 at 16:59
  • @ArnelleBalane So what do you suggest? I Added more info to my OP. Thanks – slevin Sep 11 '15 at 17:00
  • 1
    I've got a pretty comprehensive solution on the way. Wait a couple minutes and i'll post it :) – jonny Sep 11 '15 at 18:01
  • 1
    @slevin I'd suggest persisting the generated codes into a database or some form of storage to make sure that a code inputted by a new user was really generated by an existing user, and not just randomly made up by a user. – Arnelle Balane Sep 11 '15 at 18:16

1 Answers1

2

Okay, since you've specified you'd like to use express, here's something like a solution to your problem.

Firstly, you wanted a way of generating a random string which could be identifiable by the function that created it - which is impossible. Instead, you need the node application to remember the strings that have been generated by this function. You can go about this a number of ways but here is the process I will be outlining:

  • You create a simple express API with a couple of routes: /generate, and /register.

  • requesting the /generate URL generates a random string on the server, stores that string in an active codes array on the server, and then returns that string.

  • The /register route will have two parts: the GET path will return an HTML form that your friend will have to fill in with his code (which you have emailed), his new username, and his new password. The POST path will send this data to the server, and check his code with the codes stored in the active codes array. If his code matches one of the codes in the array, this creates a user with the credentials they entered in the HTML form (otherwise it returns an error, something like invalid code error).

  • Preferably, you'd want to create an HTML page for requesting the /generate URL. This would include a button that attaches a function onclick that makes an XMLHttpRequest asynchronously to this URL. It then displays the returned code in a <p> tag (or whatever floats your boat).

  • Naturally you'd also be required to create an HTML form at the /register route, for the friend to register his new account using the code you emailed.

  • You'll need some kind of database to store your user credentials. It could be something as simple as a .json file, or a more sophisticated NOSQL database. I won't go into the details of implementing this, but a number of great resources exist out there for whichever implementation you go with.

Here is a basic outline for the code you'd write:

routes/index.js - this would be in your express app

var activeKeys = [];

router.get("/", function(req, res) {
    var options = {
        root: __dirname + '/public/',
        dotfiles: 'deny',
        headers: {
            'sent-timestamp': Date.now()
        }
    };

    res.sendFile("index.html", options, function (err) {
        if (err) {
            console.log(err);
            res.status(err.status).end();
        }
        else {
            return;
        }
    });
});

router.get("/generate", function(req, res) {
    require('crypto').randomBytes(48, function(ex, buf) {
        var token = buf.toString('hex');
        activeKeys.push(token);
        res.send(token);
        return;
    });
});

router.get("/register", function(req, res) {    
    var options = {
        root: __dirname + '/public/',
        dotfiles: 'deny',
        headers: {
            'sent-timestamp': Date.now()
        }
    };

    res.sendFile("register.html", options, function (err) {
        if (err) {
            console.log(err);
            res.status(err.status).end();
        }
        else {
            return;
        }
    });
});

router.post("/register", function(req, res) {
    var validKey = keys.indexOf(req.body.code);
    if (validKey < 0) {
        res.send("invalid code error");
    }
    else {
        //here you would implement adding your newly created user to the database,
        //and then sending a success response
    }
});

public/index.html - default route, where the user

<button id="generate">Generate Key</button>
<p>Mail this to your friend!</p><p id="key"></p>
<script>
    document.getElementById("generate").addEventListener("click", function(e) {
        var xhr = new XMLHttpRequest();
        xhr.addEventListener("load", function() {
          document.getElementById("key").innerHTML(this.responseText);
        });
        xhr.open("GET", "http://www.example.com/generate", true);
        xhr.send();
    });
</script>

public/register.html - your friend registers his new account here

<form method="post" action="/generate">
    <input placeholder="your code" name="code" type="text"></input>
    <input placeholder="username" name="username" type="text"></input>
    <input placeholder="password" name="password" type="password"></input>
    <input placeholder="confirm" name="confirm" type="password"></input>
</form>

That should just about suit your needs.

PLEASE NOTE: I haven't tested any of this code, so don't expect to copy + paste and for it to work. This is meant only as a guideline

Hope this helps!

jonny
  • 3,022
  • 1
  • 17
  • 30
  • Man, I cannot thank you enough. This is an awesome well-written and well-organized answer. I will start implementing and let you know – slevin Sep 12 '15 at 09:44
  • 1
    @slevin no problem. One immediate mistake I see I've made is with the `indexOf` function - I should be checking that it's not -1 rather than whether it's true. let me know if you have any questions and I'll be happy to help :) – jonny Sep 12 '15 at 10:06
  • @slevin Another mistake, at the */register* route's POST method, `req.body.key` should in fact be `req.body.code`, i.e. the `name` attribute of the `` tag being posted in the request to */register*. Edited the post :) – jonny Sep 12 '15 at 19:46