I have two services (APIs) deployed on GCP Cloud Run. Call them service-one.myDomain.com
and service-two.myDomain.com
. I would like service-one to be authenticated in calling service-two independently of what any user is doing.
I've read and implemented the instructions from GCP Cloud Run docs on Authenticating service-to-service (https://cloud.google.com/run/docs/authenticating/service-to-service) but service-one.myDomain.com
is unsuccessful in calling service-two.myDomain.com
receiving a 401:Unauthorized response.
Any thoughts on how to get service-one
to successfully call service-two
?
On google IAM, I created two service accounts and granted them both the "Cloud Run Invoker" (roles/run.invoker
) role:
[email protected]
[email protected]
Inside Cloud Run I changed the service account from the "Default compute service account" to the service accounts I created. I assigned [email protected]
for service-one.myDomain.com
and [email protected]
for service-two.myDomain.com
In service-one.myDomain.com
I make a call to the metadata server to get a token (jwt) from the following url:
http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://service-two.myDomain.com
with a request header set as {'Metadata-Flavor': 'Google'}
The request is successful and the token I receive is decoded to have the following payload:
{
"alg": "RS256",
"kid": "9cef5340642b157fa8a4f0d874fe7543872d82db",
"typ": "JWT"
}
{
"aud": "https://service-two.mydomain.com",
"azp": "100959068407876085761",
"email": "[email protected]",
"email_verified": true,
"exp": 1572806540,
"iat": 1572802940,
"iss": "https://accounts.google.com",
"sub": "100953168404568085761"
}
Using the token I make a request from service-one.myDomain.com
to an http endpoint on service-two.myDomain.com
. I set the request header with {'Authorization': 'Bearer {token}'}
({token}
is value of token).
The response is a 401 Unauthorized and my logs show the response headers to include:
{'WWW-Authenticate': 'Bearer error="invalid_token" error_description="The access token could not be verified"'}
With a content of:
"
<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>401 Unauthorized</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Unauthorized</h1>
<h2>Your client does not have permission to the requested URL <code>/health</code>.</h2>
<h2></h2>
</body></html>
"
I'm stumped.... any ideas on what I'm missing to get service-one
to authenticate to service-two
?
The answer was to use the gcp cloud run generated Url as the audience in the OIDC token request. And relatedly the "aud" field in the jwt.
My discovery was that Service-to-Service authentication in cloud run does not support custom domains (myDomain.com). I was using my custom domain.
(I feel like a bonehead) thanks @guillaumeblaquiere
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With