UNPKG

appstore-cli

Version:

A command-line interface (CLI) to interact with the Apple App Store Connect API.

74 lines (61 loc) 2.08 kB
import jwt from 'jsonwebtoken'; import crypto from 'crypto'; import { Config, getPrivateKey } from './config.js'; export async function generateJwt(config: Config): Promise<string> { // Validate required configuration fields if (!config.issuerId) { throw new Error('Issuer ID is required but not provided'); } if (!config.keyId) { throw new Error('Key ID is required but not provided'); } // Get private key from secure storage const privateKey = await getPrivateKey(config); if (!privateKey) { throw new Error('Private key is required but not provided'); } // Create a proper key object for the JWT library let keyObject; try { keyObject = crypto.createPrivateKey(privateKey); } catch (keyError) { // Sanitize error message to avoid exposing key information throw new Error('Invalid private key format'); } const payload = { iss: config.issuerId, exp: Math.floor(Date.now() / 1000) + (20 * 60), // 20 minutes aud: 'appstoreconnect-v1' }; // Validate payload fields if (!payload.iss) { throw new Error('Issuer ID is required in JWT payload'); } const currentTime = Math.floor(Date.now() / 1000); if (!payload.exp || payload.exp <= currentTime) { throw new Error('Invalid expiration time in JWT payload'); } // Ensure expiration doesn't exceed 30 minutes (with 10-minute buffer) if (payload.exp - currentTime > 30 * 60) { throw new Error('Token expiration time exceeds maximum allowed duration'); } const options: jwt.SignOptions = { algorithm: 'ES256', header: { alg: 'ES256', kid: config.keyId, typ: 'JWT' } }; try { const token = jwt.sign(payload, keyObject, options); // Additional validation that token was created successfully if (!token || typeof token !== 'string') { throw new Error('Failed to generate JWT token'); } return token; } catch (signError) { // Sanitize error message to avoid exposing key information throw new Error('Failed to sign JWT token'); } }