Skip to main content

vercel-passport-bundle

This is a version of vercel-passport with third-party dependencies bundled. For normal use, install the unbundled vercel-passport package instead: https://pypi.org/project/vercel-passport/

Passport

vercel.passport reads and verifies Vercel Passport identities in Python functions.

uv add vercel-passport

Read the current visitor

from fastapi import FastAPI
from fastapi.responses import JSONResponse
from vercel.passport import get_identity

app = FastAPI()


@app.get("/api/me")
async def me():
    identity = await get_identity()
    if identity is None:
        return JSONResponse({"authenticated": False}, status_code=401)

    return {
        "authenticated": True,
        "external_subject": identity.external_subject,
        "subject": identity.subject,
    }

get_identity() reads the x-vercel-oidc-passport-token header that Vercel adds after Passport authenticates the visitor, falling back to the _vercel_passport cookie. A session too large for one cookie is split across several, and is reassembled and checksummed before it is verified. With no arguments, it reads the headers the Vercel Python runtime records for the current request. You can also pass the request, or its headers, explicitly:

identity = await get_identity(request)
identity = await get_identity(request.headers, cookies=request.cookies)

A token from the request is always verified against Vercel's OIDC JWKS. Only the Passport issuer, https://passport.vercel.com/<owner>, is accepted, and the token must have the Passport shape, so a regular Vercel OIDC token is never accepted as a Passport identity.

By default the token must match this deployment's project and environment, read from VERCEL_PROJECT_ID and VERCEL_TARGET_ENV (or VERCEL_ENV). If neither can be determined, verification fails closed. Pass project_id, environment, owner_id, or audience to set the expectations explicitly. Time claims allow 60 seconds of clock skew.

Differences from @vercel/passport

Expectations compare by equality, so a backend cannot accidentally accept tokens minted for any project:

  • "*" is not a wildcard for project_id or environment; it matches only a token whose claim is literally "*".
  • Lists of accepted projects or environments are not supported. Call verify_identity() once per expected project instead.
  • Of jose's verify options, only audience is exposed, and the clock-skew allowance is fixed at 60 seconds. That allowance also applies to iat: a token claiming to be issued more than 60 seconds in the future is rejected, where jose does not check iat at all.
  • An unverified debugging token is accepted only in local development by default. See Local development.
  • The synthesized development identity is opt-in with VERCEL_PASSPORT_DEV=1 rather than on by default, so a process that is merely not on Vercel, such as a self-hosted server, never authenticates every visitor as a test user.
  • Local identities are set with the local_identity() context manager or VERCEL_PASSPORT_IDENTITY rather than getIdentity options, and are ignored on Vercel deployments other than VERCEL_ENV=development.
  • identity.project is set only when the token names a project ID, which every verified token does, so identity.project.id is never None.
  • In PassportDevelopmentIdentity, an explicit None clears a field its VERCEL_PASSPORT_DEV_* variable sets.

Identities are frozen Pydantic models, so an endpoint can return one directly, or serialize it with identity.model_dump(). The bearer token is left out of both model_dump() and the repr, so neither a response nor a log line exposes it; read it as identity.token when you need to forward it.

Use require_identity() when a route needs a real Passport token. It takes the same arguments as get_identity(), but raises PassportIdentityError instead of returning None, and also rejects an identity without a token, such as the local development identity. The returned identity's token is always set:

from vercel.passport import PassportIdentityError, require_identity

try:
    identity = await require_identity()
except PassportIdentityError:
    raise HTTPException(status_code=401)

forward_to_backend(identity.token)

For synchronous code, such as Flask or Django views, use vercel.passport.sync, which has the same names and arguments:

from vercel.passport.sync import get_identity

identity = get_identity()

Verify forwarded tokens

Use verify_identity() when a Passport-protected app forwards its Passport token to another backend. It accepts the token itself, or request headers carrying an Authorization: Bearer <token> header:

from fastapi import FastAPI, HTTPException, Request
from vercel.passport import PassportIdentityError, verify_identity

app = FastAPI()


@app.post("/api/orders")
async def orders(request: Request):
    try:
        identity = await verify_identity(
            request,
            owner_id="team_123",
            project_id="prj_123",
            environment="production",
        )
    except PassportIdentityError:
        raise HTTPException(status_code=401)

    return {"external_subject": identity.external_subject, "email": identity.email}

