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