#!/bin/node import { SignJWT } from "jose" import { createPrivateKey } from "crypto" if (process.argv.includes("--help") || process.argv.includes("-h")) { console.log(` Creates a JWT from the components found at Apple. By default, the JWT has a 6 months expiry date. Read more: https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens#3262048 Usage: node apple.mjs [--kid] [--iss] [--private_key] [--sub] [--expires_in] [--exp] Options: --help Print this help message --kid, --key_id The key id of the private key --iss, --team_id The Apple team ID --private_key The private key to use to sign the JWT. (Starts with -----BEGIN PRIVATE KEY-----) --sub, --client_id The client id to use in the JWT. --expires_in Number of seconds from now when the JWT should expire. Defaults to 6 months. --exp Future date in seconds when the JWT expires `) } else { const args = process.argv.slice(2).reduce((acc, arg, i) => { if (arg.match(/^--\w/)) { const key = arg.replace(/^--/, "").toLowerCase() acc[key] = process.argv[i + 3] } return acc }, {}) const { team_id, iss = team_id, private_key, client_id, sub = client_id, key_id, kid = key_id, expires_in = 86400 * 180, exp = Math.ceil(Date.now() / 1000) + expires_in, } = args /** * How long is the secret valid in seconds. * @default 15780000 */ const expiresAt = Math.ceil(Date.now() / 1000) + expires_in const expirationTime = exp ?? expiresAt console.log(` Apple client secret generated. Valid until: ${new Date(expirationTime * 1000)} ${await new SignJWT({}) .setAudience("https://appleid.apple.com") .setIssuer(iss) .setIssuedAt() .setExpirationTime(expirationTime) .setSubject(sub) .setProtectedHeader({ alg: "ES256", kid }) .sign(createPrivateKey(private_key.replace(/\\n/g, "\n")))}`) }