Unlike get_identity(), verify_identity() always verifies and never falls back to a local identity. If the token was minted by a different Vercel project than the backend verifying it, pass the source project's project_id and environment.

Local development

Local development usually has no Passport header or cookie, because Passport creates them in Vercel's edge network, so get_identity() returns None there. To work locally as a signed-in visitor, opt in to a synthesized test identity:

VERCEL_PASSPORT_DEV=1

get_identity() then returns a test identity when the request has no token, and emits a PassportDevelopmentIdentityWarning the first time it does so. The test identity uses:

external_subject: test-user
email: test-user@passport.local
name: Test User

Override individual fields with environment variables:

VERCEL_PASSPORT_DEV_OWNER=acme
VERCEL_PASSPORT_DEV_CONNECTOR_ID=scl_dev
VERCEL_PASSPORT_DEV_EXTERNAL_SUB=user_dev
VERCEL_PASSPORT_DEV_EXTERNAL_ISS=https://idp.example.com
VERCEL_PASSPORT_DEV_PROJECT=my-project
VERCEL_PASSPORT_DEV_PROJECT_ID=prj_local

To set the identity in code, such as in tests, use local_identity(). Inside the block, requests without a token get that identity, with no environment variable needed. Pass a PassportDevelopmentIdentity, whose unset fields still come from the environment, or the full claims yourself:

from vercel.passport import PassportDevelopmentIdentity, local_identity

with local_identity(PassportDevelopmentIdentity(owner="acme", external_subject="user_dev")):
    response = client.get("/api/me")

with local_identity({
    "typ": "passport",
    "iss": "https://passport.vercel.com/local",
    "owner": "local",
    "connector_id": "local",
    "external_sub": "local-user",
    "sub": "owner:local:connector:local:principal:local-user",
}):
    ...

The identity is held in a context variable, so it applies to the current request or test, to tasks started inside the block, and to threads started with anyio.to_thread or asyncio.to_thread, but not a plain threading.Thread. Full claims can also be given as JSON in VERCEL_PASSPORT_IDENTITY. The identity set with local_identity() comes first, then VERCEL_PASSPORT_IDENTITY, then the VERCEL_PASSPORT_DEV=1 test identity.

None of these is used on a Vercel deployment unless VERCEL_ENV=development, and none is verified, so identity.verified is False.

To debug with a real token copied from a deployed request, pass it directly or set VERCEL_PASSPORT_TOKEN. Such a token is decoded without verification unless you pass verify=True:

identity = await get_identity(token=copied_token)

Unverified tokens are accepted only in local development. On a Vercel deployment, other than VERCEL_ENV=development, an unverified token raises PassportIdentityError, including one left in VERCEL_PASSPORT_TOKEN. In deployed code, use verify_identity() or pass verify=True to verify explicit tokens. Pass allow_unverified=True only if you really mean to trust an unsigned token.

Metadata

Release files for vercel-passport-bundle 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vercel-passport-bundle 0.1.0
File Size Uploaded Provenance Actions
vercel_passport_bundle-0.1.0.tar.gz 18.9 kB Without provenance Details for vercel_passport_bundle-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for vercel-passport-bundle 0.1.0
File Interpreter ABI Platform Actions
vercel_passport_bundle-0.1.0-py3-none-any.whl Python 3 none any Details for vercel_passport_bundle-0.1.0-py3-none-any.whl

Total release size: 41.7 kB

Release files / vercel_passport_bundle-0.1.0.tar.gz

Download URL vercel_passport_bundle-0.1.0.tar.gz
Size 18.9 kB
Tags Source
SHA-256 checksum
How to use checksums
97d7c1c8e8f1e47144e7de06974eb12dc1222e638ba72fc035e30e106c7b3b01
BLAKE2b-256 checksum
How to use checksums
2068923da8028e028b3c5f712bbfc25b3e6dd2a9c4bf551a23bb62efbcd38c57
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / vercel_passport_bundle-0.1.0-py3-none-any.whl

Download URL vercel_passport_bundle-0.1.0-py3-none-any.whl
Size 22.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
672ca9b482c5c8909c6ac06bb5b594222caf0602b2b1c2c364f7d21a71f7fa53
BLAKE2b-256 checksum
How to use checksums
6e003ceaca3faaf8a0a45fe81775fd8d02229a442fd36740a12bdf4367fefe8a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for vercel-passport-bundle 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page