Establishing Trust between Microservices using JWT

How JWTs can be used to establish trust between system components such as Microservices

Claes Jonsson

3 minute read

Introduction

In case you are unfamiliar with JWT (JSON Web Tokens) you can think of them as credentials you can use whenever a proxy or stand-in need to represent a user of any kind; human, another microservice or another system altogether. Besides the token itself, they can contain additional information that is cryptographically verifiable, meaning the information, whether is authorization claim, service request data or any other information, is secure against tampering.

In this post, the second in a series of posts about JWTs, I will present an example of how JWTs can be used to establish trust between microservices, allowing one microservice to verify the authenticy of a user, what authorizations a user has and the possibility to deliver request parameters other information between microservices in a secure way. We will be able to cryptographically verify that the information came from a trusted microservice and from which microservice it came and also verify that the information has not been tampered with. The first post introduced JWTs and surrounding topics.

The code for this article can be found here

Overview

You may know that JWTs are very useful for authorizing client requests to API endpoints, and if you have ever implemented such as solution, which is something of an industry best practice, you are already used to seeing an authorization request return an access token as well as a refresh token. This makes perfect sense and it is part of the envisioned JWT authorization flow. In this post we will instead consider the case of a microservice calling another microservice, where a microservice does not represent a user and so has no way of calling an authorization server to obtain access and refresh tokens using user credentials (and no, we won't be creating the dreaded “service user” that I've seen in far too many places). Instead we will take advantage of the public/private nature of RSA keys to uniquely identify and verify each microservice to other relevant microservices, for each request. This can then further be orchestrated using a hardened and trusted credentials service. In the next post in this series on JWTs, I will show an example how this can also be used in an event driven microservice system.

More here

Even more here

[overview images here]

 
docker-compose up -d


 
docker exec -t httpservice http http://clientservice/my-public-credentials


 
docker exec -it httpservice sh
/ # http http://clientservice/my-public-credentials
/ # http ...


 
HTTP/1.1 200 
...

{
    "keyId": "1dd88b71-86c1-4d02-8aa9-feb662d99097",
    "publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCY0x6HYkcs3jGHCz6XJoF3e1z-BqLZS_z2j5ME_vfO1OC1nlMv3P63n51fwEzG7BX8NKRfaR5sPF8meJ8_U5DhLG35Xt3hrYUH4diCugQgPIfpprI4i__J8IxWHWxbT_4eYfvSQDwzmlWanlh2TZfVfst3ZDw6URNRJWjujNOYqQIDAQAB"
}


 
public PublicCredentials refreshMyCredentials() {
    myKeyPair = RsaProvider.generateKeyPair(1024);
    keyId = UUID.randomUUID().toString();

    PublicCredentials publicCredentials = getMyPublicCredentials();

    // this microservice will trust itself
    addPublicCredentials(publicCredentials);

    return publicCredentials;
}


 
public PublicCredentials refreshMyCredentials() {
    myKeyPair = RsaProvider.generateKeyPair(1024);
    keyId = UUID.randomUUID().toString();

    PublicCredentials publicCredentials = getMyPublicCredentials();

    // this microservice will trust itself
    addPublicCredentials(publicCredentials);

    return publicCredentials;
}


comments powered by Disqus