Decoding raw URL-encoded cookie in JavaScript

1k Views Asked by At

I generate session cookies in PHP using

$cookie = random_bytes(64);

then set the value of this variable as a cookie:

setcookie('access', $cookie, time()+31536000, '/', false);

When I look for the desired value using

function getAccessToken(){
    var n = document.cookie.match(/access=([^;]+)(?:$|;)/i);
    if (n && n.length)
        return n[1];
}

on the client side, I get

"%1D%D8%E1%3F%7E%3E%D7b%A5%04%3Bl%3A%ADB%DF%DAg%E5%1DH%0A%21%5E%15%D9%2Be8k%3A%E2%AF%CE7%F2%BF%5B%CB%14%95%CEO%28%60p%DF%FBeY%95%3C%86%B99U%B7%F1p%E0%AC%2B%C5%2F"

This value is being sent to a Node.js websocket server to authenticate the user, but since the value is already wrong at the client side, the connection fails. When PHP receives this cookie, it is automatically decoded, and $_COOKIE['access'] correctly contains

��?~>�b�;l:�B��g�H
!^�+e8k:���7��[���O(`p��eY�<��9U��p��+�/

Everywhere I looked I was told to use decodeURI / decodeURIComponent and escape, but the first throws URIError: URI malformed and the second doesn't help me the slightest.

How can I turn this raw URL-encoded string into a string of actual characters/bytes on either the client OR Node.js (doesn't matter which side does the decoding)?

2

There are 2 best solutions below

0
SeinopSys On BEST ANSWER

Based on @BlackBurn027's comment, all I did was add an extra bin2hex step before setting the cookie value:

$cookie = bin2hex(random_bytes(64));

This produces a string that both languages can easily understand without issues.

0
matiaslauriti On

The problem is that you are randomly generating bytes, so if you try to "decode" them, there will be not ASCII characters, so you will see that "?" sign and more random letters like other languages letters (japanese, russian for example)...

The best way is to create a function that you for sure know that will return A-Z, a-z, 0-9 and special characters like "!?=$#" or any you allow.

So, what I usually do is to get the phpsession id and do MD5 on it, then get a random part of the MD5 (never entire string) and do other MD5, then sum anything, current year + month + date, or any random number o whatever you want. Then other MD5... Do you get it ?

Tell me if this answered your question !