In OAuth, or any other protocol where the token can be opaque or transparent, the benefits and risks swing based on what your desired result is:
- If you want the client to be able to parse the access token, you need the token to be transparent.
- If you don't want the client to be able to parse the access token, you need the token to be opaque.
Indeed, this is the definition of opaque and transparent tokens; the client can see into them, or not.
If your token is transparent, you must sign it, otherwise, anyone could simply edit your token contents, and claim anything they want.
So, the first obvious benefit of having an opaque token is that you can just throw away any signing mechanism; you don't need it, and conversely, if you have a proper transparent token, the client can read the token, but not edit it.
Another benefit of having an opaque token is it is more secure; No encryption method is truly random (i.e., there must be a way to decrypt it), meaning you can always tell which encryption protocol is used if you can read enough of the contents of the tokens (transparent tokens). This itself reduces the time to identify your cipher (knowing the protocol). Many people don't think this is very risky, and indeed, if you use more than 80 bits of entropy, they are right (10 truly random characters for your cipher, i.e. "secret key").
However, and this is much more of a risk; transparent tokens allow crackers to play with the contents (because they see them), and some protocols have serious weaknesses that allow you to create collisions or even decode the cipher in a much shorter period because the cracker will know the protocol as well as the contents of valid blocks (most encryption protocols use 16 byte-long blocks, so if your token contains 160 chars of data, you've given the cracker 10 valid combinations to your cipher. This decreases the time it will take for them to identify your cipher by an order of magnitude. Giving them more transparent tokens will further reduce this time as well. Some protocols have a reduced version of this risk, but by the nature of what encoding is, having the encoded block, and decoded block both in your hands, you're always going to make it easier to break.
This is why many choose opaque tokens. Indeed you should always opt for opaque tokens if there is no need for any external entity to be able to parse your token. An example of this is a service framework in which you only pass the token to the service as a blind claim; you have no idea what it says, but you know it works and identifies you. It is only up to the service to confirm it's you via the secret key or cipher.
Opaque tokens also don't require signing, which I mentioned above, they also don't require divulging anything about chosen protocols.
For this reason, they are much more secure, not only mathematically and logically, but get rid of human implementation errors, which is, to be honest, 99% of the reason cracks are ever made in the first place.
Should I use opaque or transparent when implementing X?
OAuth electing opaque tokens when logical was done to just raise the bar for hacking it. However, if you want to implement something custom, Opaque v. transparent isn't the question you should be asking.
Doing it yourself is actually the more lazy approach; the hackable approach.
Of course this is up to you, but a better question to ask is "should I use custom or existing?". Statistically, nearly all hacks are made in the implementation, not the underlying tech; i.e. SQL injection still works today not because this isn't solved, but because people implement their services on their own, thinking "custom is more secure". This thinking is certainly false, because in 2024, SQL injection still is one of the leading causes of information theft; and in nearly all cases, the architect thought "I'll do this custom, so hackers won't know to attack library X".
Those are literally famous last words.
When choosing opaque v. transparent, it is much better to choose an existing tech. JWT, a transparent token, is 100% secure for all intents and purposes; the flaws are in implementation; i.e. the length of your secret, and how much entropy is contained in it.
If your JWT gets hacked, it's because of something unavoidable like MITM, or your secret wasn't secure; i.e. this is all implementation; it has nothing to do with the transparency.
Electing opaque over transparent simply because it's technically more secure is like locking your inside doors for the same reason; you make your life a lot harder and limit your abilities all in the name of security. And if one day you leave your window open to air out your bedroom... HACKED, and all your internal door locking was pointless suffering.
Don't do that.
Accepted methods > human behavior
When considering custom v. existing, think in the same terms of building a door and lock yourself, vs buying one; Sure, someone can look up hacks for your brand of lock, but hopefully you stayed up to date on updates. Alternatively, if you built it yourself, chances are, they can just "try human method x", because you are human, and be done, because humans generally make the same mistakes when they do things custom. This is much, much, much worse.