I\'ve created a Rest API based on the PHP Slim framework which uses JSON Web Tokens (JWT) to authenticate and authorize access.
To use the API the client must first
The cryptographic algorithms that can be used to generate the Message Authentication Code (MAC) or the digital signature are listed in RFC 7518.
In the entire list of algorithms, the only one that is "required" to be implemented by a compliant implementation is HMAC using SHA256 (HS256). HS256 requires a private secret for signing the token as well as validating the token. If you are using HS256, ideally you should not share the secret among all the servers. Instead both the signing and tge validation logic will remain in the "authorization server" (OAuth2 terminology). Individual "resource servers" (again OAuth2 terminology) would invoke a service in authorization server to validate the token. However, it may not be practical to call the authorization server token validation api for each api call. Therefore, it maybe a good idea for the resource servers to cache the JWTs and simply compare the JWT in the incoming requests with the cached list of JWTs. If the incoming JWT is not present in the cache, only then the authorization server validation functionality will be invoked. This ensures the secret signing key doesn't need to be shared and the remote authorization server validation function is also not invoked for each api call.
The two other recomnended algorithms in the RFC are "RSASSA-PKCS1-v1_5 using SHA-256" and "ECDSA using P-256 and SHA-256" (ES256), where the later (ECDSA) is likely to be also made "required" in future.
If you use ES256, you'd keep the private key with the authorization server for signing the tokens and share tge public key across all the resource servers so the each resource server can validate the signature using the public key. This definitely saves the resource servers from making authorization server call for validation at the cost of increased computation and without having to share the secret with every resource server.
It is better to sign JWT using private/public key (RSA or ECDSA algorithm) instead of a secret (HMAC algorithm). In that case your auth service would sign JWT with private key and other APIs would validate JWT with public key, well... you still need to distribute a public key to your APIs then, but you have options.
Depends on your architecture, you might look at:
API Gateway pattern
For microservice architecture a good practice is to use API Gateway pattern. More about gateway pattern. API Gateway can validate JWT token and then proxy requests to your services. So auth service would sign JWT token with private key, then requests to APIs would go though API Gateway. API Gateway would validate token with public key, so you would not distribute public key to all APIs behind the proxy.
With this approach your would need an API Gateway, you can look at: express-gateway, kong + jwt plugin, tyk etc, also there is much more benefits from API Gateway rather then just JWT token validation, like traffic control, analytics, logging, requests and responses transformations and so on.
Secrets management
Instead of or additionally to API Gateway you can take a look at centralised secrets management systems, like Hashi Vault. Depends on the project/team size it could be an overkill for your project.