使用JWT触发Google Cloud功能
我正在尝试使用HTTP请求和服务帐户触发Google云功能。 我遵循以下步骤:
- 创建一个服务帐户
- 下载JSON密钥文件
- 创建一个需要身份验证的Google Cloud函数(这是一个仅返回“ Hello World!”的测试功能,
- 我在“云函数权限”中添加了我的服务帐户,其中包括角色云功能 如果我使用此服务帐户(GCLOUD auth print-nidentity-token)生成身份令牌,并使用它来触发我的
云功能(授权:bearer $ id_token
在标题中),则可以按预期工作。 但是现在我希望能够在生产中做到这一点。因此,我所做的就是生成一个JWT,使用它来获得访问令牌并使用此访问令牌,就像我对身份令牌一样,但我得到401未经授权的响应。
这是我的代码(Python),
import jwt
import time
import requests
# These elements are found in the service account JSON file (step 2)
PRIVATE_KEY_ID_FROM_JSON = "123ab4cdefghi56jk789123456789f123456m7n"
PRIVATE_KEY_FROM_JSON = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
SERVICE_ACCOUNT_EMAIL = "ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com"
# Create JWT
iat = int(time.time())
exp = iat + 3600
payload = {
'iss': SERVICE_ACCOUNT_EMAIL,
'sub': SERVICE_ACCOUNT_EMAIL,
'aud': "https://www.googleapis.com/oauth2/v4/token",
'target_audience ': 'https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME',
'iat': iat,
'exp': exp,
"scope": "https://www.googleapis.com/auth/cloud-platform"
}
additional_headers = {'kid': PRIVATE_KEY_ID_FROM_JSON}
signed_jwt = jwt.encode(
payload,
PRIVATE_KEY_FROM_JSON,
headers=additional_headers,
algorithm='RS256'
)
# Use JWT to get access token
resp = requests.post(
f"https://www.googleapis.com/oauth2/v4/token"
f"?grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion={signed_jwt}",
headers={
"Authorization": f"Bearer {signed_jwt}",
"Content-Type": "application/x-www-form-urlencoded"
}
)
access_token = resp.json()["access_token"]
# Trigger Cloud Function using this access token
resp_cf = requests.post(
"https://europe-west1-cuure-265415.cloudfunctions.net/Test_service_account",
headers={
"Authorization": f"Bearer {access_token}"
}
)
print(resp_cf.content)
结果是
b'\n<html><head>\n<meta http-equiv="content-type" content="text/html;charset=utf-8">\n<title>401 Unauthorized</title>\n</head>\n<body text=#000000 bgcolor=#ffffff>\n<h1>Error: Unauthorized</h1>\n<h2>Your client does not have permission to the requested URL <code>/CLOUD FUNCTION NAME</code>.</h2>\n<h2></h2>\n</body></html>\n'
我不想使用python库用服务帐户来验证我的请求,因为我的目的是能够在一个无代码开发平台Bubble.io中重现此请求。
有人知道我在做什么错吗?
I am trying to trigger a Google cloud function using an HTTP request and a service account.
I followed these steps :
- Create a service account
- Download JSON key file
- Create a Google Cloud function that requires authentication (this is a test function that just returns "Hello world !"
- In the Cloud function permissions I added my service account with the role Cloud Functions Invoker
If I generate an identity token with this service account (gcloud auth print-identity-token) and use it to trigger my Cloud function (with Authorization: Bearer $ID_TOKEN
in headers) it works as expected.
But now I want to be able to do it in production. So what I did is generate a JWT, use it to get an access token and use this access token just like I did with the identity token but I get 401 Unauthorized response.
Here is my code (Python)
import jwt
import time
import requests
# These elements are found in the service account JSON file (step 2)
PRIVATE_KEY_ID_FROM_JSON = "123ab4cdefghi56jk789123456789f123456m7n"
PRIVATE_KEY_FROM_JSON = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
SERVICE_ACCOUNT_EMAIL = "ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com"
# Create JWT
iat = int(time.time())
exp = iat + 3600
payload = {
'iss': SERVICE_ACCOUNT_EMAIL,
'sub': SERVICE_ACCOUNT_EMAIL,
'aud': "https://www.googleapis.com/oauth2/v4/token",
'target_audience ': 'https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME',
'iat': iat,
'exp': exp,
"scope": "https://www.googleapis.com/auth/cloud-platform"
}
additional_headers = {'kid': PRIVATE_KEY_ID_FROM_JSON}
signed_jwt = jwt.encode(
payload,
PRIVATE_KEY_FROM_JSON,
headers=additional_headers,
algorithm='RS256'
)
# Use JWT to get access token
resp = requests.post(
f"https://www.googleapis.com/oauth2/v4/token"
f"?grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion={signed_jwt}",
headers={
"Authorization": f"Bearer {signed_jwt}",
"Content-Type": "application/x-www-form-urlencoded"
}
)
access_token = resp.json()["access_token"]
# Trigger Cloud Function using this access token
resp_cf = requests.post(
"https://europe-west1-cuure-265415.cloudfunctions.net/Test_service_account",
headers={
"Authorization": f"Bearer {access_token}"
}
)
print(resp_cf.content)
The result is the following
b'\n<html><head>\n<meta http-equiv="content-type" content="text/html;charset=utf-8">\n<title>401 Unauthorized</title>\n</head>\n<body text=#000000 bgcolor=#ffffff>\n<h1>Error: Unauthorized</h1>\n<h2>Your client does not have permission to the requested URL <code>/CLOUD FUNCTION NAME</code>.</h2>\n<h2></h2>\n</body></html>\n'
I don't want to use Python libraries to authenticate my request with the service account because my aim is to be able to reproduce this in Bubble.io, a no code development platform.
Anyone knows what I'm doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如答案:
您还可以参考答案在其中解释了Google签名的ID代币的自我签名JWT的地方,可以很好地解释。
As mentioned in the Answer :
You can also refer to the documentation and answer where exchanging a self-signed JWT for a Google-signed ID token is well explained.
我注意到的一件事是云功能第二代不使用这种类型的端点'https://region-project_id.cloudfunctions.net/function_name'。 GCP生成了该功能的URL
One thing I noticed is CLoud functions 2nd gen is not working with this type of endpoint 'https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME'. GCP generates a URL for the function
我正在发布对我有用的解决方案。
为了获取ID令牌而不是访问令牌(以便再次在ADC或Google Enviornment或本地机器外面获取/请求您的另一个Google服务(如Cloud Funtion)。
这是您可能使用的代码。
现在,要测试此令牌以请求和身份验证的功能,您可以通过
I am posting the solution which worked for me.
To fetch the ID token rather than access token (for again fetching/requesting your another google service like cloud funtion) outside the ADC or google enviornment or in local machine.
Here is the code which you may use.
now to test this token to request and authenticated function you can do so by