Generating Cryptographic Random State in JavaScript (in the Browser)

Daz
2 min readNov 2, 2017

I need to generate some random state for an OAuth2 implicit flow for a JavaScript SPA. This “state” is passed to the identity provider, and then passed back after authentication to guard against XSS. Basically, I just need a string of random characters.

This state parameter is optional in OAuth2 implicit flow, and it only needs to be pseudo-random, but authentication isn’t something I like to take chances with, so I thought I’d look for the best option. I did a quick web search, as this seemed like the kind of thing that I’d find a perfect, best-practise, solution for on stack overflow, GitHub or similar. But, I had a few issues with the solutions I found:

  1. They used the crypto library from node, so were server-side solutions not intended for the browser, or,
  2. They used Math.random which I decided wasn’t suitable and I wanted to use the Javascript Cryptography API, or,
  3. They had nested loops and conditionals, which were either inefficient, or not declarative enough for my programming style, or,
  4. They produced a byte-string that didn’t encode easily in a URL.

Here was one of the implementations I liked, from an Angular OAuth2 library:

I liked the use of “possible” chars, but it uses Math.random() and I wanted to use getRandomValues() from the Cryptography API. I tried a couple of simple looking approaches to converting the bytes returned from getRandomValues but decided to combine it with the “possible” chars approach, and ended up with this:

The MDN docs for the Cryptography API states that:

To guarantee enough performance, implementations are not using a truly random number generator, but they are using a pseudo-random number generator seeded with a value with enough entropy. The PRNG used differs from one implementation to the other but is suitable for cryptographic usages. Implementations are also required to use a seed with enough entropy, like a system-level entropy source.

The 40 character strings that are produced by this code should be random enough, performance is OK, and they encode easily into an URL for submitting to the identify provider as part of an OAuth2 implicit flow.

--

--

Daz

Geocities Developer Expert. Keywords: Angular, TypeScript, JavaScript, Cyril Live Coding, Functional Programming