Call another API from already authenticated API

What is the recommended approach of authentication when calling one service from another service (both with end-points authenticated from Auth0)?

In a little more details. We have created a few services with REST end-points that uses Auth0 for authentication. An end-point is either called with a JWT bearer token when authenticated from our web app or with basic authentication when called by a third party. In the latter case the third party is given a client ID and secret and these are delivered in a basic authentication header and our app then authenticates against Auth0 to get a token (this is done as we don’t want our third parties to first get a token before calling). In some of our services we will need to call some of our other services. In this case we may forward the authentication header we just received. We can also decide to just let the service have its own client and obtain its own token. The former approach has the advantage that the information about the external caller will be available. In the latter approach we will know what service is calling, but will not have available information about the external caller, which shall probably in most cases be used for authorization. I hope there is a recommended approach for these scenarios.

In general, service to service scenarios should be handled by leveraging the client credentials grant so that the service itself could obtain an access token that would allow to call another service.

This approach has a distinct advantage over just forwarding the received credentials when the calling service has some sort of asynchronous processing. For example, if a user makes a request to a reporting service requesting a weekly report delivered by email, forwarding the received credential to other services that had to be called to collect data would work for the report delivered immediately, but next week even if the access token was stored (which could be a problem on his own) the call would most likely fail due to lack of a valid/non-expired token.

Another point in favor of going with client credentials would be that nothing stops you from still forwarding external caller information for further authorization. For example, User A calls Service X with an access token associated with the user itself. Since Service X needs to additionally call Service Y, it performs a client credentials grant to get an access token issued to the service itself. However, nothing stops Service X to include additional information in the request to Service Y stating that is performing a call on behalf of User A. In this scenario, Service Y would validate the client credentials access token to ensure that is being called by a trusted service; then, since it’s being called by a trusted service it would also trust the additional information stating that the call should be authorized as if coming from User A.

Finally, just have in mind that the above works really well in environments where all services are fully and equally trusted. In a partial trust environment you may not want to let a given service be able to state that a call is performed on behalf of a different entity because it could be abused. However, most of the situations fall under the full trust scenario where every service is under your control.