View on GitHub

Matimo - AI Tools Ecosystem

Define tools once in YAML, use them everywhere

Download this project as a .zip file Download this project as a tar.gz file

Provider Configuration Guide

Overview

Matimo uses a configuration-driven approach to OAuth2 provider endpoints. Instead of hardcoding provider information into the application, all provider definitions are stored in YAML files. This enables:

Provider Definition Structure

Each OAuth2 provider must have a definition.yaml file in its provider folder:

tools/
├── gmail/
│   └── definition.yaml          ← Provider definition
├── github/
│   └── definition.yaml
├── slack/
│   └── definition.yaml
└── [your-provider]/
    └── definition.yaml

Provider Definition Format

name: google-provider # Unique name for this provider definition
type: provider # MUST be "provider" to indicate this is an OAuth2 config
version: '1.0.0' # Semantic version of the provider config
description: Google OAuth2 provider # Optional description

provider:
  name: google # Provider identifier (used in code)
  displayName: Google # Human-readable name

  endpoints:
    authorizationUrl: https://accounts.google.com/o/oauth2/v2/auth
    tokenUrl: https://oauth2.googleapis.com/token
    revokeUrl: https://oauth2.googleapis.com/revoke # Optional

  defaultScopes: # Optional default scopes
    - https://www.googleapis.com/auth/gmail.send
    - https://www.googleapis.com/auth/gmail.readonly

  documentation: https://developers.google.com/identity/protocols/oauth2

Configuration Priority

Matimo resolves OAuth2 endpoints using a 3-tier priority system:

1. Runtime Configuration (Highest Priority)

User provides endpoints directly in code:

const oauth2 = new OAuth2Handler({
  provider: 'google',
  clientId: '...',
  clientSecret: '...',
  redirectUri: '...',
  endpoints: {
    // ← These override everything else
    authorizationUrl: 'https://custom.company.com/auth',
    tokenUrl: 'https://custom.company.com/token',
  },
});

Use case: Custom or internal OAuth2 servers

2. Environment Variables (Medium Priority)

Deploy-time configuration via environment variables:

export OAUTH_GOOGLE_AUTH_URL=https://custom.company.com/auth
export OAUTH_GOOGLE_TOKEN_URL=https://custom.company.com/token
export OAUTH_GOOGLE_REVOKE_URL=https://custom.company.com/revoke

Use case: Different endpoints per deployment (dev, staging, prod)

3. YAML Configuration (Default)

Default endpoints defined in tools/[provider]/definition.yaml:

provider:
  endpoints:
    authorizationUrl: https://accounts.google.com/o/oauth2/v2/auth
    tokenUrl: https://oauth2.googleapis.com/token

Use case: Standard provider defaults

Resolution Example

// If config.endpoints is provided → Use that (Priority 1)
const handler = new OAuth2Handler({
  provider: 'google',
  clientId: '...',
  endpoints: { authorizationUrl: 'https://custom/auth', ... }  // ← Used
});

// Else if OAUTH_GOOGLE_AUTH_URL env var is set → Use that (Priority 2)
process.env.OAUTH_GOOGLE_AUTH_URL = 'https://custom/auth';
const handler = new OAuth2Handler({
  provider: 'google',
  clientId: '...',
  // No endpoints provided, env var checked
});

// Else use tools/google/definition.yaml (Priority 3)
const handler = new OAuth2Handler({
  provider: 'google',
  clientId: '...',
  // No endpoints or env vars, loads from YAML
});

Adding a New Provider

Step 1: Create Provider Definition File

Create tools/[provider-name]/definition.yaml:

name: microsoft-provider
type: provider
version: '1.0.0'
description: Microsoft Azure AD OAuth2 provider

provider:
  name: microsoft
  displayName: Microsoft

  endpoints:
    authorizationUrl: https://login.microsoftonline.com/common/oauth2/v2.0/authorize
    tokenUrl: https://login.microsoftonline.com/common/oauth2/v2.0/token
    revokeUrl: https://login.microsoftonline.com/common/oauth2/v2.0/token/revoke

  defaultScopes:
    - https://graph.microsoft.com/Mail.Send
    - https://graph.microsoft.com/user.read

  documentation: https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow

