Authors: @LalitMaganti
Status: Adopted
RFC-0005 (Perfetto UI Server Extensions) defines a system where users can configure HTTP(S) endpoints to serve Perfetto UI extensions (macros, SQL modules, proto descriptors). These extension servers may require authentication to access:
The authentication system needs to:
Implement authentication as part of the server configuration itself, using per-server-type discriminated unions for auth options. Credentials are stored inline with the server settings in localStorage, with secret fields annotated via Zod metadata so they can be stripped when sharing server configurations.
Authentication is configured when adding or editing a server in Settings. Each server type (GitHub, HTTPS) has its own set of supported auth mechanisms, modeled as discriminated unions.
GitHub servers:
| Auth type | Description |
|---|---|
none | Public repos (no auth required) |
github_pat | Personal Access Token for private repos |
HTTPS servers:
| Auth type | Description |
|---|---|
none | Public servers (no auth required) |
https_basic | Username/password (Basic auth header) |
https_apikey | API key via Bearer, X-API-Key, or custom header |
https_sso | Cookie-based SSO with automatic iframe refresh |
Credentials are stored inline with the server configuration in the Perfetto settings system (localStorage). There is no separate credential store.
Secret fields (PAT, passwords, API keys) are annotated with .meta({secret: true}) in the Zod schema. This metadata is used to strip secrets when generating shareable server URLs.
// GitHub auth const githubAuthSchema = z.discriminatedUnion('type', [ z.object({type: z.literal('none')}), z.object({ type: z.literal('github_pat'), pat: z.string().meta({secret: true}).default(''), }), ]); // HTTPS auth const httpsAuthSchema = z.discriminatedUnion('type', [ z.object({type: z.literal('none')}), z.object({ type: z.literal('https_basic'), username: z.string().meta({secret: true}).default(''), password: z.string().meta({secret: true}).default(''), }), z.object({ type: z.literal('https_apikey'), keyType: z.enum(['bearer', 'x_api_key', 'custom']).default('bearer'), key: z.string().meta({secret: true}).default(''), customHeaderName: z.string().default(''), }), z.object({type: z.literal('https_sso')}), ]);
All URL construction and auth header injection happens in a single buildFetchRequest() function that takes a server configuration and a resource path, producing a URL and RequestInit:
GitHub PAT:
api.github.com/repos/.../contents/...) instead of raw.githubusercontent.comAuthorization: token {pat} headerAccept: application/vnd.github.raw+json headerGitHub (no auth):
raw.githubusercontent.com directly (avoids GitHub API rate limits)HTTPS Basic:
Authorization: Basic {base64(username:password)} headerHTTPS API Key:
bearer → Authorization: Bearer {key}x_api_key → X-API-Key: {key}custom → {customHeaderName}: {key}HTTPS SSO:
credentials: 'include' to the fetch request to send cookiesFor SSO-authenticated servers, a 403 response may indicate an expired session cookie. The UI handles this automatically:
onload, the browser has fresh cookiesThe iframe has a 10-second timeout. This flow is transparent to the user.
Auth configuration happens upfront during server addition, not on-demand after a 401/403. This is simpler and avoids the complexity of detecting auth requirements at runtime.
Servers can be shared via URL (?addServer=<base64>). When generating the share URL, the stripSecrets() function removes all fields annotated with .meta({secret: true}), replacing the auth with {type: 'none'}. The recipient must configure their own credentials after importing.
Embedder-configured servers (e.g., Google's internal server auto-added for Googlers) are marked as locked: true. Locked servers:
Credential Storage:
User controls:
CORS requirements:
All HTTPS extension servers must set CORS headers:
Access-Control-Allow-Origin: https://ui.perfetto.dev Access-Control-Allow-Methods: GET, POST Access-Control-Allow-Headers: Authorization, Content-Type, X-API-Key
SSO servers additionally need Access-Control-Allow-Credentials: true.