CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-slack--oauth

Official library for interacting with Slack's OAuth endpoints

Pending
Overview
Eval results
Files

error-handling.mddocs/

Error Handling

Comprehensive error types with specific codes for different OAuth failure scenarios, enabling precise error handling and debugging.

Capabilities

Error Base Types

Base interfaces and enums for OAuth error handling.

/**
 * Base interface for errors with specific error codes
 */
interface CodedError extends Error {
  /** Error code identifying the specific error type */
  code: string;
}

/**
 * Enumeration of OAuth-specific error codes
 */
enum ErrorCode {
  /** Error during InstallProvider initialization */
  InstallerInitializationError = "slack_oauth_installer_initialization_error";
  /** Error during authorization/authentication */
  AuthorizationError = "slack_oauth_installer_authorization_error";
  /** Error generating OAuth installation URL */
  GenerateInstallUrlError = "slack_oauth_generate_url_error";
  /** Missing required state parameter */
  MissingStateError = "slack_oauth_missing_state";
  /** Invalid or corrupted state parameter */
  InvalidStateError = "slack_oauth_invalid_state";
  /** Missing required authorization code */
  MissingCodeError = "slack_oauth_missing_code";
  /** Unexpected or unhandled error */
  UnknownError = "slack_oauth_unknown_error";
}

Specific Error Classes

Individual error classes for different OAuth failure scenarios.

InstallerInitializationError

/**
 * Error thrown during InstallProvider initialization
 * Common causes: missing client ID/secret, invalid configuration
 */
class InstallerInitializationError extends Error implements CodedError {
  public code = ErrorCode.InstallerInitializationError;
  
  constructor(message: string);
}

AuthorizationError

/**
 * Error during authorization process with optional wrapped original error
 */
class AuthorizationError extends Error implements CodedError {
  public code = ErrorCode.AuthorizationError;
  /** Original error that caused this authorization failure */
  public original?: Error;
  
  /**
   * @param message - Error description
   * @param original - Optional original error that caused this failure
   */
  constructor(message: string, original?: Error);
}

GenerateInstallUrlError

/**
 * Error when generating OAuth installation URL
 * Common causes: invalid options, missing configuration
 */
class GenerateInstallUrlError extends Error implements CodedError {
  public code = ErrorCode.GenerateInstallUrlError;
  
  constructor(message: string);
}

State Parameter Errors

/**
 * Error when state parameter is missing from OAuth callback
 */
class MissingStateError extends Error implements CodedError {
  public code = ErrorCode.MissingStateError;
  
  constructor(message: string);
}

/**
 * Error when state parameter is invalid, corrupted, or expired
 */
class InvalidStateError extends Error implements CodedError {
  public code = ErrorCode.InvalidStateError;
  
  constructor(message: string);
}

Authorization Code Errors

/**
 * Error when authorization code is missing from OAuth callback
 */
class MissingCodeError extends Error implements CodedError {
  public code = ErrorCode.MissingCodeError;
  
  constructor(message: string);
}

Generic Error

/**
 * Generic error for unexpected OAuth failures
 */
class UnknownError extends Error implements CodedError {
  public code = ErrorCode.UnknownError;
  
  constructor(message: string);
}

Usage Examples:

import { 
  InstallProvider,
  ErrorCode,
  InstallerInitializationError,
  AuthorizationError,
  GenerateInstallUrlError,
  MissingStateError,
  InvalidStateError,
  MissingCodeError,
  UnknownError,
  CodedError
} from "@slack/oauth";

// Error handling during initialization
try {
  const installer = new InstallProvider({
    clientId: "", // Invalid: empty client ID
    clientSecret: process.env.SLACK_CLIENT_SECRET!,
    stateSecret: "secret",
  });
} catch (error) {
  if (error instanceof InstallerInitializationError) {
    console.error("Initialization error:", error.message);
    console.error("Error code:", error.code);
  }
}

// Error handling during URL generation
try {
  const installer = new InstallProvider({
    clientId: process.env.SLACK_CLIENT_ID!,
    clientSecret: process.env.SLACK_CLIENT_SECRET!,
    stateSecret: "secret",
  });
  
  const url = await installer.generateInstallUrl({
    scopes: [], // Invalid: empty scopes
  });
} catch (error) {
  if (error instanceof GenerateInstallUrlError) {
    console.error("URL generation failed:", error.message);
  }
}

// Error handling during authorization
try {
  const authResult = await installer.authorize({
    teamId: "INVALID_TEAM_ID",
  });
} catch (error) {
  if (error instanceof AuthorizationError) {
    console.error("Authorization failed:", error.message);
    if (error.original) {
      console.error("Original error:", error.original.message);
    }
  }
}

// Comprehensive error handling in callback handler
app.get("/slack/oauth_redirect", async (req, res) => {
  try {
    await installer.handleCallback(req, res);
  } catch (error) {
    // Type-safe error handling
    if (error instanceof MissingStateError) {
      console.error("State parameter missing from callback");
      res.status(400).send("Invalid OAuth request: missing state");
    } else if (error instanceof InvalidStateError) {
      console.error("State parameter invalid or expired");
      res.status(400).send("Invalid OAuth request: invalid state");
    } else if (error instanceof MissingCodeError) {
      console.error("Authorization code missing from callback");
      res.status(400).send("Invalid OAuth request: missing code");
    } else if (error instanceof AuthorizationError) {
      console.error("Authorization failed:", error.message);
      res.status(500).send("OAuth authorization failed");
    } else {
      console.error("Unknown OAuth error:", error);
      res.status(500).send("OAuth request failed");
    }
  }
});

// Generic error code checking
function handleOAuthError(error: unknown) {
  if (error && typeof error === "object" && "code" in error) {
    const codedError = error as CodedError;
    
    switch (codedError.code) {
      case ErrorCode.InstallerInitializationError:
        console.log("Fix your InstallProvider configuration");
        break;
      case ErrorCode.AuthorizationError:
        console.log("Check your app credentials and permissions");
        break;
      case ErrorCode.GenerateInstallUrlError:
        console.log("Verify your OAuth URL options");
        break;
      case ErrorCode.MissingStateError:
      case ErrorCode.InvalidStateError:
        console.log("State parameter issue - possible CSRF attack");
        break;
      case ErrorCode.MissingCodeError:
        console.log("Authorization code missing - user may have denied access");
        break;
      case ErrorCode.UnknownError:
      default:
        console.log("Unexpected OAuth error occurred");
        break;
    }
  }
}

// Error handling with custom callback handlers
const installer = new InstallProvider({
  clientId: process.env.SLACK_CLIENT_ID!,
  clientSecret: process.env.SLACK_CLIENT_SECRET!,
  stateSecret: "secret",
});

app.get("/slack/oauth_redirect", async (req, res) => {
  await installer.handleCallback(req, res, {
    success: (installation, options, req, res) => {
      console.log("OAuth successful for team:", installation.team?.id);
      res.send("Installation successful!");
    },
    failure: (error, options, req, res) => {
      console.error("OAuth failed:", error.code, error.message);
      
      // Custom error responses based on error type
      if (error.code === ErrorCode.InvalidStateError) {
        res.status(400).send("Security error: Invalid request state");
      } else if (error.code === ErrorCode.AuthorizationError) {
        res.status(401).send("Authorization failed");
      } else {
        res.status(500).send("Installation failed");
      }
    },
  });
});

Install with Tessl CLI

npx tessl i tessl/npm-slack--oauth

docs

error-handling.md

index.md

installation-storage.md

oauth-flow.md

state-management.md

tile.json