Step 2: Use in Code

The provider loader automatically discovers the provider:

import { OAuth2Handler } from '@matimo/oauth2';

const oauth2 = new OAuth2Handler({
  provider: 'microsoft', // Provider name from definition.yaml
  clientId: process.env.MICROSOFT_CLIENT_ID,
  clientSecret: process.env.MICROSOFT_CLIENT_SECRET,
  redirectUri: 'http://localhost:3000/callback',
});

// Get authorization URL
const authUrl = oauth2.getAuthorizationUrl({
  scopes: ['https://graph.microsoft.com/Mail.Send'],
  userId: 'user-123',
});

Step 3: (Optional) Override with Environment Variables

For deployment-specific endpoints:

export OAUTH_MICROSOFT_AUTH_URL=https://custom-idp.company.com/authorize
export OAUTH_MICROSOFT_TOKEN_URL=https://custom-idp.company.com/token
export OAUTH_MICROSOFT_REVOKE_URL=https://custom-idp.company.com/revoke

Built-in Provider Examples

Google (Gmail)

File: tools/gmail/definition.yaml

name: google-provider
type: provider
version: '1.0.0'

provider:
  name: google
  displayName: Google

  endpoints:
    authorizationUrl: https://accounts.google.com/o/oauth2/v2/auth
    tokenUrl: https://oauth2.googleapis.com/token
    revokeUrl: https://oauth2.googleapis.com/revoke

  defaultScopes:
    - https://www.googleapis.com/auth/gmail.send
    - https://www.googleapis.com/auth/gmail.readonly
    - https://www.googleapis.com/auth/gmail.compose

  documentation: https://developers.google.com/identity/protocols/oauth2

GitHub

File: tools/github/definition.yaml

name: github-provider
type: provider
version: '1.0.0'

provider:
  name: github
  displayName: GitHub

  endpoints:
    authorizationUrl: https://github.com/login/oauth/authorize
    tokenUrl: https://github.com/login/oauth/access_token

  defaultScopes:
    - user:email
    - repo
    - gist

  documentation: https://docs.github.com/en/developers/apps/building-oauth-apps

Slack

File: tools/slack/definition.yaml

name: slack-provider
type: provider
version: '1.0.0'

provider:
  name: slack
  displayName: Slack

  endpoints:
    authorizationUrl: https://slack.com/oauth/v2/authorize
    tokenUrl: https://slack.com/api/oauth.v2.access

  defaultScopes:
    - chat:write
    - channels:read
    - users:read

  documentation: https://api.slack.com/authentication/oauth-v2

Token Management

Matimo handles OAuth2 flows but does NOT store tokens. Token storage is your responsibility:

import { OAuth2Handler } from '@matimo/oauth2';

// 1. Initialize handler
const oauth2 = new OAuth2Handler({
  provider: 'google',
  clientId: '...',
  clientSecret: '...',
  redirectUri: 'http://localhost:3000/callback',
});

// 2. Generate auth URL
const authUrl = oauth2.getAuthorizationUrl({
  scopes: ['https://www.googleapis.com/auth/gmail.send'],
  userId: 'user-123',
});
// → Redirect user to authUrl

// 3. Exchange code for token
const token = await oauth2.exchangeCodeForToken('user-123', authCode);
// Result: { accessToken, refreshToken, expiresAt, ... }

// 4. YOU store the token (database, Redis, file, etc.)
await database.saveToken('user-123', token);

// 5. Later, retrieve and use the token with Matimo tools
const stored = await database.getToken('user-123');
await matimo.execute('gmail-send-email', {
  to: 'recipient@example.com',
  GMAIL_ACCESS_TOKEN: stored.accessToken, // ← Pass token here
});

Dynamic Provider Discovery

The provider loader automatically discovers all providers from YAML files:

