The Tyranny of Best Practice

T

All architects know what’s best practice, but only good architects know when to use them.

I’ve been in plenty conversations where someone goes “we should do X because it’s best practice” — and act that the discussion ended.

Best practice is what works for most people, most of the time. It isn’t something that works for everyone all of the time — otherwise we would mandate it across the board and architects would be out of their jobs.

What is best for a multi-billion dollar bank, is not what is best for a small startup with 4 employees straight out of college — and vice-versa.

It’s true that if you don’t know what you’re doing, blindly following best practice might put you in a better situation that not. But even just a little thought into whether a best practice is applicable to your use-case goes a long way.

Sometimes trying to chase the ‘best’ actually takes time away for useful work. Be careful not to chase best practice too far down the rabbit hole — you might end up with a great architecture but no useful features.

Take for example a Rubiks Cube. There are algorithms to solve a cube, and regardless of how scrambled the cube is, the algorithm will solve it to perfection. You will reach the solved state by blindly applying the algorithm regardless of how the cube starts out.

But life isn’t like a Rubiks Cube — not everyone starts off at the same place, and wants to go to the same destination. Plus, the cube applies no constraints, it does not involve trade-offs, it’s just a fun puzzle that is always solveable.

Life is more like Chess.

In Chess, everyone may start at the same place, but the game very quickly descends into some new permutation you’ve never seen before. And unlike the Rubiks Cube, there is no one set algorithm that determines success. Every move has a trade-off, and every move invites your opponent to do respond in some unpredictable way.

So in Chess, we don’t have algorithms. We have principles.

Principles like Knights before Bishops, or Don’t move the same piece twice. And learning these principles will make you a better chess player — but the good players (and certainly the great ones) know when to ignore the principles. Blindly following principles will actually make you a poor player — you will not win a single Game of chess if you stick to all the principles. If you want to win, you have to break the principles — and more importantly know when to break them.

And you can’t break the Principles unless you know why they’re there in the first place. Which brings us back to the ‘best practice’. Do not listen to anyone spouting best practice, if they cannot backup their claim for why it is best practice — and ‘the spec says so’ is not a good answer.

Know why a standard is there, know when it is applicable, and then decide if it makes sense based on your context.

Working Example

The best example of this is the Access Token vs. ID token debate for oAuth and OIDC. The oAuth spec says very clearly:

ID tokens should never be sent to an API.

https://oauth.net/id-tokens-vs-access-tokens/

So here the best practice is to use Access Tokens to access an API.

Cool. Got it.

But Access tokens don’t have user identity, and it’s much easier to just send the ID token with the user identity, and so many people do. But of course, you have the chorus of people who will tell you that access tokens are “following the spec” and ID tokens will introduce issues — and those same people won’t be able to articulate their point any further, other than some arcane specifications or edge cases that don’t apply to you.

Now there’s a lot of developers out there who are trying to do the right thing, but are confused, they can’t see any reason why an access token would be preferred over an ID token? See here, here, here and here …. and here and here and here… and here.

Then there are people who go to projects like Kubernetes and oauth2-proxy and ask them “hey why do you use ID tokens instead of access tokens when the spec says otherwise” … and the standard answer back is “Defacto standards vs standards written“. Defacto standards are what people build applications with, standards written are what people build powerpoint slides for — pick the right standard for your use-case.

So let’s understand why the best practice is there — but before that we need to understand what is the objective of OAuth:

The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, …

https://datatracker.ietf.org/doc/html/rfc6749

Ah, so here we understand OAuth is for interaction between 3rd-parties, but I’m building my own application for my own users. 90% of people are building first-party apps that in theory don’t need a protocol whose stated objective is 3rd-party delegation with limited access.

So really if we’re building a first-party application where the “resource server” and the “client application” are the same thing, we don’t need to follow a spec of something that has a different objective than us. Of course if they were different, there would be a case for access tokens, but not in our context. We need to dive deeper.

What is the difference between an Access Token and ID Token?

  • The Access Token has a Scopes, but not Identity information
  • The ID token has Identity information but not scopes.

And if we don’t need scopes, because in a first-party scenario, users will have complete access to all of their data anyway.

But we need identity, because when a requests hits an API we need to understand which user this belongs to. It’s much easier to use ID Tokens than it is to use Access Tokens to get those …. so……

We’ll just use ID Tokens. It make sense, it’s generally cheaper and easier to implement, and as far as we can tell introduces no security risk.

And maybe this decision isn’t correct, that I missed out something critical. But if there were something so critical, it would be better articulated in the reasons for using access tokens. Good architects must be bold enough to take risk, but still remain humble enough to accept that they are wrong. A lot of us suffer for analysis paralysis because we’re afraid to give advice that breaks the ‘norms’ — it’s much safer just recommending best practice.

And like I said, all architects can recommend best practice.

But the good ones know when not too.

Add comment

Astound us with your intelligence