- Implement full OAuth 2.0 with PKCE using haileyok/atproto-oauth-golang - Backend For Frontend (BFF) pattern: tokens stored server-side only - AES-256-GCM encrypted session cookies - Auto token refresh when near expiry - Restrict access to allowed handles (1440.news, wehrv.bsky.social) - Add genkey utility for generating OAuth configuration - Generic error messages to prevent handle enumeration - Server-side logging of failed login attempts for security monitoring New files: - oauth.go: OAuth client wrapper and DID/handle resolution - oauth_session.go: Session management with encrypted cookies - oauth_middleware.go: RequireAuth middleware for route protection - oauth_handlers.go: Login, callback, logout, metadata endpoints - cmd/genkey/main.go: Generate OAuth secrets and JWK keypair - oauth.env.example: Configuration template Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
46 lines
1.0 KiB
Go
46 lines
1.0 KiB
Go
// genkey generates an ES256 JWK keypair for OAuth client authentication
|
|
package main
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/haileyok/atproto-oauth-golang/helpers"
|
|
)
|
|
|
|
func main() {
|
|
fmt.Println("Generating OAuth configuration...")
|
|
fmt.Println()
|
|
|
|
// Generate cookie secret
|
|
cookieSecret := make([]byte, 32)
|
|
if _, err := rand.Read(cookieSecret); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error generating cookie secret: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Generate ES256 JWK
|
|
key, err := helpers.GenerateKey(nil)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error generating JWK: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Marshal JWK to JSON
|
|
keyJSON, err := json.Marshal(key)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error marshaling JWK: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
fmt.Println("Add these values to your oauth.env file:")
|
|
fmt.Println()
|
|
fmt.Printf("OAUTH_COOKIE_SECRET=%s\n", hex.EncodeToString(cookieSecret))
|
|
fmt.Printf("OAUTH_PRIVATE_JWK=%s\n", string(keyJSON))
|
|
fmt.Println()
|
|
fmt.Println("Keep these values secret!")
|
|
}
|