import { OAuth2ProviderLoader } from '@matimo/auth';

const loader = new OAuth2ProviderLoader('./tools');
const providers = await loader.loadProviders();

// List all discovered providers
const providerNames = providers.keys();
// Output: ['google', 'github', 'slack', 'microsoft', ...]

// Get endpoints for specific provider
const googleEndpoints = providers.get('google');
console.log(googleEndpoints);
// Output: {
//   authorizationUrl: 'https://accounts.google.com/...',
//   tokenUrl: 'https://oauth2.googleapis.com/token',
//   revokeUrl: '...'
// }

Custom OAuth2 Server

Use runtime configuration to connect to a custom OAuth2 server:

const oauth2 = new OAuth2Handler({
  provider: 'internal-oauth', // Any name
  clientId: 'internal-client',
  clientSecret: 'internal-secret',
  redirectUri: 'http://localhost:3000/callback',
  endpoints: {
    authorizationUrl: 'https://oauth.company.internal/authorize',
    tokenUrl: 'https://oauth.company.internal/token',
    revokeUrl: 'https://oauth.company.internal/revoke',
  },
});

Or use environment variables:

export OAUTH_INTERNAL_AUTH_URL=https://oauth.company.internal/authorize
export OAUTH_INTERNAL_TOKEN_URL=https://oauth.company.internal/token
export OAUTH_INTERNAL_REVOKE_URL=https://oauth.company.internal/revoke
const oauth2 = new OAuth2Handler({
  provider: 'internal',
  clientId: '...',
  clientSecret: '...',
  redirectUri: '...',
  // Endpoints loaded from env vars automatically
});

Best Practices

1. Use Configuration-Driven Approach

❌ Don’t hardcode endpoints:

const oauth2 = new OAuth2Handler({
  provider: 'custom',
  clientId: '...',
  endpoints: {
    authorizationUrl: 'https://hardcoded.example.com/auth', // ❌ Bad
  },
});

✅ Use YAML or environment variables:

# tools/custom/definition.yaml
provider:
  endpoints:
    authorizationUrl: https://custom.example.com/auth

2. Document Provider Requirements

Include setup instructions in provider definition:

provider:
  documentation: https://docs.example.com/oauth2-setup
  # Include links to:
  # - How to register OAuth app
  # - Where to get client ID/secret
  # - Required scopes for different use cases

3. Use Semantic Versioning

Update version when endpoints change:

version: '1.1.0' # Increment for breaking changes

4. Never Hardcode Secrets

Always use environment variables:

const oauth2 = new OAuth2Handler({
  provider: 'google',
  clientId: process.env.GOOGLE_CLIENT_ID, // ✅ From env vars
  clientSecret: process.env.GOOGLE_CLIENT_SECRET, // ✅ From env vars
  redirectUri: process.env.GOOGLE_REDIRECT_URI, // ✅ From env vars
});

5. Validate Provider Definition

Matimo automatically validates YAML structure:

// This throws MatimoError if definition is invalid
const loader = new OAuth2ProviderLoader('./tools');
await loader.loadProviders();

Troubleshooting

Provider Not Found

MatimoError: Unsupported OAuth2 provider: custom. Provide endpoints via:
  1. config.endpoints (runtime override)
  2. OAUTH_CUSTOM_AUTH_URL env var (deployment config)
  3. tools/custom/definition.yaml (YAML configuration)

Solution: Create tools/custom/definition.yaml with provider definition

Invalid Provider Definition

MatimoError: Invalid provider definition: Missing required field 'endpoints'

Solution: Ensure YAML has required fields:

Environment Variable Not Read

Make sure env var name matches the pattern:

# For provider: 'google'
export OAUTH_GOOGLE_AUTH_URL=...
export OAUTH_GOOGLE_TOKEN_URL=...
export OAUTH_GOOGLE_REVOKE_URL=...  # Optional

# For provider: 'microsoft'
export OAUTH_MICROSOFT_AUTH_URL=...

See Also