UNPKG

webpods

Version:

Append-only log service with OAuth authentication

127 lines 4.22 kB
/** * OAuth provider configuration using config.json */ import { Issuer } from "openid-client"; import { createLogger } from "../logger.js"; import { getConfig, } from "../config-loader.js"; const logger = createLogger("webpods:auth:oauth-config"); // Cache for OAuth clients const clientCache = new Map(); // Cache for provider configs let providerConfigs = null; /** * Load OAuth provider configurations from config.json */ export function loadProviderConfigs() { if (providerConfigs) { return providerConfigs; } providerConfigs = new Map(); const config = getConfig(); if (!config.oauth || !config.oauth.providers) { logger.warn("No OAuth providers configured"); return providerConfigs; } // Use public URL for OAuth callbacks const baseUrl = config.server.publicUrl || "http://localhost:3000"; for (const provider of config.oauth.providers) { // Build full config with redirect URI // Use explicit callbackUrl if provided, otherwise construct from baseUrl const fullConfig = { ...provider, redirectUri: provider.callbackUrl || `${baseUrl}/auth/${provider.id}/callback`, }; providerConfigs.set(provider.id, fullConfig); logger.info("OAuth provider configured", { provider: provider.id }); } return providerConfigs; } /** * Get or create OAuth client for a provider */ export async function getOAuthClient(providerId) { // Check cache first if (clientCache.has(providerId)) { return clientCache.get(providerId); } const configs = loadProviderConfigs(); const config = configs.get(providerId); if (!config) { throw new Error(`OAuth provider ${providerId} not configured`); } let issuer; if (config.issuer) { // Try OIDC discovery try { issuer = await Issuer.discover(config.issuer); logger.info("OIDC discovery successful", { provider: providerId }); } catch (error) { logger.warn("OIDC discovery failed, using manual config", { provider: providerId, error, }); // Fall back to manual configuration if (!config.authUrl || !config.tokenUrl) { throw new Error(`OAuth provider ${providerId} discovery failed and no manual endpoints configured`); } issuer = new Issuer({ issuer: config.issuer, authorization_endpoint: config.authUrl, token_endpoint: config.tokenUrl, userinfo_endpoint: config.userinfoUrl, }); } } else { // Manual configuration if (!config.authUrl || !config.tokenUrl || !config.userinfoUrl) { throw new Error(`OAuth provider ${providerId} missing required endpoints`); } issuer = new Issuer({ issuer: providerId, authorization_endpoint: config.authUrl, token_endpoint: config.tokenUrl, userinfo_endpoint: config.userinfoUrl, }); } const client = new issuer.Client({ client_id: config.clientId, client_secret: config.clientSecret, redirect_uris: [config.redirectUri], response_types: ["code"], }); // Cache the client clientCache.set(providerId, client); logger.info("OAuth client initialized", { provider: providerId }); return client; } /** * Get list of configured OAuth providers */ export function getConfiguredProviders() { const configs = loadProviderConfigs(); return Array.from(configs.keys()); } /** * Check if a provider is configured */ export function isProviderConfigured(providerId) { const configs = loadProviderConfigs(); return configs.has(providerId); } /** * Get provider configuration */ export function getProviderConfig(providerId) { const configs = loadProviderConfigs(); return configs.get(providerId); } /** * Get default OAuth provider */ export function getDefaultProvider() { const config = getConfig(); return config.oauth.defaultProvider || getConfiguredProviders()[0]; } //# sourceMappingURL=oauth-config.js.map