A community based topic aggregation platform built on atproto
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
42 // This route is used for iOS Universal Links and Android App Links
43 // Path must match the path in .well-known/apple-app-site-association
44 // Uses the same handler as web callback - the system routes it to the mobile app
45 r.With(loginLimiter.Middleware).Get("/app/oauth/callback", handler.HandleCallback)
46
47 // Session management - dedicated rate limits
48 r.With(logoutLimiter.Middleware).Post("/oauth/logout", handler.HandleLogout)
49 r.With(refreshLimiter.Middleware).Post("/oauth/refresh", handler.HandleRefresh)
50}
51
52// corsMiddleware creates a CORS middleware for OAuth callback with specific allowed origins
53func corsMiddleware(allowedOrigins []string) func(next http.Handler) http.Handler {
54 return cors.Handler(cors.Options{
55 AllowedOrigins: allowedOrigins, // Only allow specific origins for OAuth callback
56 AllowedMethods: []string{"GET", "POST", "OPTIONS"},
57 AllowedHeaders: []string{
58 "Accept",
59 "Authorization",
60 "Content-Type",
61 "X-CSRF-Token",
62 },
63 ExposedHeaders: []string{"Link"},
64 AllowCredentials: true,
65 MaxAge: 300, // 5 minutes
66 })
67}