Skip to main content
Toolshed includes built-in OAuth2 support for four providers. Each provider handles authorization, token exchange, encrypted storage, and automatic refresh.

Supported providers

ProviderPKCERevoke endpointDefault scopes
GitHubNoNorepo, read:user
GoogleYes (S256)Yesgmail.modify, calendar, drive.readonly
SlackNoNochannels:read, chat:write, groups:read
LinearYes (S256)Yesread, write

Required environment variables

Each provider requires a client ID and secret:
VariableDescription
GITHUB_CLIENT_IDGitHub OAuth app client ID
GITHUB_CLIENT_SECRETGitHub OAuth app client secret
GOOGLE_CLIENT_IDGoogle OAuth client ID
GOOGLE_CLIENT_SECRETGoogle OAuth client secret
SLACK_CLIENT_IDSlack app client ID
SLACK_CLIENT_SECRETSlack app client secret
LINEAR_CLIENT_IDLinear OAuth app client ID
LINEAR_CLIENT_SECRETLinear OAuth app client secret
Additionally:
VariableDescription
AUTH_REDIRECT_BASEBase URL for OAuth callbacks (e.g., https://toolshed.example.com/api/auth)
ENCRYPTION_KEYAES encryption key (base64) for encrypting stored tokens

OAuth flow

  1. Initiate: Client calls GET /api/auth/:provider/login?userId=X
  2. Redirect: Server redirects to provider’s authorization URL with scopes and state parameter
  3. Authorize: User grants permission in the provider’s UI
  4. Callback: Provider redirects to GET /api/auth/:provider/callback with authorization code
  5. Exchange: Server exchanges code for access/refresh tokens
  6. Store: Tokens are encrypted with AES and stored in the token store

Provider-specific behavior

Google:
  • Uses access_type=offline to get a refresh token
  • Uses prompt=consent to ensure refresh token is always returned
  • PKCE with S256 code challenge
Linear:
  • PKCE with S256 code challenge
  • Scope separator is comma (not space)
Slack:
  • Scope separator is comma
  • Token response uses authed_user.access_token (not top-level access_token)

Token vending

Plugins don’t handle OAuth directly. Instead, they call ctx.auth.getToken(provider) in their handlers, which:
  1. Calls POST /api/tokens/vend with the user’s ID and provider
  2. The server decrypts the stored token
  3. If expired, attempts automatic refresh
  4. Returns a usable access token
See Token Routes for the full API.

Connecting from the CLI

Once toolshed login is implemented, it will:
  1. Open a browser to the server’s auth page
  2. User authorizes each provider they want to use
  3. Session token is stored in ~/.toolshed/config.json