Authentication
Specify CLI uses opt-in authentication for HTTP requests to catalog sources, extension downloads, and release checks. No credentials are sent unless you explicitly configure them.
Configuration
Create ~/.specify/auth.json to enable authentication:
{
"providers": [
{
"hosts": ["github.com", "api.github.com", "raw.githubusercontent.com", "codeload.github.com"],
"provider": "github",
"auth": "bearer",
"token_env": "GH_TOKEN"
}
]
}Security: Restrict the file to owner-only access:
bashchmod 600 ~/.specify/auth.json
Without this file, all HTTP requests are unauthenticated.
Fields
Each entry in the providers array has the following fields:
| Field | Required | Description |
|---|---|---|
hosts | Yes | Array of hostnames this entry applies to. Supports exact hostnames, or a leading *. wildcard for subdomains only (for example, *.visualstudio.com). *.visualstudio.com matches foo.visualstudio.com, but not visualstudio.com. Other glob patterns such as *github.com or gith?b.com are not supported. |
provider | Yes | Built-in provider key: github or azure-devops. |
auth | Yes | Auth scheme (see below). |
token | No | Token value (inline). Use token_env instead when possible. |
token_env | No | Environment variable name to read the token from. |
For azure-ad auth, additional fields are required:
| Field | Required | Description |
|---|---|---|
tenant_id | Yes | Azure AD tenant ID. |
client_id | Yes | Service principal client ID. |
client_secret_env | Yes | Environment variable containing the client secret. |
Either token or token_env must be set for bearer and basic-pat schemes.
Providers and auth schemes
GitHub (github)
| Scheme | Header | Use for |
|---|---|---|
bearer | Authorization: Bearer <token> | PATs, fine-grained PATs, OAuth tokens, GitHub App tokens |
Example — PAT via environment variable:
{
"hosts": ["github.com", "api.github.com", "raw.githubusercontent.com", "codeload.github.com"],
"provider": "github",
"auth": "bearer",
"token_env": "GH_TOKEN"
}GitHub Enterprise Server (GHES)
To use a private catalog or extension hosted on a GitHub Enterprise Server instance, add a github entry listing your GHES host(s). The same entry authenticates both catalog JSON fetches and private release-asset downloads — Specify recognizes the listed hosts as GitHub Enterprise and resolves release downloads through the GHES REST API (/api/v3).
{
"providers": [
{
"hosts": ["ghes.example.com", "raw.ghes.example.com", "codeload.ghes.example.com"],
"provider": "github",
"auth": "bearer",
"token_env": "GH_ENTERPRISE_TOKEN"
}
]
}List the bare web host (e.g. ghes.example.com) — release-download URLs live there. If your instance uses subdomain isolation, also list the raw. and codeload. subdomains your catalog/extension URLs use. A *.ghes.example.com wildcard matches subdomains but not the bare host, so always include the bare host explicitly.
Azure DevOps (azure-devops)
| Scheme | Header | Use for |
|---|---|---|
basic-pat | Authorization: Basic base64(:<PAT>) | Personal Access Tokens |
bearer | Authorization: Bearer <token> | Pre-acquired OAuth / Azure AD tokens |
azure-cli | Authorization: Bearer <token> | Token acquired via az account get-access-token |
azure-ad | Authorization: Bearer <token> | Token acquired via OAuth2 client credentials flow |
Example — PAT via environment variable:
{
"hosts": ["dev.azure.com"],
"provider": "azure-devops",
"auth": "basic-pat",
"token_env": "AZURE_DEVOPS_PAT"
}Example — Azure CLI (interactive login):
{
"hosts": ["dev.azure.com"],
"provider": "azure-devops",
"auth": "azure-cli"
}Requires az login to have been run beforehand.
Example — Azure AD service principal (CI/automation):
{
"hosts": ["dev.azure.com"],
"provider": "azure-devops",
"auth": "azure-ad",
"tenant_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"client_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"client_secret_env": "AZURE_CLIENT_SECRET"
}Multiple entries
You can configure multiple entries for different hosts or organizations:
{
"providers": [
{
"hosts": ["github.com", "api.github.com", "raw.githubusercontent.com", "codeload.github.com"],
"provider": "github",
"auth": "bearer",
"token_env": "GH_TOKEN"
},
{
"hosts": ["dev.azure.com"],
"provider": "azure-devops",
"auth": "basic-pat",
"token_env": "AZURE_DEVOPS_PAT"
}
]
}How it works
- For each outbound HTTP request, the URL hostname is matched against the
hostspatterns inauth.json. - If a match is found, the corresponding provider resolves the token and attaches the appropriate
Authorizationheader. - If the request receives a 401 or 403, the next matching entry is tried.
- After all matching entries are exhausted, an unauthenticated request is attempted as a final fallback.
- On redirects, the
Authorizationheader is stripped if the redirect target leaves the entry's declared hosts — preventing credential leakage to CDNs or third-party services.
Template
A reference auth.json with GitHub pre-configured:
{
"providers": [
{
"hosts": [
"github.com",
"api.github.com",
"raw.githubusercontent.com",
"codeload.github.com"
],
"provider": "github",
"auth": "bearer",
"token_env": "GH_TOKEN"
}
]
}To use it:
mkdir -p ~/.specify
# Copy the JSON above into ~/.specify/auth.json
chmod 600 ~/.specify/auth.json