oauth - OAuth authentication in SLICC
SYNOPSIS
oauth-token <provider> Get an access token for a provider
oauth-token --provider <id> Same, using flag form
oauth-token Get token for the currently selected provider
oauth-token --list List OAuth providers with status
oauth-token --help Show help
DESCRIPTION
The oauth-token command retrieves an OAuth access token for a given provider. If a valid (non-expired) token already exists, it is returned immediately. If no token exists or the current token has expired, the OAuth login flow is triggered automatically — a browser tab opens for the user to authenticate. The raw access token is printed to stdout on success.
When called with no arguments, oauth-token uses the currently selected provider. If the selected provider is not an OAuth provider, it falls back to the first available OAuth provider. Use oauth-token --list to see which providers are configured and their login status.
USAGE IN SHELL PIPELINES
Use command substitution to inject tokens into HTTP requests:
curl -H "Authorization: Bearer $(oauth-token adobe)" https://api.example.com/data
curl -H "Authorization: Bearer $(oauth-token github)" https://api.github.com/user
The token is printed to stdout with a trailing newline, so $(oauth-token <provider>) captures it cleanly.
USAGE IN .jsh SCRIPTS
In .jsh scripts, use exec() to call oauth-token:
const result = await exec('oauth-token adobe');
if (result.exitCode !== 0) {
console.error('OAuth failed:', result.stderr);
process.exit(1);
}
const token = result.stdout.trim();
const resp = await fetch('https://api.example.com/data', {
headers: { 'Authorization': `Bearer ${token}` }
});
const data = await resp.json();
console.log(JSON.stringify(data, null, 2));
PROVIDER-BASED AUTH
Each OAuth provider (adobe, github, etc.) has its own configuration defined as a ProviderConfig with isOAuth: true. The provider handles provider-specific logic: building the authorize URL, extracting the token from the redirect URL, and fetching user profile information. SLICC provides the transport layer — opening the browser window and returning the redirect URL.
Supported providers depend on what is configured in the deployment. Use oauth-token --list to see available providers and their status (logged in, expired, or no token).
LOGIN FLOW
When oauth-token needs a new token, it calls the provider's onOAuthLogin(launcher, onSuccess) callback. The flow works as follows:
- The provider builds an authorize URL with client ID, scopes, and redirect URI.
- The provider calls the
OAuthLauncherwith this URL. - CLI mode: a popup window opens to the authorize URL. After authentication, the OAuth provider redirects to
/auth/callback, which posts the redirect URL back viapostMessage. - Extension mode: the request routes through the service worker, which calls
chrome.identity.launchWebAuthFlow. The redirect URL is returned via a broadcast message. - The provider extracts the access token from the redirect URL and saves it.
The createOAuthLauncher() factory in providers/oauth-service.ts automatically selects the correct transport for the current runtime. Both modes time out after 2 minutes.
TOKEN STORAGE AND REFRESH
Tokens are persisted via saveOAuthAccount() in provider settings. Each account stores the access token, expiration time, and optional user name. When oauth-token is called, it checks for a stored non-expired token first. If the token is expired, the full login flow is re-triggered. Providers that support token refresh handle it within their onOAuthLogin implementation.
PROVIDER MERGE LAYERS
Model capabilities are resolved through a three-layer merge:
- pi-ai defaults: base model registry from the pi-ai library.
- modelOverrides (static): per-model overrides defined in the provider's
ProviderConfig.modelOverridesfield. - getModelIds (dynamic): runtime model list with metadata returned by the provider's
getModelIds()method. Highest priority.
Fields include api (anthropic or openai), context_window, max_tokens, reasoning, and input modalities.
EXTERNAL PROVIDERS
Custom providers are added by placing .ts files in packages/webapp/providers/. Each file exports a config: ProviderConfig and optionally a register() function for custom stream functions. External providers are always included (never filtered by build config) and are typically used for corporate SSO or API proxies.
ERROR HANDLING
- Unknown provider: exit code 1,
unknown provider "<id>" - Non-OAuth provider: exit code 1,
provider "<id>" is not an OAuth provider - No OAuth providers configured: exit code 1
- Login failed (e.g., popup closed): exit code 1,
login failed: <reason> - Login completed but no token saved: exit code 1
SEE ALSO
jsh(1), skill(1), float(1)