Skip to content

Instantly share code, notes, and snippets.

@JesseVelden
Last active February 13, 2026 18:20
Show Gist options
  • Select an option

  • Save JesseVelden/e11aaf876d9409b560f873bd156564ab to your computer and use it in GitHub Desktop.

Select an option

Save JesseVelden/e11aaf876d9409b560f873bd156564ab to your computer and use it in GitHub Desktop.
Retrieve JWT to Vault JSON

Retrieve JWT to Vault JSON

Usable by just using npx:

# Just start listening on http://localhost:12765/ext-login 
npx https://gist.github.com/JesseVelden/e11aaf876d9409b560f873bd156564ab

# Also opening an external link, and not displaying a startup message:
npx https://gist.github.com/JesseVelden/e11aaf876d9409b560f873bd156564ab -s -u https://example.com?callback=http://localhost:12765/ext-login

# Storing the JWT in a cache file
npx https://gist.github.com/JesseVelden/e11aaf876d9409b560f873bd156564ab -s -u https://example.com?callback=http://localhost:12765/ext-login -c /path/to/.jwt-cache.json
#!/usr/bin/env node
import { spawn } from 'node:child_process';
import * as http from 'node:http';
import * as fs from 'node:fs/promises';
import * as path from 'node:path';
const LOCAL_JWT_REDIRECT_PORT = 12765;
let silentMode = false;
let jwtCachePath = null;
let loginUrl = null;
const args = process.argv.slice(2); // Skip 'node' and script path
for (let i = 0; i < args.length; i++) {
const arg = args[i];
const value = args[i + 1];
if (arg === '-u' && value !== undefined && isUrl(value)) {
loginUrl = value;
i++;
} else if (arg === '-c' && value !== undefined) {
jwtCachePath = path.resolve(value);
i++;
} else if (arg === '-s') {
silentMode = true;
}
}
function decodeJwtPayload(token) {
const parts = token.split('.');
if (parts.length !== 3) return null;
const payload = parts[1].replace(/-/g, '+').replace(/_/g, '/');
const padded = payload.padEnd(payload.length + ((4 - (payload.length % 4)) % 4), '=');
try {
const json = Buffer.from(padded, 'base64').toString('utf8');
return JSON.parse(json);
} catch {
return null;
}
}
function isJwtValid(token) {
const payload = decodeJwtPayload(token);
if (!payload || typeof payload.exp !== 'number') return false;
const nowSeconds = Math.floor(Date.now() / 1000);
return payload.exp > nowSeconds;
}
async function readCachedJwt(cachePath) {
try {
const raw = await fs.readFile(cachePath, 'utf8');
const parsed = JSON.parse(raw);
if (parsed && typeof parsed.jwt === 'string' && isJwtValid(parsed.jwt)) {
return parsed.jwt;
}
return null;
} catch {
return null;
}
}
async function writeCachedJwt(cachePath, jwt) {
const payload = {
jwt,
savedAt: new Date().toISOString(),
};
await fs.writeFile(cachePath, JSON.stringify(payload, null, 2), 'utf8');
}
function isUrl(str) {
try {
new URL(str);
return true;
} catch {
return false;
}
}
async function retrieveJwtInteractive() {
if (loginUrl) {
// On Windows, 'start' opens the default browser
spawn(`start "" "${loginUrl}"`, { shell: true, stdio: 'ignore', detached: true });
}
return new Promise((resolve, reject) => {
const server = http.createServer(async (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
if (req.method === 'OPTIONS') {
res.writeHead(204); // No content
res.end();
return;
}
const requestUrl = new URL(req.url || '', `http://localhost:${LOCAL_JWT_REDIRECT_PORT}`);
if (requestUrl.pathname === '/ext-login') {
let body = '';
req.on('data', (chunk) => {
body += chunk.toString();
});
req.on('end', () => {
try {
const jsonBody = JSON.parse(body);
const jwt = jsonBody.jwt;
if (jwt) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Login success! You can close this window now.');
server.close(() => {
resolve(jwt);
});
} else {
const errMessage = 'Could not find JWT in the request body.';
console.error(errMessage);
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end(errMessage);
reject(new Error(errMessage));
}
} catch (error) {
const errMessage = 'Error in processing the JSON body.';
console.error(errMessage, error);
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end(errMessage);
reject(new Error(errMessage));
}
});
} else {
res.writeHead(404);
res.end();
}
});
server.listen(LOCAL_JWT_REDIRECT_PORT, async () => {
if (!silentMode) console.debug(`Local login HTTP server started on port ${LOCAL_JWT_REDIRECT_PORT}.`);
});
server.on('error', (err) => {
console.error('Error at local login HTTP server.', err);
reject(err);
});
});
}
(async () => {
const cachedJwt = jwtCachePath ? await readCachedJwt(jwtCachePath) : null;
const jwt = cachedJwt || (await retrieveJwtInteractive());
if (jwtCachePath && !cachedJwt) {
try {
await writeCachedJwt(jwtCachePath, jwt);
} catch (error) {
if (!silentMode) console.warn('Failed to write JWT cache file.', error);
}
}
const result = {
data: {
username: '',
password: jwt,
},
};
console.log(JSON.stringify(result, null, 2));
})().catch((error) => {
console.error('JWT flow failed.', error);
process.exitCode = 1;
});
{
"name": "@jessevelden/retrieve-jwt-to-vault-json",
"version": "1.0.0",
"type": "module",
"bin": "./index.js"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment