Nik Afiq 8a549504a4 feat(auth): implement Firebase authentication and token verification
- Added FirebaseAuth struct and TokenVerifier interface for verifying Firebase ID tokens.
- Introduced FirebaseConfig struct in config to manage Firebase credentials and project ID.
- Implemented OAuth handler for Firebase ID token verification in HTTP handlers.
- Added middleware for authenticating requests using Firebase tokens.
- Updated router to conditionally apply authentication based on configuration.
- Created tests for the new authentication middleware.
- Added request and response types for Firebase OAuth handling.
- Included a sample JSON file for testing purposes.
2025-12-10 19:05:11 +09:00

76 lines
1.9 KiB
Go

package main
// @title Watch Party Backend API
// @version 1.0
// @description Backend API for watch-party app.
// @BasePath /
// @schemes http https
// @host localhost:8082
import (
"context"
"log"
"net/http"
"time"
_ "watch-party-backend/docs"
"watch-party-backend/internal/auth"
"watch-party-backend/internal/config"
"watch-party-backend/internal/db"
httpapi "watch-party-backend/internal/http"
"watch-party-backend/internal/repo"
"watch-party-backend/internal/service"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
"github.com/gin-gonic/gin"
)
func main() {
// 1) config
cfg := config.Load()
gin.SetMode(cfg.GinMode)
// 2) DB pool
ctx := context.Background()
pool, err := db.NewPool(ctx, cfg.DB.DSN(), cfg.DB.MaxConns)
if err != nil {
log.Fatalf("db connect failed: %v", err)
}
defer pool.Close()
// 3) wiring
episodeRepo := repo.NewEpisodeRepo(pool)
episodeSvc := service.NewEpisodeService(episodeRepo)
var verifier auth.TokenVerifier
if cfg.Auth.Enabled {
v, err := auth.NewFirebaseAuth(ctx, cfg.Firebase)
if err != nil {
log.Fatalf("firebase auth init failed: %v", err)
}
verifier = v
log.Printf("auth enabled (project: %s)", cfg.Firebase.ProjectID)
} else {
log.Printf("auth disabled (AUTH_ENABLED=false)")
}
router := httpapi.NewRouter(episodeSvc, verifier, cfg.Auth.Enabled)
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
// 4) HTTP server with timeouts
s := &http.Server{
Addr: cfg.Addr,
Handler: router,
ReadTimeout: 10 * time.Second,
ReadHeaderTimeout: 5 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 60 * time.Second,
}
log.Printf("listening on %s (dsn: %s)", cfg.Addr, config.RedactDSN(cfg.DB.DSN()))
if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("server error: %v", err)
}
}