A community based topic aggregation platform built on atproto
at main 2.9 kB view raw
1package routes 2 3import ( 4 "Coves/internal/api/middleware" 5 "Coves/internal/atproto/oauth" 6 "net/http" 7 "time" 8 9 "github.com/go-chi/chi/v5" 10 "github.com/go-chi/cors" 11) 12 13// RegisterOAuthRoutes registers OAuth-related endpoints on the router with dedicated rate limiting 14// OAuth endpoints have stricter rate limits to prevent: 15// - Credential stuffing attacks on login endpoints 16// - OAuth state exhaustion 17// - Refresh token abuse 18func RegisterOAuthRoutes(r chi.Router, handler *oauth.OAuthHandler, allowedOrigins []string) { 19 // Create stricter rate limiters for OAuth endpoints 20 // Login endpoints: 10 req/min per IP (credential stuffing protection) 21 loginLimiter := middleware.NewRateLimiter(10, 1*time.Minute) 22 23 // Refresh endpoint: 20 req/min per IP (slightly higher for legitimate token refresh) 24 refreshLimiter := middleware.NewRateLimiter(20, 1*time.Minute) 25 26 // Logout endpoint: 10 req/min per IP 27 logoutLimiter := middleware.NewRateLimiter(10, 1*time.Minute) 28 29 // OAuth metadata endpoints - public, no extra rate limiting (use global limit) 30 r.Get("/oauth/client-metadata.json", handler.HandleClientMetadata) 31 r.Get("/.well-known/oauth-protected-resource", handler.HandleProtectedResourceMetadata) 32 33 // OAuth flow endpoints - stricter rate limiting for authentication attempts 34 r.With(loginLimiter.Middleware).Get("/oauth/login", handler.HandleLogin) 35 r.With(loginLimiter.Middleware).Get("/oauth/mobile/login", handler.HandleMobileLogin) 36 37 // OAuth callback - needs CORS for potential cross-origin redirects from PDS 38 // Use login limiter since callback completes the authentication flow 39 r.With(corsMiddleware(allowedOrigins), loginLimiter.Middleware).Get("/oauth/callback", handler.HandleCallback) 40 41 // Mobile Universal Link callback route (fallback when app doesn't intercept) 42 // This route exists for iOS Universal Links and Android App Links. 43 // When properly configured, the mobile OS intercepts this URL and opens the app 44 // BEFORE the request reaches the server. If this handler is reached, it means 45 // Universal Links failed to intercept. 46 r.With(loginLimiter.Middleware).Get("/app/oauth/callback", handler.HandleMobileDeepLinkFallback) 47 48 // Session management - dedicated rate limits 49 r.With(logoutLimiter.Middleware).Post("/oauth/logout", handler.HandleLogout) 50 r.With(refreshLimiter.Middleware).Post("/oauth/refresh", handler.HandleRefresh) 51} 52 53// corsMiddleware creates a CORS middleware for OAuth callback with specific allowed origins 54func corsMiddleware(allowedOrigins []string) func(next http.Handler) http.Handler { 55 return cors.Handler(cors.Options{ 56 AllowedOrigins: allowedOrigins, // Only allow specific origins for OAuth callback 57 AllowedMethods: []string{"GET", "POST", "OPTIONS"}, 58 AllowedHeaders: []string{ 59 "Accept", 60 "Authorization", 61 "Content-Type", 62 "X-CSRF-Token", 63 }, 64 ExposedHeaders: []string{"Link"}, 65 AllowCredentials: true, 66 MaxAge: 300, // 5 minutes 67 }) 68}