Authentication
Require authentication for a worker served over HTTP, and read the caller’s identity inside your functions.
Auth applies only to the HTTP transport. A subprocess or Unix-socket worker is launched by the
engine and runs co-located and trusted — there’s no remote caller to authenticate — so it always
runs as AuthContext.anonymous(). Reach for authentication when you
serve over HTTP.
| Transport | Auth behavior |
|---|---|
| HTTP, with auth configured | Validated per request; the caller’s AuthContext is propagated to your functions |
| HTTP, no auth configured | All requests anonymous |
| Subprocess / Unix socket | Always AuthContext.anonymous() (co-located, trusted) |
| TCP | Always AuthContext.anonymous() — and not trusted. See the warning below. |
Subprocess and Unix-socket workers are anonymous because they’re co-located. A TCP worker is anonymous for a different reason: the raw Arrow-IPC framing carries no auth and no encryption, so anyone who can reach the port can call every function. Bind it to loopback or a trusted network — and use HTTP the moment the network isn’t one.
How it fits together
Section titled “How it fits together”The authentication machinery — the AuthContext, the authenticate callback, and the HTTP
middleware that runs it per request — is provided by vgi-rpc, the RPC framework VGI runs on. VGI
wires it into the HTTP server and surfaces the resulting AuthContext to your functions. So this
page covers the VGI integration; for the full model (the callback contract, the AuthContext
type, mTLS, OAuth discovery) see vgi-rpc’s
Auth & Context reference.
Authentication is fully optional — unconfigured, every request is anonymous.
Enable it: static bearer tokens
Section titled “Enable it: static bearer tokens”The quickest setup is static bearer tokens via an environment variable — comma-separated
token=principal pairs:
VGI_BEARER_TOKENS="token1=alice,token2=bob" vgi-serve my_worker.py --http
Unauthenticated requests get HTTP 401; authenticated ones carry the principal in an
AuthContext. (Each pair splits on the first =, so a principal may contain =, but a token
must not contain = or ,.)
Read the caller in your functions
Section titled “Read the caller in your functions”A function opts in by declaring the auth context; the framework injects it per call.
Scalar functions — annotate a compute parameter with Auth:
from typing import Annotated
import pyarrow as pa
from vgi import ScalarFunction, Param, Returns, Auth
from vgi.auth import AuthContext
class WhoAmI(ScalarFunction):
@classmethod
def compute(
cls,
x: Annotated[pa.Int64Array, Param(doc="rows to label")],
auth: Annotated[AuthContext, Auth()],
) -> Annotated[pa.StringArray, Returns()]:
auth.require_authenticated() # raises if anonymous
return pa.array([auth.principal] * len(x))
Table / aggregate / buffering functions — read params.auth_context (also available at bind
time on the bind params):
from vgi.table_function import TableFunctionGenerator
class SecureTable(TableFunctionGenerator):
@classmethod
def process(cls, params, state, out):
if not params.auth_context.authenticated:
raise PermissionError("Authentication required")
# … produce output …
AuthContext carries principal, authenticated, and domain, and require_authenticated()
raises PermissionError when anonymous. The full type lives in vgi-rpc —
Auth & Context.
JWT / OAuth
Section titled “JWT / OAuth”For real deployments, validate JWTs against a JWKS endpoint instead of static tokens. Set the issuer
and audience (pip install vgi-python[oauth]):
VGI_JWT_ISSUER="https://auth.example.com/" \
VGI_JWT_AUDIENCE="my-api" \
vgi-serve my_worker.py --http
| Variable | Description |
|---|---|
VGI_JWT_ISSUER | JWT issuer URL (enables JWT validation) |
VGI_JWT_AUDIENCE | Expected audience(s), comma-separated |
VGI_JWT_JWKS_URI | JWKS endpoint (auto-discovered from the issuer if omitted) |
VGI_OAUTH_RESOURCE | Resource URL for RFC 9728 OAuth metadata (and related VGI_OAUTH_* vars) |
When both VGI_BEARER_TOKENS and VGI_JWT_ISSUER are set, JWT validation is tried first, falling
back to bearer lookup. The full OAuth/JWKS surface — RFC 9728 resource metadata, OIDC id_token
mode, and the discovery flow — is documented in vgi-rpc’s
OAuth discovery reference.
Beyond env vars
Section titled “Beyond env vars”- Custom schemes — pass your own
authenticatecallback tomake_wsgi_app(authenticate=…)/create_app(...)to implement any scheme; env vars are then ignored. See vgi-rpc’s Auth & Context. - Mutual TLS — client-certificate auth is a vgi-rpc capability; see Mutual TLS.
- Behind a reverse proxy — when the proxy terminates the only public listener, override
Worker.resolve_token()to expose a token-introspection route, and advertise proof enforcement withVGI_PROXY_PROOF_MODE. Both are covered under Deployment caps and proxies.
Next steps
Section titled “Next steps”- Stand up the HTTP service first → Serve over HTTP.
- The auth model in full → vgi-rpc Auth & Context.