A community based topic aggregation platform built on atproto
1package main 2 3import ( 4 "crypto/ecdsa" 5 "crypto/elliptic" 6 "crypto/rand" 7 "encoding/json" 8 "fmt" 9 "log" 10 "os" 11 12 "github.com/lestrrat-go/jwx/v2/jwk" 13) 14 15// genjwks generates an ES256 keypair for OAuth client authentication 16// The private key is stored in the config/env, public key is served at /oauth/jwks.json 17// 18// Usage: 19// go run cmd/genjwks/main.go 20// 21// This will output a JSON private key that should be stored in OAUTH_PRIVATE_JWK 22func main() { 23 fmt.Println("Generating ES256 keypair for OAuth client authentication...") 24 25 // Generate ES256 (NIST P-256) private key 26 privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 27 if err != nil { 28 log.Fatalf("Failed to generate private key: %v", err) 29 } 30 31 // Convert to JWK 32 jwkKey, err := jwk.FromRaw(privateKey) 33 if err != nil { 34 log.Fatalf("Failed to create JWK from private key: %v", err) 35 } 36 37 // Set key parameters 38 if err := jwkKey.Set(jwk.KeyIDKey, "oauth-client-key"); err != nil { 39 log.Fatalf("Failed to set kid: %v", err) 40 } 41 if err := jwkKey.Set(jwk.AlgorithmKey, "ES256"); err != nil { 42 log.Fatalf("Failed to set alg: %v", err) 43 } 44 if err := jwkKey.Set(jwk.KeyUsageKey, "sig"); err != nil { 45 log.Fatalf("Failed to set use: %v", err) 46 } 47 48 // Marshal to JSON 49 jsonData, err := json.MarshalIndent(jwkKey, "", " ") 50 if err != nil { 51 log.Fatalf("Failed to marshal JWK: %v", err) 52 } 53 54 // Output instructions 55 fmt.Println("\n✅ ES256 keypair generated successfully!") 56 fmt.Println("\n📝 Add this to your .env.dev file:") 57 fmt.Println("\nOAUTH_PRIVATE_JWK='" + string(jsonData) + "'") 58 fmt.Println("\n⚠️ IMPORTANT:") 59 fmt.Println(" - Keep this private key SECRET") 60 fmt.Println(" - Never commit it to version control") 61 fmt.Println(" - Generate a new key for production") 62 fmt.Println(" - The public key will be automatically derived and served at /oauth/jwks.json") 63 64 // Optionally write to a file (not committed) 65 if len(os.Args) > 1 && os.Args[1] == "--save" { 66 filename := "oauth-private-key.json" 67 if err := os.WriteFile(filename, jsonData, 0600); err != nil { 68 log.Fatalf("Failed to write key file: %v", err) 69 } 70 fmt.Printf("\n💾 Private key saved to %s (remember to add to .gitignore!)\n", filename) 71 } 72}