Merge pull request 'dev' (#95) from dev into master
All checks were successful
Deploy application with Docker / build_and_deploy (push) Successful in 53s

Reviewed-on: #95
This commit is contained in:
Hayden Hargreaves 2026-03-12 20:18:06 -07:00
commit 787fff6bb0
3 changed files with 39 additions and 6 deletions

View File

@ -4,7 +4,6 @@ import (
"fmt"
"net/http"
"net/url"
"time"
"github.com/gin-gonic/gin"
)
@ -32,12 +31,13 @@ func (s *Server) GoogleCallbackHandlerV2(ctx *gin.Context) {
domain := s.deps.EnvironmentConfig.FrontendDomain
if jwt, err := s.deps.AuthService.GoogleAuthSuccess(state, code); err != nil {
url := fmt.Sprintf("%s/v2/web/login?error=%s", domain, url.QueryEscape(err.Error()))
ctx.Redirect(http.StatusSeeOther, url)
redirectUrl := fmt.Sprintf("%s/v2/web/login?error=%s", domain, url.QueryEscape(err.Error()))
ctx.Redirect(http.StatusSeeOther, redirectUrl)
} else {
url := fmt.Sprintf("%s/v2/web/home", domain)
s.SetCookie(ctx, "jwt_token", jwt, time.Hour*24*7)
ctx.Redirect(http.StatusSeeOther, url)
// Pass JWT via query param - frontend will set the cookie
// This bypasses cross-origin cookie issues with Cloudflare/proxies
redirectUrl := fmt.Sprintf("%s/v2/web/auth/callback?token=%s", domain, url.QueryEscape(jwt))
ctx.Redirect(http.StatusSeeOther, redirectUrl)
}
}

View File

@ -13,6 +13,7 @@ import { use, type ReactNode } from 'react';
import { AuthContext } from './context/AuthContext';
import RecipePage from './pages/Recipe';
import SearchPage from './pages/Search';
import AuthCallback from './pages/AuthCallback';
function ProtectedRoute({ children }: { children: ReactNode }) {
const { isLoggedIn } = use(AuthContext)
@ -37,6 +38,9 @@ function App() {
{/* Login page does not inherit WebLayout */}
<Route path="/v2/web/login" element={<LoginPage />} />
{/* Auth callback - handles token from OAuth redirect */}
<Route path="/v2/web/auth/callback" element={<AuthCallback />} />
<Route path="/v2/web" element={<WebLayout />}>
<Route index element={<Navigate to={ROUTE_CONSTANTS.Home} replace />} />
<Route path="home" element={<Home />} />

View File

@ -0,0 +1,29 @@
import { useEffect } from "react";
import { useSearchParams, useNavigate } from "react-router-dom";
import { useCookies } from "react-cookie";
export default function AuthCallback() {
const [searchParams] = useSearchParams();
const navigate = useNavigate();
const [, setCookie] = useCookies(["jwt_token"]);
useEffect(() => {
const token = searchParams.get("token");
if (token) {
// Set cookie with 7 day expiration, accessible across all subdomains
setCookie("jwt_token", token, {
path: "/",
maxAge: 60 * 60 * 24 * 7, // 7 days in seconds
secure: true,
sameSite: "lax",
});
void navigate("/v2/web/home", { replace: true });
} else {
// No token provided, redirect to login
void navigate("/v2/web/login", { replace: true });
}
}, [searchParams, setCookie, navigate]);
return null;
}