-
Notifications
You must be signed in to change notification settings - Fork 1
Open
Description
Describe the feature you'd like to request
For local testing oauth, users need jwks public/private pairs. Let help them get those
Describe the solution you'd like
Add a script, maybe executable with npx @hypercerts-org/sdk-core generate-jwks
maybe something like this
#!/usr/bin/env tsx
/**
* Generate JWK keypair for ATProto OAuth
*
* This script generates an ES256 (P-256) keypair for use with ATProto OAuth.
* - Private keyset: Output to console for copying to .env
* - Public keyset: Written to public/jwks.json for serving via endpoint
*
* Usage:
* pnpm generate:jwks
*/
import { generateKeyPair, exportJWK } from "jose";
import { writeFileSync } from "fs";
import { join } from "path";
import { randomUUID } from "crypto";
async function generateJWKs() {
console.log("π Generating ES256 (P-256) keypair for ATProto OAuth...\n");
// Generate ES256 keypair
const { publicKey, privateKey } = await generateKeyPair("ES256", {
extractable: true,
});
// Generate a unique key ID
const kid = randomUUID();
// Export keys to JWK format
const publicJWK = await exportJWK(publicKey);
const privateJWK = await exportJWK(privateKey);
// Add required fields
publicJWK.kid = kid;
publicJWK.alg = "ES256";
publicJWK.use = "sig";
privateJWK.kid = kid;
privateJWK.alg = "ES256";
privateJWK.use = "sig";
// Create keysets
const privateKeyset = {
keys: [privateJWK],
};
const publicKeyset = {
keys: [publicJWK],
};
// Write public keyset to file
const publicPath = join(process.cwd(), "public", "jwks.json");
writeFileSync(publicPath, JSON.stringify(publicKeyset, null, 2));
console.log(`β
Public keyset written to: ${publicPath}\n`);
// Output private keyset for .env
console.log("π Copy this PRIVATE keyset to your .env.local file:");
console.log(
"ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ",
);
console.log(`ATPROTO_JWK_PRIVATE='${JSON.stringify(privateKeyset)}'`);
console.log(
"ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n",
);
console.log("β οΈ IMPORTANT:");
console.log(" 1. Add the ATPROTO_JWK_PRIVATE to your .env.local file");
console.log(" 2. NEVER commit the private keyset to version control");
console.log(" 3. The public keyset (public/jwks.json) is safe to commit");
console.log(
" 4. Generate new keys for each environment (dev/staging/prod)\n",
);
console.log("π Also add this to your .env.local:");
console.log(
"ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ",
);
console.log('NEXT_PUBLIC_ATPROTO_JWKS_URI="http://localhost:3000/jwks.json"');
console.log(
"ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n",
);
console.log("β¨ JWK generation complete!\n");
}
generateJWKs().catch((error) => {
console.error("β Error generating JWKs:", error);
process.exit(1);
});Describe alternatives you've considered
.
Metadata
Metadata
Assignees
Labels
No labels