This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Best Practices

How to contribute to the docs

1 - Versioning

Versioning

An API can be versioned in several ways, but this documentation is limited to the three most commonly used variants.

However, a correct implementation is indispensable in any way, since a later migration is usually associated with breaking changes and can thus render applications unusable!

Why is versioning needed?

Applications evolve, and so do their interfaces.

However, if an interface is used by other developers or applications, then you have to make sure that you don’t disrupt their operations when you evolve or generally change an API. Therefore, it is extremely important to develop a concept that makes it possible to handle changes in such a way that other applications do not crash abruptly.

The most common concept is multi versioning. This means that multiple versions of an API are available in parallel so that other development and applications can update to the latest version over time.

Such a multi versioning is usually implemented via the following three variants:

URI Path Versioning

With URI path versioning, the version is part of the URI.

> myapi.com/api/v1/tasks
> myapi.com/api/v2/tasks
> myapi.com/api/v3/tasks
> myapi.com/api/latest/tasks

This type of versioning is very easy to implement: in effect, each version is a separate endpoint. These multiple endpoints can be served either by a single application, or by multiple applications.

With multiple applications, the advantage is that each version is also independent of the runtime. So version 1 could be run with Java, and version 2 with .NET.

Another big advantage is that not only the operation but also the development is really isolated. If a certain period of time of an old version is exceeded, it can simply be switched off without interfering with the operation of the other versions.
This versioning is not only very simple, it is also very powerful and therefore very widely used.

The disadvantage of this versioning is that in the end a resource can have multiple URIs, since there are multiple API endpoints - and thus contradicts REST, in which each resource should have a unique URI.

However, this disadvantage is conceptually minimal and in most cases only theoretical.

HTTP Header Versioning

With header versioning, the server is told at the time of the request which version the client wants to work with against the API.

> Accept: Version=1
> myapi.com/api/tasks

Header versioning allows the URI to be decoupled with the version so that the URIs themselves also remain unique. This can be implemented either by the Accept header or by Content Negotation.

The big disadvantage of this variant is that it is very intransparent compared to URI versioning, and URL structure changes are extremely complex.
This versioning type has its advantages in certain scenarios when it is a very established and mature API. For growing APIs where restructuring can be expected, this causes frustrating problems among developers in most cases.

HTTP Query Parameter Versioning

With the HTTP query parameter, the desired version of the client is not sent via an opaque header field, but as a query parameter and thus immediately visible via the URI.

> myapi.com/api/tasks?version=1
> myapi.com/api/tasks?version=2
> myapi.com/api/tasks?version=latest

The disadvantages of this variant hardly differ from the header variant, but the dynamic query parameter also makes caching more complex.

Conclusion

  • API versioning is the practice of managing changes to your API.
  • For most APIs, versioning the URI path is the best practise solution.

2 - Security

A collection of client libraries to communicate with REST services.

Security should be done over HTTPS in all cases, among which there are generally three very widely used approaches: API-Key-based, Token-based or certificate-based APIs.

API Key-based Authentication

In API key authentication, an individual key is issued to the client, usually a string of alphanumeric characters. The length varies, but the longer the better.
The server receives the API key, which is usually located in the HTTP header. The key is then checked for validity with a key store - for example a DB. If the result is positive, the server responds with the corresponding request.

The advantage of this method is that it is very easy to implement and does not require any other services, only a database for matching. The disadvantage is that simplicity becomes a problem at the same time when it comes to more complex scenarios. Furthermore, a key loss is very problematic, because misuse can only be prevented by a complete blocking.

Token-based Authentication

With token-based authentication, it is common for the client to first obtain a token for authentication: the id_token. Usually, an extra authorization server is responsible for this.
With the id_token, the server now logs on to the Authorization Server and asks for a token for a specific API: the access_token.
The API can now be requested with the access token, whereby the API itself trusts the Authorization Server and thus also the token. There is no additional validation via a database.

The advantage of this method is that it is very powerful even for complex scenarios. It is also a very big advantage that the responsibility of creating the token takes place at a central location and is decoupled from the actual API resource server. The tokens also enable very fine-grained authorization options, for example through claims. Since a token has only a short lifespan, its loss is not quite as bad as with an API key, but is still problematic.

The downside is that this is a relatively complex scenario with multiple services, which itself must also be well organized to ensure token validity. Real-time validation of the tokens requires very many HTTP calls.

Nevertheless, due to the enormous advantages, this method is the recommended way, along with OpenID and OAuth2.

Docs: Implement authentication in .NET microservices and web applications

Certificate-based Authentication

In certificate-based APIs, both the server and the client have appropriate certificates to identify each other.
When the client connects, the server checks whether the client’s certificate is known and valid. If the result is positive, the connection is accepted and the client receives the response.

This method is rarely used on the Internet due to certificate handling, but it is certainly used for closed backend systems.

Docs: Configure certificate authentication in ASP.NET Core

About HTTPS

When it comes to security, special care must be taken to ensure that no information bypasses the HTTPS encryption. This means that all sensitive content must be transmitted either via HTTP headers or via the HTTP body. The query values are not part of the encryption and can be seen from any point in the data transmission despite HTTPS!

The header should always be used in authentication.

GET /articles HTTP/1.1
Authorization: Bearer S0VLU0UhIExFQ0tFUiEK

or

POST /articles HTTP/1.1
Authorization: API-Key S0VLU0UhIExFQ0tFUiEK

Similarly, it would be safe to transmit content through the body at certain endpoints where no other content is otherwise transmitted. This is also secure in HTTPS.

POST /authentication/reset HTTP/1.1
{
    "API-Key" : "S0VLU0UhIExFQ0tFUiEK"
}

Never transfer sensitive data with the query!