feat: generate secrets
parent
b3554c1310
commit
76ac7fe403
@ -0,0 +1,56 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
/**
|
||||||
|
* Helper CLI to generate SESSION_SECRET and STATE_SIGNING_SECRET values.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* node scripts/generate-session-secrets.js
|
||||||
|
*
|
||||||
|
* Optional flags:
|
||||||
|
* --session-bytes=<number> (default: 48)
|
||||||
|
* --state-bytes=<number> (default: 32)
|
||||||
|
* --derive-state (derive STATE_SIGNING_SECRET from SESSION_SECRET)
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { randomBytes } = require('node:crypto');
|
||||||
|
|
||||||
|
const defaults = {
|
||||||
|
sessionBytes: 48,
|
||||||
|
stateBytes: 32,
|
||||||
|
deriveState: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const options = process.argv.slice(2).reduce((acc, arg) => {
|
||||||
|
if (arg.startsWith('--session-bytes=')) {
|
||||||
|
acc.sessionBytes = parseInt(arg.split('=')[1], 10);
|
||||||
|
} else if (arg.startsWith('--state-bytes=')) {
|
||||||
|
acc.stateBytes = parseInt(arg.split('=')[1], 10);
|
||||||
|
} else if (arg === '--derive-state') {
|
||||||
|
acc.deriveState = true;
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, { ...defaults });
|
||||||
|
|
||||||
|
const validateBytes = (value, flagName) => {
|
||||||
|
if (!Number.isInteger(value) || value <= 0) {
|
||||||
|
console.error(`Invalid value for ${flagName}. Expected a positive integer, received: ${value}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
validateBytes(options.sessionBytes, '--session-bytes');
|
||||||
|
if (!options.deriveState) {
|
||||||
|
validateBytes(options.stateBytes, '--state-bytes');
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateSecret = (bytes) => randomBytes(bytes).toString('base64');
|
||||||
|
|
||||||
|
const sessionSecret = generateSecret(options.sessionBytes);
|
||||||
|
const stateSecret = options.deriveState
|
||||||
|
? `${sessionSecret}-state-signing`
|
||||||
|
: generateSecret(options.stateBytes);
|
||||||
|
|
||||||
|
console.log(`SESSION_SECRET=${sessionSecret}`);
|
||||||
|
console.log(`STATE_SIGNING_SECRET=${stateSecret}`);
|
||||||
|
|
||||||
|
console.log('\n# Copy the values above into your deployment secret store (.env, Vault, etc.).');
|
||||||
|
console.log('# Keep them private and rotate on a regular schedule.');
|
||||||
Loading…
Reference in New Issue