I have a series of microservices on GCP Cloud Run that are each hosting a federated Apollo GraphQL service. I then have one last container which is acting as a federated GraphQL gateway for the rest of the services.
This works fine when public access is enabled on the containers but I cannot get the gateway server to authenticate against the other two services.
I have tried using the Apollo RemoteGraphQLDataSource and implementing the willSendRequest method to set the neccessary headers.
I have also tried adding the cloud run invoker role to the service role that the gateway runs as.
const servicex = new RemoteGraphQLDataSource({
url: serviceurl,
willSendRequest({ request, context }) {
request.http.headers.set(
"Authorization",
"Bearer ${TOKEN}"
);
}
});
const gateway = new ApolloGateway({
serviceList: [
servicex
]
});
const { schema, executor } = await gateway.load();
const server = new ApolloServer({ schema, executor })
I expect the gateway server to be able to authenticate against the other microservices.
Cloud Run authorization requires an OAuth 2.0 Identity Token in your authorization: bearer TOKEN
HTTP header. A common mistake is to use an Access Token.
Unless you have specified a new service account in your deploy command, Cloud Run uses the Compute Engine Default Service Account as its identity. This means you need to specify the Service Account email address for the role/run.Invoker
.
When you authorize with OAuth for User Credentials, you can receive three tokens: Access Token, Refresh Token and Identity Token depending on what you have specified in the Scopes parameter. The Identity Token is what you use in your HTTP Authorization header.
When you authorize service-to-service using a service account identity, call the Cloud Run metadata server to create a token for you. This endpoint will return an Identity Token. Use the returned token in your HTTP Authorization header.
http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=<ususally-the-url-of-the-cloud-run-service-you-are-calling>
The returned token is a Signed JWT that you can decode. Typical base64 encoding of header.payload.signature. The payload contains the email address of the service account and this email address is what the Cloud Run Proxy uses for authorization.