UNPKG

oauth-connector

Version:

OAuth Connector SDK for automatic token management and refresh with multiple persistence strategies

508 lines (492 loc) 13.5 kB
import { IncomingMessage } from 'http'; /** * Base OAuth configuration (shared fields) */ interface BaseOAuthConfig { clientId: string; clientSecret: string; refreshToken?: string; } /** * Zoho-specific OAuth configuration */ interface ZohoOauthConfig { clientId: string; clientSecret: string; accountsDomain: string; refreshToken?: string; } /** * Generic OAuth connector configuration (for Google and others) */ interface ConnectorConfig extends BaseOAuthConfig { authUrl: string; refreshUrl: string; } /** * Token data structure */ interface TokenData { accessToken: string; refreshToken?: string; expiresAt: number; tokenType?: string; scope?: string; } /** * Remote storage strategy configuration */ interface RemoteStorageConfig { onUpload: (data: TokenData) => Promise<void>; onDownload: () => Promise<TokenData | null>; encryptionKey?: string; } /** * Local storage strategy configuration */ interface LocalStorageConfig { filePath: string; encryptionKey?: string; } /** * Extended IncomingMessage with Catalyst-specific headers */ interface CatalystIncomingMessage extends IncomingMessage { catalystHeaders?: Record<string, string | string[] | undefined>; } /** * Catalyst Cache storage strategy configuration */ interface CatalystCacheStorageConfig { httpReq: CatalystIncomingMessage; key: string; encryptionKey?: string; } /** * Connector options */ interface ConnectorOptions { instanceId?: string; backgroundSyncIntervalInSecs?: number; graceExpiryTimeInSecs?: number; debug?: boolean; } /** * OAuth token response */ interface OAuthTokenResponse { access_token: string; refresh_token?: string; expires_in?: number; token_type?: string; scope?: string; } /** * Callback function types */ type OnFetchingAccessTokenCallback = () => void | Promise<void>; type OnTokenRefreshedCallback = (token: TokenData) => void | Promise<void>; type OnTokenErrorCallback = (error: Error) => void | Promise<void>; /** * Log levels */ declare enum LogLevel { DEBUG = 0, INFO = 1, WARN = 2, ERROR = 3 } /** * Simple logger with levels */ declare class Logger { private level; private prefix; constructor(level?: LogLevel, prefix?: string); /** * Set log level */ setLevel(level: LogLevel): void; /** * Set prefix for log messages */ setPrefix(prefix: string): void; /** * Get formatted timestamp */ private getTimestamp; /** * Format log message with timestamp */ private formatMessage; /** * Debug log */ debug(message: string, ...args: unknown[]): void; /** * Info log */ info(message: string, ...args: unknown[]): void; /** * Warn log */ warn(message: string, ...args: unknown[]): void; /** * Error log */ error(message: string, ...args: unknown[]): void; } /** * HTTP request options */ interface HttpClientOptions { method?: string; headers?: Record<string, string>; body?: string; timeout?: number; } /** * HTTP response */ interface HttpClientResponse<T = unknown> { statusCode: number; statusMessage: string; headers: Record<string, string | string[] | undefined>; data: T; } /** * HTTP client using native Node.js modules * Compatible with Node.js 14+ (no fetch dependency) */ declare class HttpClient { private logger; constructor(logger?: Logger); /** * Make HTTP/HTTPS request */ request<T = unknown>(url: string, options?: HttpClientOptions): Promise<HttpClientResponse<T>>; /** * Make POST request */ post<T = unknown>(url: string, body?: string, headers?: Record<string, string>): Promise<HttpClientResponse<T>>; /** * Make GET request */ get<T = unknown>(url: string, headers?: Record<string, string>): Promise<HttpClientResponse<T>>; /** * Parse response data based on content type */ private parseResponse; } /** * Abstract base class for OAuth services */ declare abstract class OAuthService { protected config: ConnectorConfig; protected logger: Logger; protected httpClient: HttpClient; constructor(config: ConnectorConfig, logger?: Logger); /** * Get refresh token from config (if available) */ getRefreshToken(): string | undefined; /** * Refresh access token using refresh token */ abstract refreshAccessToken(refreshToken: string): Promise<TokenData>; /** * Get authorization URL for initial OAuth flow */ abstract getAuthorizationUrl(redirectUri: string, scopes?: string[]): string; /** * Exchange authorization code for tokens */ abstract exchangeCodeForTokens(code: string, redirectUri: string): Promise<TokenData>; /** * Make token refresh request */ protected makeTokenRequest(url: string, params: Record<string, string>): Promise<OAuthTokenResponse>; /** * Convert OAuth response to TokenData */ protected convertToTokenData(response: OAuthTokenResponse): TokenData; } /** * Encryption service using AES-256-GCM */ declare class EncryptionService { private algorithm; private keyLength; private ivLength; private saltLength; private tagLength; /** * Derive key from password using scrypt */ private deriveKey; /** * Encrypt data */ encrypt(data: string, password: string): Promise<string>; /** * Decrypt data */ decrypt(encryptedData: string, password: string): Promise<string>; } /** * Abstract base class for storage strategies */ declare abstract class StorageStrategy { protected encryptionService: EncryptionService; protected logger: Logger; protected encryptionKey?: string; constructor(encryptionKey?: string, logger?: Logger); /** * Save token data */ abstract saveToken(tokenData: TokenData): Promise<void>; /** * Load token data */ abstract loadToken(): Promise<TokenData | null>; /** * Delete token data */ abstract deleteToken(): Promise<void>; /** * Encrypt token data if encryption key is provided */ protected encryptIfNeeded(data: string): Promise<string>; /** * Decrypt token data if encryption key is provided */ protected decryptIfNeeded(data: string): Promise<string>; } /** * Main Connector class that orchestrates OAuth service and persistence strategy */ declare class Connector { private oauthService; private storageStrategy?; private tokenManager; private logger; onFetchingAccessToken?: OnFetchingAccessTokenCallback; onTokenRefreshed?: OnTokenRefreshedCallback; onTokenError?: OnTokenErrorCallback; constructor(oauthService: OAuthService, storageStrategy?: StorageStrategy, // Make optional options?: ConnectorOptions); /** * Get access token (auto-refreshes if expired) */ getAccessToken(): Promise<string>; /** * Manually refresh token */ refreshToken(): Promise<TokenData>; /** * Get current token data */ getTokenData(): Promise<TokenData | null>; /** * Get authorization URL for initial OAuth flow */ getAuthorizationUrl(redirectUri: string, scopes?: string[]): string; /** * Exchange authorization code for tokens */ exchangeCodeForTokens(code: string, redirectUri: string): Promise<TokenData>; /** * Delete stored token */ deleteToken(): Promise<void>; /** * Start background sync */ startBackgroundSync(): void; /** * Stop background sync */ stopBackgroundSync(): void; /** * Cleanup resources */ destroy(): void; } /** * Local file system storage strategy */ declare class LocalStorageStrategy extends StorageStrategy { private filePath; constructor(config: LocalStorageConfig, logger?: Logger); /** * Save token to local file */ saveToken(tokenData: TokenData): Promise<void>; /** * Load token from local file */ loadToken(): Promise<TokenData | null>; /** * Delete token file */ deleteToken(): Promise<void>; } /** * Remote storage strategy */ declare class RemoteStorageStrategy extends StorageStrategy { private onUpload; private onDownload; constructor(config: RemoteStorageConfig, logger?: Logger); /** * Save token using remote upload callback */ saveToken(tokenData: TokenData): Promise<void>; /** * Load token using remote download callback */ loadToken(): Promise<TokenData | null>; /** * Delete token from remote storage * Note: This requires onUpload to handle deletion (upload null/empty) */ deleteToken(): Promise<void>; } /** * Catalyst Cache storage strategy * * Stores tokens in Catalyst cache using HTTP requests */ declare class CatalystCacheStorageStrategy extends StorageStrategy { private httpReq?; private key; private httpClient; constructor(config?: CatalystCacheStorageConfig, logger?: Logger); private getApiUrl; private getReqHeaders; getCache(key: string): Promise<string | null>; setCache(key: string, value: string): Promise<void>; /** * Save token to Catalyst cache */ saveToken(tokenData: TokenData): Promise<void>; /** * Load token from Catalyst cache */ loadToken(): Promise<TokenData | null>; /** * Delete token from Catalyst cache */ deleteToken(): Promise<void>; } /** * Zoho OAuth service implementation */ declare class ZohoOAuth extends OAuthService { private zohoConfig; private authUrl; private refreshUrl; constructor(config: ZohoOauthConfig, logger?: Logger); /** * Refresh access token using Zoho's refresh token endpoint */ refreshAccessToken(refreshToken: string): Promise<TokenData>; /** * Get Zoho authorization URL */ getAuthorizationUrl(redirectUri: string, scopes?: string[]): string; /** * Exchange authorization code for tokens */ exchangeCodeForTokens(code: string, redirectUri: string): Promise<TokenData>; } /** * Google OAuth service implementation */ declare class GoogleOAuth extends OAuthService { constructor(config: ConnectorConfig, logger?: Logger); /** * Refresh access token using Google's refresh token endpoint */ refreshAccessToken(refreshToken: string): Promise<TokenData>; /** * Get Google authorization URL */ getAuthorizationUrl(redirectUri: string, scopes?: string[]): string; /** * Exchange authorization code for tokens */ exchangeCodeForTokens(code: string, redirectUri: string): Promise<TokenData>; } /** * Generic OAuth service implementation */ declare class OAuth extends OAuthService { constructor(config: ConnectorConfig, logger?: Logger); /** * Refresh access token using generic OAuth refresh flow */ refreshAccessToken(refreshToken: string): Promise<TokenData>; /** * Get authorization URL (generic implementation) */ getAuthorizationUrl(redirectUri: string, scopes?: string[]): string; /** * Exchange authorization code for tokens */ exchangeCodeForTokens(code: string, redirectUri: string): Promise<TokenData>; } /** * Token manager handles token refresh, expiry checks, and background sync */ declare class TokenManager { private oauthService; private storageStrategy?; private logger; private backgroundSyncInterval?; private backgroundSyncIntervalSecs?; private graceExpiryTimeSecs; private cachedTokenData; constructor(oauthService: OAuthService, storageStrategy?: StorageStrategy, // Make optional backgroundSyncIntervalInSecs?: number, // seconds - if provided, sync is enabled graceExpiryTimeInSecs?: number, // seconds - default 0 (refresh only when expired) logger?: Logger); /** * Check if token is expired or within grace period */ private isTokenExpired; /** * Get valid access token, refreshing if necessary * Checks in-memory cache first for performance */ getAccessToken(): Promise<string>; /** * Manually refresh token */ refreshToken(): Promise<TokenData>; /** * Start background token sync */ startBackgroundSync(): void; /** * Stop background token sync */ stopBackgroundSync(): void; /** * Get current token data (uses cache) */ getTokenData(): Promise<TokenData | null>; /** * Set cached token (used after exchangeCodeForTokens) */ setCachedToken(tokenData: TokenData): void; /** * Clear cached token */ clearCache(): void; /** * Cleanup resources */ destroy(): void; } export { type BaseOAuthConfig, type CatalystCacheStorageConfig, CatalystCacheStorageStrategy, Connector, type ConnectorConfig, type ConnectorOptions, EncryptionService, GoogleOAuth, HttpClient, type HttpClientOptions, type HttpClientResponse, type LocalStorageConfig, LocalStorageStrategy, LogLevel, Logger, OAuth, OAuthService, type OAuthTokenResponse, type OnFetchingAccessTokenCallback, type OnTokenErrorCallback, type OnTokenRefreshedCallback, type RemoteStorageConfig, RemoteStorageStrategy, StorageStrategy, type TokenData, TokenManager, ZohoOAuth, type ZohoOauthConfig };