A Python decorator that restricts a Google App Engine handler to a whitelist of calling applications, for locking down app-to-app traffic inside App Engine.
Archived. Written in 2013 for Python 2 and
webapp2on the App Engine standard runtime, both long retired. Kept for reference.
When one App Engine application calls another using the URL Fetch service, the platform stamps the request with an X-AppEngine-Inbound-AppId header containing the caller's application ID. Crucially, App Engine strips this header from anything arriving off-platform, so it cannot be forged by an outside client — which makes it usable as an authentication signal on its own.
This decorator reads that header and rejects the request with 403 unless the caller's ID appears in the list you supply.
from app_id_security import appIdSecurity
class MyHandler(webapp2.RequestHandler):
@appIdSecurity({"my-other-app", "some-partner-app"})
def post(self):
self.response.write("only reachable from the two apps above")For Google Cloud Endpoints methods, use the variant that reads request_state instead of request:
from app_id_security import appIdSecurityForEndpoints
@appIdSecurityForEndpoints({"my-other-app"})
@endpoints.method(...)
def my_method(self, request):
...The header is absent on the development server and on any request that didn't originate from App Engine, so the check fails there by design. Pass * in the allowed list to skip it:
@appIdSecurity({"*"}) # no check — development onlyLeaving * in production disables the protection entirely.
| Situation | Result |
|---|---|
| Caller ID is in the list | Handler runs normally |
| Caller ID is not in the list | 403 with an explanatory body |
| Header missing (dev server, external caller) | 403 with a hint about the * escape hatch |
* present in the list |
Check skipped, handler runs |
Every decision is written to the App Engine log with an appIdSecurity: prefix.
Whole implementation is a single file: app_id_security.py.