Security between microservices - Which protocol ?

Secure communication is one of the most important aspect of modern development, and this is even more true for microservices.

Indeed, as we are splitting our good old monolith application, we are creating much more interfaces (mostly using HTTP). So we need a security protocol that best meets our architecture needs.

Here a list of standard security protocols with their advantages and drawbacks.

Basic Authentication

The quickest way and also the less secure. Username and password (base64 encoded) are sent in Authorization HTTP header.
Pros:
  • easy to use
Cons:
  • credentials are sent on each request without encryption
  • recipient must have username/password on its side

White listing

One of the most common security method which depends of your infrastructure (firewall, gateway, container orchestrator,...). The calling system ip is known and white listed at the network level.

While being easy to implement, this method is not very flexible. The ip can changed and if you use a Cloud services platform, it can be hard to get a fix ip. Moreover, you cannot apply fine-grained authorizations.

Pros:
  • easy to use
Cons:
  • depends of your infrastructure
  • not flexible
  • hard to use on Cloud platform
  • no fine-grained authorizations

HMAC (Hash-based messaging code)

Sign the request with a private key which is shared by the client and the server. The server uses the same key to hash the request and compare the signature of the incoming request.
Pros:
  • private key not sent in the request
Cons:
  • each part must have the private key (how send the key securely, how manage the revokation if the key is compromised)

Client certificate

Use TLS (with X.509 certificate) on the client side. Besides the regular asymetric key exchange done in TLS (eg. HTTPS) to secure communication between the client and the server, this protocol adds an additionnal layer (with a client certificate) to authenticate the client on the server side
Pros:
  • highly secure
  • private key is never sent
Cons:
  • can be onerous as we have to generate a certificate for each client
  • hard to maintain all certificates (expiration)
  • hard to implement

API Key

A key is generated by the server for a specific client, the latter has to put it in a HTTP header (eg. x-api-key) when it send a request. API key are not really use for strong authentication but mainly to identify which system is calling us. It is often use for read-only operation and to apply rate limiting or quota. This protocol is often use for public API along with physical user authentication (eg OpenId/Authorization Code Flow).
Pros:
  • easy to use
  • easy to revoke
Cons:
  • has to be coupled with strong authentication protocol for write operation

OAuth2 Client credentials flow

This protocol uses a third-party system called Authorization Server to manages sensitive data (secrets) and authorizations.

The application has to be registered in the Authorization server to get credentials and request an access token. Then, this token is put in the Authorization HTTP header when sending a request to the server (called a Resource Server in the protocol).

The token is most of the time a JWT (JSon Web Token) and contains information about the calling system but no sensitive data. The token authenticity is ensured by its signature and validated against the Authorization Server public key.

Pros:
  • secret is never sent to the server
  • token has a limited duration
  • authorizations can be applied against token claims
  • easy to revoke an access
Cons:
  • a third-party system is mandatory
OAuth2 has different flows for specific authentication scenarios (Authorization code, Implicit, ...). But here we 're addressing system to system authentication, so the flow is Client Credentials.

Which one ?

Among all these protocols, the most suitable in a microservices ecosystem is the OAuth2 Client Credentials flow as it gives both a strong authentication and flexibility.

When the number of services increases, it can be tedious to manage accesses for each one and the use of an Authorization server (or Access management) becomes mandatory. It allows to configure authorizations in a third-party system.

Here the workflow of the OAuth2 Client Credentials flow:

As you can see, Authorization server issues the credentials for a given system (a client id and a client secret) and manages authorizations.

The token is self sufficient and the recipient doesn't need to have secret or key to authenticate the caller. The Stock service knows that the token is coming from the Authorization server due to its signature. This one is validate against a public key (step 0).

Here a list a Authorization server solutions if you want to implement this protocol:

  • Keycloak (Free and Open Source, RedHat)
  • Auth0 (Saas)
  • Microsoft Azure Ad
  • Okta
  • AWS Cognito

Conclusion

In a microservices architecture, the number of endpoints can increase quickly. A flexible authentication mechanism must be used if you don't want to fall in the access management nightmare.

OAuth2 Client credentials has the benefit of coupling both strong authentication and flexibility even if it involves a third-party system.