From eab9188273bad9fb7d3410d369ca5ffc1ad6fbd9 Mon Sep 17 00:00:00 2001 From: Evan Jarrett Date: Fri, 10 Oct 2025 15:16:15 -0500 Subject: [PATCH] more oauth fixes for hold and appview --- cmd/appview/serve.go | 16 ++++++++++++++++ cmd/hold/main.go | 22 ++++++++++++++++------ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/cmd/appview/serve.go b/cmd/appview/serve.go index 2057d56..461b2bc 100644 --- a/cmd/appview/serve.go +++ b/cmd/appview/serve.go @@ -3,6 +3,7 @@ package main import ( "context" "database/sql" + "encoding/json" "fmt" "html/template" "net/http" @@ -201,6 +202,20 @@ func serveRegistry(cmd *cobra.Command, args []string) error { mux.HandleFunc("/auth/oauth/authorize", oauthServer.ServeAuthorize) mux.HandleFunc("/auth/oauth/callback", oauthServer.ServeCallback) + // OAuth client metadata endpoint + mux.HandleFunc("/client-metadata.json", func(w http.ResponseWriter, r *http.Request) { + // Get the client config from the OAuth app + config := oauth.NewClientConfig(baseURL) + metadata := config.ClientMetadata() + + // Serve as JSON + w.Header().Set("Content-Type", "application/json") + w.Header().Set("Access-Control-Allow-Origin", "*") + if err := json.NewEncoder(w).Encode(metadata); err != nil { + http.Error(w, "Failed to encode metadata", http.StatusInternalServerError) + } + }) + // Note: Indigo handles OAuth state cleanup internally via its store // Mount auth endpoints if enabled @@ -227,6 +242,7 @@ func serveRegistry(cmd *cobra.Command, args []string) error { fmt.Printf(" - Device Auth: /auth/device/token\n") fmt.Printf(" - OAuth: /auth/oauth/authorize\n") fmt.Printf(" - OAuth: /auth/oauth/callback\n") + fmt.Printf(" - OAuth Meta: /client-metadata.json\n") } // Create HTTP server diff --git a/cmd/hold/main.go b/cmd/hold/main.go index cfacc69..6718b1a 100644 --- a/cmd/hold/main.go +++ b/cmd/hold/main.go @@ -763,6 +763,16 @@ func main() { mux.HandleFunc("/put-presigned-url", service.HandlePutPresignedURL) mux.HandleFunc("/move", service.HandleMove) + // Pre-register OAuth callback route (will be populated by auto-registration) + var oauthCallbackHandler http.HandlerFunc + mux.HandleFunc("/auth/oauth/callback", func(w http.ResponseWriter, r *http.Request) { + if oauthCallbackHandler != nil { + oauthCallbackHandler(w, r) + } else { + http.Error(w, "OAuth callback not initialized", http.StatusServiceUnavailable) + } + }) + // OAuth client metadata endpoint for ATProto OAuth // The hold service serves its metadata at /client-metadata.json // This is referenced by its client ID URL @@ -823,7 +833,7 @@ func main() { // Auto-register if owner DID is set (now that server is running) if cfg.Registration.OwnerDID != "" { - if err := service.AutoRegister(); err != nil { + if err := service.AutoRegister(&oauthCallbackHandler); err != nil { log.Printf("WARNING: Auto-registration failed: %v", err) log.Printf("You can register manually later using the /register endpoint") } else { @@ -974,7 +984,7 @@ func (s *HoldService) isHoldRegistered(ctx context.Context, did, pdsEndpoint, pu // AutoRegister registers this hold service in the owner's PDS // Checks if already registered first, then does OAuth if needed -func (s *HoldService) AutoRegister() error { +func (s *HoldService) AutoRegister(callbackHandler *http.HandlerFunc) error { reg := &s.config.Registration publicURL := s.config.Server.PublicURL @@ -1033,11 +1043,11 @@ func (s *HoldService) AutoRegister() error { log.Printf("Starting OAuth registration for hold service") log.Printf("Public URL: %s", publicURL) - return s.registerWithOAuth(publicURL, handle, reg.OwnerDID, pdsEndpoint) + return s.registerWithOAuth(publicURL, handle, reg.OwnerDID, pdsEndpoint, callbackHandler) } // registerWithOAuth performs OAuth flow and registers the hold -func (s *HoldService) registerWithOAuth(publicURL, handle, did, pdsEndpoint string) error { +func (s *HoldService) registerWithOAuth(publicURL, handle, did, pdsEndpoint string, callbackHandler *http.HandlerFunc) error { // Define the scopes we need for hold registration holdScopes := []string{ "atproto", @@ -1078,8 +1088,8 @@ func (s *HoldService) registerWithOAuth(publicURL, handle, did, pdsEndpoint stri handle, holdScopes, // Pass hold-specific scopes func(handler http.HandlerFunc) error { - // Register callback on existing server (persistent server pattern) - http.HandleFunc("/auth/oauth/callback", handler) + // Populate the pre-registered callback handler + *callbackHandler = handler return nil }, func(authURL string) error {