A community based topic aggregation platform built on atproto
at main 70 lines 3.1 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 // Serve at root /oauth-client-metadata.json so OAuth screens show clean brand domain 31 r.Get("/oauth-client-metadata.json", handler.HandleClientMetadata) 32 r.Get("/oauth-client-keys.json", handler.HandleClientJWKS) 33 r.Get("/.well-known/oauth-protected-resource", handler.HandleProtectedResourceMetadata) 34 35 // OAuth flow endpoints - stricter rate limiting for authentication attempts 36 r.With(loginLimiter.Middleware).Get("/oauth/login", handler.HandleLogin) 37 r.With(loginLimiter.Middleware).Get("/oauth/mobile/login", handler.HandleMobileLogin) 38 39 // OAuth callback - needs CORS for potential cross-origin redirects from PDS 40 // Use login limiter since callback completes the authentication flow 41 r.With(corsMiddleware(allowedOrigins), loginLimiter.Middleware).Get("/oauth/callback", handler.HandleCallback) 42 43 // Mobile Universal Link callback route (fallback when app doesn't intercept) 44 // This route exists for iOS Universal Links and Android App Links. 45 // When properly configured, the mobile OS intercepts this URL and opens the app 46 // BEFORE the request reaches the server. If this handler is reached, it means 47 // Universal Links failed to intercept. 48 r.With(loginLimiter.Middleware).Get("/app/oauth/callback", handler.HandleMobileDeepLinkFallback) 49 50 // Session management - dedicated rate limits 51 r.With(logoutLimiter.Middleware).Post("/oauth/logout", handler.HandleLogout) 52 r.With(refreshLimiter.Middleware).Post("/oauth/refresh", handler.HandleRefresh) 53} 54 55// corsMiddleware creates a CORS middleware for OAuth callback with specific allowed origins 56func corsMiddleware(allowedOrigins []string) func(next http.Handler) http.Handler { 57 return cors.Handler(cors.Options{ 58 AllowedOrigins: allowedOrigins, // Only allow specific origins for OAuth callback 59 AllowedMethods: []string{"GET", "POST", "OPTIONS"}, 60 AllowedHeaders: []string{ 61 "Accept", 62 "Authorization", 63 "Content-Type", 64 "X-CSRF-Token", 65 }, 66 ExposedHeaders: []string{"Link"}, 67 AllowCredentials: true, 68 MaxAge: 300, // 5 minutes 69 }) 70}