Social Annotations in the Atmosphere
15
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix(oauth): add explicit routes for OAuth callbacks to prevent 301 redirects

Problem:
- Commit 96ab9b9 changed OAuth callbacks from .html files to directory structure
- Go's http.FileServer returns 301 redirect for /oauth/callback -> /oauth/callback/
- browser.identity.launchWebAuthFlow() rejects any HTTP redirects
- Result: Extension OAuth login fails with 'Authorization page could not be loaded'

Root Cause:
- FileServer requires trailing slash for directories (standard behavior)
- OAuth redirect URIs in client-metadata.json have no trailing slash
- Mismatch causes 301 redirect which breaks OAuth flow

Solution:
- Add explicit chi routes for /oauth/callback and /oauth/ff/callback
- Serve index.html directly without FileServer's redirect behavior
- Keeps directory structure organized while serving clean URLs

Testing:
- Local: curl http://localhost:8080/oauth/callback returns 200 (not 301)
- With query params: ?code=test&state=test returns 200 (not 301)
- Firefox callback: /oauth/ff/callback returns 200 (not 301)

Fixes:
- Chrome extension OAuth login
- Firefox extension OAuth login
- Maintains compatibility with existing redirect URIs

+17 -4
+17 -4
server/cmd/server/main.go
··· 4 4 "log" 5 5 "net/http" 6 6 "os" 7 + "path/filepath" 7 8 8 9 // AMPDO: change to pkg.sealight.xyz 9 10 // THEN: help me configure the DNS so the above points to: ··· 69 70 }) 70 71 r.Get("/health", handler.Health) 71 72 72 - // Serve static files for everything else 73 + // Static files configuration 73 74 publicDir := getEnv("PUBLIC_DIR", "../landing") 74 75 log.Printf("Serving static files from %s", publicDir) 75 - 76 + 77 + // OAuth callback routes - serve directly to avoid 301 redirects from FileServer 78 + // These must be served without redirects for browser.identity.launchWebAuthFlow to work 79 + r.Get("/oauth/callback", func(w http.ResponseWriter, req *http.Request) { 80 + http.ServeFile(w, req, filepath.Join(publicDir, "oauth/callback/index.html")) 81 + }) 82 + r.Get("/oauth/ff/callback", func(w http.ResponseWriter, req *http.Request) { 83 + http.ServeFile(w, req, filepath.Join(publicDir, "oauth/ff/callback/index.html")) 84 + }) 85 + 76 86 // Create final handler that checks API routes first, then static files 77 87 fileServer := http.FileServer(http.Dir(publicDir)) 78 88 finalHandler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 79 - // Try API routes first 80 - if req.URL.Path == "/health" || (len(req.URL.Path) >= 4 && req.URL.Path[:4] == "/api") { 89 + // Try API routes and OAuth callbacks first 90 + if req.URL.Path == "/health" || 91 + (len(req.URL.Path) >= 4 && req.URL.Path[:4] == "/api") || 92 + req.URL.Path == "/oauth/callback" || 93 + req.URL.Path == "/oauth/ff/callback" { 81 94 r.ServeHTTP(w, req) 82 95 return 83 96 }