UNPKG

zerokey

Version:

Zero-knowledge cross-domain secret sharing library using ECDH encryption

127 lines (125 loc) 4.46 kB
/** * Validated and required parameters for the zero-knowledge secret sharing flow. * These are stored globally after validation for use during the secret transfer process. */ interface ZerokeyParams { publicKey: string; redirect: string; state: string; } /** * Configuration options for the secret server. */ interface SecretServerOptions { /** * Optional callback to validate the redirect URL. * If provided, must return true for the URL to be accepted. * This provides an additional security layer to prevent unauthorized domains * from requesting secrets. * * @param url - The redirect URL to validate * @returns True if the URL should be allowed, false otherwise * * @example * // Only allow specific domain * validateCallbackUrl: (url) => url.startsWith('https://myapp.com') * * @example * // Allow multiple domains * validateCallbackUrl: (url) => { * const allowed = ['https://app1.com', 'https://app2.com']; * return allowed.some(domain => url.startsWith(domain)); * } */ validateCallbackUrl?: (url: string) => boolean; } /** * Global window extension to store validated zerokey parameters. * This allows the parameters to persist between initialization and secret setting. */ declare global { interface Window { zerokeyParams?: ZerokeyParams; } } /** * Initializes the zero-knowledge secret server handler. * This function should be called when the secret server page loads. * It parses the query parameters, validates them, and prepares the system to receive a secret. * * The function expects the following query parameters: * - publicKey: RSA public key for encrypting the secret * - redirect: URL to redirect to after processing * - state: CSRF protection state parameter * * If a secret has already been set via `setSecret()` before initialization, * it will immediately process and redirect with the encrypted secret. * * @param {SecretServerOptions} options - Optional configuration for the secret server * @param {Function} options.validateCallbackUrl - Optional callback to validate redirect URLs * @returns {void} * * @throws {Error} Logs errors if required parameters are missing or invalid * * @example * // Basic initialization * import { initSecretServer } from 'zerokey/server'; * * document.addEventListener('DOMContentLoaded', () => { * initSecretServer(); * }); * * @example * // With domain validation for security * initSecretServer({ * validateCallbackUrl: (url) => url.startsWith('https://myapp.com') * }); * * @example * // Allow multiple trusted domains * initSecretServer({ * validateCallbackUrl: (url) => { * const trustedDomains = [ * 'https://app.example.com', * 'https://staging.example.com', * 'http://localhost:3000' // for development * ]; * return trustedDomains.some(domain => url.startsWith(domain)); * } * }); */ declare function initSecretServer(options?: SecretServerOptions): void; /** * Sets the secret that will be encrypted and transferred to the requesting application. * This function should be called after the user has authenticated and the server * has determined what secret (e.g., API key, token) to share. * * If `initSecretServer()` has already been called and valid parameters are present, * this will immediately encrypt the secret and redirect. Otherwise, it stores the * secret until initialization occurs. * * The secret is encrypted client-side using the public key provided in the query parameters, * ensuring the secret server never sees the public key and the requesting app never sees * the plaintext secret - maintaining zero-knowledge properties. * * @param {string} secret - The plaintext secret to be encrypted and transferred * @returns {void} * * @throws {Error} Logs an error if the secret is empty * * @example * // After user authentication: * const userApiKey = await generateApiKeyForUser(userId); * setSecret(userApiKey); * // User is automatically redirected with encrypted secret * * @example * // In a form submission handler: * document.getElementById('secret-form').addEventListener('submit', (e) => { * e.preventDefault(); * const secret = document.getElementById('secret-input').value; * setSecret(secret); * }); */ declare function setSecret(secret: string): void; export { initSecretServer, setSecret };