Reputation: 791
If you use the Google Auth Library for Python to authenticate an App Engine app to communicate with an app running on Compute Engine that uses the Extensible Service Proxy (ESP) as part of Cloud Endpoints with OpenAPI, you get an error response:
{
"code": 16,
"message": "JWT validation failed: BAD_FORMAT",
"details": [{
"@type": "type.googleapis.com/google.rpc.DebugInfo",
"stackEntries": [],
"detail": "auth"
}]
}
The only sample Cloud Endpoints code that I found doesn't use any library and instead builds the JSON Web Token (JWT) by hand and sets the proper HTTP header completely manually. Is there a way to do it with a standard library, so you get all the other benefits that come with it?
Upvotes: 0
Views: 338
Reputation: 791
The problem is caused by the fact that google.auth.app_engine.Credentials()
does not include the aud
claim in the JWTs that it builds, while ESP requires it. (I wish I found the Troubleshooting JWT Validation page earlier, it would have saved me hours I spent investigating this myself.)
Here is how to build credentials that ESP will accept:
import google.auth.app_engine
import google.auth.jwt
from google.appengine.api import app_identity
AUDIENCE = '...'
credentials = google.auth.jwt.Credentials(
signer=google.auth.app_engine.Signer(),
issuer=app_identity.get_service_account_name(),
subject=app_identity.get_service_account_name(),
audience=AUDIENCE)
where AUDIENCE
must match the x-google-audiences
value in your OpenAPI file or your Cloud Endponts service name (see the troubleshooting doc linked to above for details).
This code even works with dev_appserver.py
and a service account as long as you pass the --appidentity_private_key_path
and --appidentity_email_address
flags. But you'll need to convert your service account's private key into the format that dev_appserver.py
accepts, because it doesn't support either of the formats that the Google Cloud Console can give you. See this bug comment for instructions.
Upvotes: 1