{"id":10530,"library":"aws-cloudfront-sign","title":"AWS CloudFront URL Signature Utility","description":"`aws-cloudfront-sign` is a JavaScript utility module designed to simplify the generation of signed URLs and signed cookies for Amazon CloudFront distributions. It addresses the historical gap where the official AWS SDK for JavaScript did not directly provide methods for CloudFront-specific URL signing, distinct from S3 signing. The package is currently stable at version 3.0.2, released in April 2026, with a release cadence that appears reactive to feature additions, bug fixes, and maintenance, rather than on a strict schedule. Key differentiators include its focused purpose on CloudFront signing, providing a straightforward API for both URL and cookie signing, and its compatibility with modern Node.js environments (v18+), including full TypeScript and ES Modules support since v3.0.0. While the AWS SDK for JavaScript now offers CloudFront signing capabilities, `aws-cloudfront-sign` remains a viable and actively maintained alternative.","status":"active","version":"3.0.2","language":"javascript","source_language":"en","source_url":"https://github.com/jasonsims/aws-cloudfront-sign","tags":["javascript","aws","CloudFront","signed URL","typescript"],"install":[{"cmd":"npm install aws-cloudfront-sign","lang":"bash","label":"npm"},{"cmd":"yarn add aws-cloudfront-sign","lang":"bash","label":"yarn"},{"cmd":"pnpm add aws-cloudfront-sign","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Since v3.0.0, the package primarily supports ES Modules. For CJS environments or older Node.js versions, `const { getSignedUrl } = require('aws-cloudfront-sign');` is used.","wrong":"const getSignedUrl = require('aws-cloudfront-sign').getSignedUrl;","symbol":"getSignedUrl","correct":"import { getSignedUrl } from 'aws-cloudfront-sign';"},{"note":"This is a named export. Ensure to use destructuring for `import` statements.","wrong":"import getSignedCookies from 'aws-cloudfront-sign';","symbol":"getSignedCookies","correct":"import { getSignedCookies } from 'aws-cloudfront-sign';"},{"note":"TypeScript types for options are exported directly from the main package since v3.0.0. The `aws-cloudfront-sign/types` path shown in some older documentation or examples is no longer necessary.","wrong":"import { SignatureOptions } from 'aws-cloudfront-sign/types';","symbol":"SignatureOptions","correct":"import type { SignatureOptions } from 'aws-cloudfront-sign';"}],"quickstart":{"code":"import { getSignedUrl, getSignedCookies } from 'aws-cloudfront-sign';\nimport * as path from 'path';\nimport * as fs from 'fs';\n\n// Replace with your actual CloudFront distribution URL\nconst cloudfrontUrl = 'https://d1234.cloudfront.net/path/to/my/asset.jpg';\n\n// Your CloudFront key pair ID\nconst keypairId = process.env.CLOUDFRONT_KEY_PAIR_ID ?? 'APKAEIBAZAZAZAZAZAZA';\n\n// Path to your private key file or the key content as a string\nconst privateKeyPath = process.env.CLOUDFRONT_PRIVATE_KEY_PATH ?? path.resolve(__dirname, 'pk-APKAEIBAZAZAZAZAZAZA.pem');\nlet privateKeyString: string;\ntry {\n  privateKeyString = fs.readFileSync(privateKeyPath, 'utf8');\n} catch (error) {\n  console.error(`Error reading private key file at ${privateKeyPath}:`, error);\n  // Fallback for demonstration if file not found, but this should be valid in a real app\n  privateKeyString = process.env.CLOUDFRONT_PRIVATE_KEY_STRING ??\n    '-----BEGIN RSA PRIVATE KEY-----\\n' +\n    'MIIJKAIBAAKCAgEAwGPMqEvxPYQIffDimM9t3A7Z4aBFAUvLiITzmHRc4UPwryJp\\n' +\n    'EVi3C0sQQKBHlq2IOwrmqNiAk31/uh4...[truncated]...QIDAQABAoIBAB2zE\\n' +\n    '-----END RSA PRIVATE KEY-----';\n}\n\n// Options for signing, including an expiration time (e.g., 1 hour from now)\nconst oneHourFromNow = Date.now() + 60 * 60 * 1000; // 1 hour in milliseconds\n\nconst options = {\n  keypairId: keypairId,\n  privateKeyString: privateKeyString,\n  expireTime: oneHourFromNow,\n  // ipRange: '192.168.1.0/24' // Optional: restrict access to a specific IP range\n};\n\nasync function signCloudFrontResources() {\n  try {\n    // 1. Get a signed URL\n    const signedUrl = getSignedUrl(cloudfrontUrl, options);\n    console.log('Generated Signed URL:', signedUrl);\n\n    // 2. Get signed cookies\n    const signedCookies = getSignedCookies(cloudfrontUrl, options);\n    console.log('Generated Signed Cookies:', signedCookies);\n\n    // Example of how you might set cookies in a response (e.g., Express.js)\n    // res.cookie('CloudFront-Policy', signedCookies['CloudFront-Policy'], { httpOnly: true, secure: true });\n    // res.cookie('CloudFront-Signature', signedCookies['CloudFront-Signature'], { httpOnly: true, secure: true });\n    // res.cookie('CloudFront-Key-Pair-Id', signedCookies['CloudFront-Key-Pair-Id'], { httpOnly: true, secure: true });\n\n  } catch (error) {\n    console.error('Error signing CloudFront resources:', error);\n  }\n}\n\nsignCloudFrontResources();","lang":"typescript","description":"Demonstrates how to generate both signed URLs and signed cookies for a CloudFront distribution, using a private key and key pair ID with an explicit expiration time."},"warnings":[{"fix":"Update `expireTime` values to use milliseconds, a `Date` instance, or a `moment` object instead of raw seconds.","message":"The `expireTime` option changed its unit from seconds to milliseconds, a `Date` object, or a `moment` object.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Migrate away from RTMP streaming. If still needed, ensure to manage RTMP assets with an alternative distribution method as CloudFront no longer supports it.","message":"The `getSignedRTMPUrl` API is deprecated and its underlying technology (RTMP) has been discontinued by Amazon CloudFront.","severity":"deprecated","affected_versions":">=2.1.0"},{"fix":"Ensure the `privateKeyString` is the exact content of the `.pem` file, including all newlines. If loading from an environment variable, ensure `\\n` characters are properly encoded/decoded.","message":"When providing `privateKeyString` directly, it must include the full PEM-encoded string with newline characters (`\\n`) between sections.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Upgrade your Node.js environment to version 18 LTS or newer. Older Node.js versions are no longer supported.","message":"Minimum Node.js engine requirement updated to version 18 or higher.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Review existing code that relies on the default expiration. While generally a positive change, explicitly set `expireTime` if a shorter duration is required.","message":"The default `expireTime` for signed URLs and cookies was increased from 30 seconds to 30 minutes to mitigate 'Access Denied' errors caused by clock drift.","severity":"gotcha","affected_versions":">=2.2.1"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Increase `expireTime` or ensure `expireTime` is set sufficiently far in the future. Verify server clock synchronization. Check CloudFront distribution settings and key pair configuration.","cause":"Signed URL/cookie has expired, or there's a significant clock drift between the server generating the signature and CloudFront.","error":"Access Denied"},{"fix":"Ensure the `privateKeyString` is the exact content of the `.pem` file, including all newlines. If loading from an environment variable, ensure `\\n` characters are properly encoded/decoded.","cause":"The `privateKeyString` is malformed, missing the `-----BEGIN RSA PRIVATE KEY-----` or `-----END RSA PRIVATE KEY-----` headers, or newlines are incorrectly handled.","error":"Error: error:0906D06C:PEM routines:PEM_read_bio:no start line"},{"fix":"For ES Modules (Node.js >=18, `type: \"module\"` in `package.json`), use `import { getSignedUrl } from 'aws-cloudfront-sign';`. For CommonJS, use `const { getSignedUrl } = require('aws-cloudfront-sign');`.","cause":"Attempting to use CommonJS `require` syntax in a pure ESM project, or vice-versa, or incorrect named import.","error":"TypeError: getSignedUrl is not a function"}],"ecosystem":"npm"}