Invect

Credentials & OAuth2

Manage API keys and OAuth2 connections securely.

Overview

Invect stores credentials encrypted with AES-256-GCM. The system supports simple API keys and full OAuth2 flows with automatic token refresh.

Encryption Key

Set the encryption key via environment variable:

INVECT_ENCRYPTION_KEY=<base64-encoded-32-byte-key>

Generate one:

npx invect-cli secret

API Key Credentials

Simple key/value credentials for services like OpenAI:

await core.createCredential({
  name: 'My OpenAI Key',
  type: 'api_key',
  config: {
    apiKey: 'sk-...',
  },
});

OAuth2 Credentials

Invect includes built-in OAuth2 provider definitions for:

  • Google — Gmail, Drive, Docs, Sheets, Calendar
  • GitHub
  • Slack
  • Microsoft 365
  • Notion
  • Jira
  • Linear

OAuth2 Flow

  1. Start — Frontend calls POST /credentials/oauth2/start with provider ID and client credentials
  2. Authorize — User is redirected to the provider's authorization page
  3. Callback — Provider redirects back with an authorization code
  4. Exchange — Backend exchanges the code for access + refresh tokens
  5. Store — Tokens are encrypted and stored in the database

Automatic Token Refresh

When a credential is accessed and the access token has expired, Invect automatically uses the refresh token to get a new one. This happens transparently — actions always receive a valid token.

Adding a Custom OAuth2 Provider

Register a custom OAuth2 provider definition through a plugin's init hook or by adding to the provider registry at runtime:

const customProvider = {
  id: 'my_service',
  name: 'My Service',
  description: 'Access My Service API',
  icon: 'Cloud',
  authorizationUrl: 'https://myservice.com/oauth/authorize',
  tokenUrl: 'https://myservice.com/oauth/token',
  defaultScopes: ['read', 'write'],
  supportsRefresh: true,
  category: 'other',
};

Using Credentials in Actions

Actions access credentials via the execution context:

export const myAction = defineAction({
  id: 'my_provider.my_action',
  credential: {
    required: true,
    oauth2Provider: 'my_service',
  },
  async execute(params, context) {
    const token = context.credential?.config?.accessToken;

    const response = await fetch('https://api.myservice.com/data', {
      headers: { Authorization: `Bearer ${token}` },
    });

    return { success: true, output: await response.json() };
  },
});

API Endpoints

MethodPathDescription
GET/credentialsList all credentials
POST/credentialsCreate a credential
DELETE/credentials/:idDelete a credential
GET/credentials/oauth2/providersList OAuth2 providers
POST/credentials/oauth2/startStart OAuth2 flow
POST/credentials/oauth2/callbackComplete OAuth2 flow
POST/credentials/:id/refreshForce token refresh