Reputation: 952
I am trying to set up service to service authentication so an external application can make requests to a Cloud Run application (behind a Cloud Endpoints API gateway).
I have followed the Cloud Endpoints authentication between services documentation, however I continue to receive the following error when trying to reach the Cloud Run service:
401: Jwt issuer is not configured
Within the openapi spec, I have setup endpoint security and securityDefinition:
/endpoint_1:
get:
...
security:
- service_account: []
securityDefinitions:
service_account:
authorizationUrl: ""
flow: "implicit"
type: "oauth2"
x-google-issuer: "<service_account_email>"
x-google-jwks_uri: "https://www.googleapis.com/robot/v1/metadata/x509/<service_account_email>"
x-google-audiences: "https://<cloud-run-service>-pjcfvhz2qq-uc.a.run.app"
This was then deployed to Cloud Run using ESPv2 Beta as described the Cloud Endpoints documentation.
After everything is deployed, I am trying to run the following script from my local machine to generate a signed jwt and make a request to the Cloud Run service:
import os
import json
import time
import requests
import google.auth.crypt
import google.auth.jwt
now = int(time.time())
expiry_length = 3600
sa_email = '<service_account_email>'
payload = {
'iat': now,
'exp': now + expiry_length,
'iss': sa_email,
'sub': sa_email,
'email': sa_email,
'aud': 'https://<cloud-run-service>-pjcfvhz2qq-uc.a.run.app',
}
file_path = "service-account.json"
signer = google.auth.crypt.RSASigner.from_service_account_file(file_path)
signed_jwt = google.auth.jwt.encode(signer, payload)
headers = {
'Authorization': 'Bearer {}'.format(signed_jwt.decode('utf-8')),
'content-type': 'application/json',
}
url = "https://<cloud-run-service>-pjcfvhz2qq-uc.a.run.app/endpoint_1"
res = requests.get(url, headers=headers)
print(res.json())
response of the get request:
{'message': 'Jwt issuer is not configured', 'code': 401}
The issuer has been specified on the openapi spec as the service account email which matches the issuer used with generating the JWT.
Any guidance on what Jwt issuer is not configured actually means, is appreciated.
Upvotes: 3
Views: 14606
Reputation: 145
Did you deploy ESPv2 Cloud-Run service with the flag "--allow-unauthenticated"? If no, the ESPv2 cloud-run service is protected by IAM server, it will verify the JWT token and pass in a new token to ESPv2. ESPv2 will not recognize its issuer from the new token.
In order for ESPv2 JWT authentication to work, you have to disable IAM for ESPv2 cloud-run by passing the flag "--allow-unauthenticated" in "gcloud run deploy" command.
Upvotes: 0
Reputation: 75745
I think you need a Google signed JWT token and not a self signed token. Try to change the end of your code with this (after your signed_jwt = ...
line)
auth_url = "https://www.googleapis.com/oauth2/v4/token"
params = {
'assertion': signed_jwt, # You may need to decode the signed_jwt: signed_jwt.decode('utf-8')
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
}
r = requests.post(auth_url, data=params)
if r.ok:
id_token = r.json()['id_token']
headers = {
'Authorization': 'Bearer {}'.format(id_token),
'content-type': 'application/json',
}
url = "https://<cloud-run-service>-pjcfvhz2qq-uc.a.run.app/endpoint_1"
res = requests.get(url, headers=headers)
print(res.json())
# For debugging
print(r)
print(vars(r))
Upvotes: 6