Dangers of using your own HTTP authentication scheme
HTTP provides some authentication schemes like: Basic, Bearer, Digest, HOBA, Mutual, Negotiate, OAuth, etc. As described in the RFC.
There is no need to reinvent the wheel. If you want to protect an HTTP comunication, you should start with something built on top of these.
Some reasons to not promote the use of a custom authentication scheme:
It’s not standardized. This will make that anyone who wants to use it, will have to understand what have you created and how to use it.
Less documentation.
There will be less people using it, so there will be less information about errors in the internet.
Is less safe.
Has more errors rate and incopatibilities with existing systems.
Real example
This is a real case that made some poeple lost some time wondering what were going on.
In this case, we were connecting to Clickatell’s One API with an HttpClient instance in netcore.
As you can see in the documentation, the specification of the Authorization HTTP header is an api-key scheme, and looks like this:
Authorization: JihURVNUMjMm==
1. Invalid syntax
As you can see, this expresion don’t follow the convention syntax of Authorization header:
Authorization: <type> <credentials>
If you not specify the scheme, you cannot use something like the comon way of setting Authorization schemes in an HTTPClient:
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("api-key", "JihURVNUMjMm==");
This will throws an exception.
2. Invalid scheme
Notice that “api-key” is not an specified scheme in the RFCS. The “Api Key” format is a common way to call a single value in the Authorization header. You can see this convention in applications like Postman:
Once we noticed this, we decided to set the Authorization header manually. This makes the code chages a little:
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Authorization", "JihURVNUMjMm==");
Or if you want, you can set it directly in an HttpRequestMessage:
HttpRequestMessage request = new HttpRequestMessage();
request.Headers.Add("Authorization", "JihURVNUMjMm==");
But, this still throws and exception.
3. Invalid token validation
As we allready know, HttpClient implementation follow the RFCS and the standards. This means that by default, Authorization header is validated.
Token “JihURVNUMjMm==” don’t follow “type credentials” format. But not only that, you can se that the token ends with “==”. This usually means that the token is a result of a hashed string, probally in base64. The problem here is that “=” is not a characted alowed by default as a part of a token.
The developer decision to use base64, and to specify any scheme generates us an exception.
To solve this problem, we had to adapt the code in order to skip te token validation with:
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "JihURVNUMjMm==");
You can read more about this topic here.
Finally, as a result of this, we get a more complex code, harder to understand for newcomers and more harder to create than it seems.
As a general rule, don’t reinvent the wheel.