// Command google-auth-proxy is a small Google OAuth SSO service designed to // sit behind nginx's auth_request module. The dokku google-auth plugin runs // one instance of it per host and points every protected app's nginx config // at it. package main import ( "context" "errors" "flag" "log" "net/http" "os" "os/signal" "strings" "syscall" "time" "dokku-google-auth/internal/authproxy" ) func main() { healthcheck := flag.Bool("healthcheck", false, "probe the locally running server and exit 0 if healthy") flag.Parse() if *healthcheck { os.Exit(runHealthcheck()) } cfg, err := authproxy.ConfigFromEnv() if err != nil { log.Fatalf("configuration error: %v", err) } server, err := authproxy.New(cfg) if err != nil { log.Fatalf("startup error: %v", err) } httpServer := &http.Server{ Addr: cfg.ListenAddr, Handler: server.Routes(), ReadHeaderTimeout: 10 * time.Second, } shutdown := make(chan os.Signal, 1) signal.Notify(shutdown, syscall.SIGINT, syscall.SIGTERM) go func() { <-shutdown ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() _ = httpServer.Shutdown(ctx) }() log.Printf("google-auth-proxy listening on %s (auth host: %s)", cfg.ListenAddr, cfg.AuthHost) if err := httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { log.Fatalf("server error: %v", err) } } func runHealthcheck() int { addr := os.Getenv("GOOGLE_AUTH_LISTEN") if addr == "" { addr = ":2999" } if strings.HasPrefix(addr, ":") { addr = "127.0.0.1" + addr } client := &http.Client{Timeout: 5 * time.Second} resp, err := client.Get("http://" + addr + "/_google-auth/healthz") if err != nil { return 1 } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return 1 } return 0 }