Why we don't put certain data in the URL
First of all, one big reason not to include certain data in the URL is because (1) URLs are saved in your browsing history, which makes it much easier to get your data with just your history (cookies are usually changed as you use your web applications and request data is usually not saved), and (2) URLs aren't protected by HTTPS, which is used to encrypt your data as you browse (the URL is encrypted by HTTPS). This simply means The URL is much more easily captured by anyone.
Making access tokens safe from enumeration
Your users will have some control over the data they're sending to your server. They can be legitimate users, editing their cookies, headers, and other data either directly in the browser (Chrome/Firefox developer console) or using a proxy (Burp Suite, zaproxy, etc.). This means they can see and manipulate the user_id=3
in the requests.
We should not use incremental values for user IDs. Instead, we use a unique and randomly generated ID for every user. For example, if I sign up with the email JohnDoe@example.com
, and the next person signs up with Alice@company.com
, we should each have unique IDs with no clear relation to our email or sign up order. If I see user_id=10
in a query, I will try changing it to user_id=11
and so on. However, seeing id=MTExIC1uCg==
will make it look more random and harder to crack (at least until you notice it's base64-encoded, which is not encryption). If I see a totally random & long string (e.g. pE5Y9G7HqNHe3bUq7Scz
) as the user ID, I will consider it safe from enumeration since I most likely can't grant me access to another account by simply changing a character and, unless I'm into cryptanalysis, move on.
Make sure your access tokens are unique
Using salted hashes is nice and all, but there's the possibility of hash collisions, where 2 different salted passwords generate the same hash, in which case you'll have to find a way to resolve such cases, however unlikely they are. It's not a good day when I login and someone get access to some random user's account.
For this, you can do what YouTube does and generate a random & unique ID for every user in just a few steps
1. Generate a random value
2. value already exists -> go to step 1
3. Value is unique -> use value as ID
Of course, you have to use a Cryptographically secure pseudorandom number generator (CSPRNG) for generating the random IDs so that people can't analyze existing keys and guess valid keys.