Spaces:
Sleeping
Sleeping
| title: TaskFlow Backend | |
| emoji: π | |
| colorFrom: green | |
| colorTo: blue | |
| sdk: docker | |
| pinned: false | |
| short_description: TaskFlow A Full-Stack-Web-Application Hackathon 2 Phase 2 | |
| Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference | |
| ## Cross-site deployment notes π§ | |
| If your backend is hosted on a different domain (e.g., Hugging Face Spaces) than your frontend (e.g., Vercel), follow these steps to make cookie-based auth work: | |
| - Set `FRONTEND_URL` in your environment to your Vercel URL (e.g. `https://your-app.vercel.app`). | |
| - Ensure `JWT_COOKIE_SECURE=True` in production (browsers require `Secure` when `SameSite=None`). | |
| - Frontend fetch calls that rely on cookies must use `credentials: 'include'` (e.g. `fetch(url, { method, credentials: 'include' })`). | |
| - Backend CORS must have `allow_credentials=True` and the exact frontend origin (not `*`) in allowed origins. This project reads `FRONTEND_URL` for that purpose. | |
| ### Refresh token flow (implemented) | |
| - On login the backend now returns a **short-lived access token** (in the response) and sets a **HttpOnly refresh cookie** (`/api/auth` path). | |
| - To get a new access token, call `POST /api/auth/refresh` with `credentials: 'include'`. The server validates and rotates the refresh token and returns a new access token in the response body. | |
| - On logout the server revokes the refresh token and clears the refresh cookie. | |
| Client example (login + using refresh) β Vercel frontend: | |
| 1) Login (receives access token in response body and a HttpOnly refresh cookie): | |
| ```js | |
| const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/auth/login`, { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| credentials: 'include', | |
| body: JSON.stringify({ email, password }), | |
| }) | |
| const data = await res.json() | |
| const accessToken = data.access_token | |
| // Store accessToken in memory (React state) | |
| ``` | |
| 2) Use access token for protected calls (in memory, sent in Authorization header): | |
| ```js | |
| await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/tasks`, { | |
| headers: { 'Authorization': `Bearer ${accessToken}` } | |
| }) | |
| ``` | |
| 3) Obtain a fresh access token when it expires: | |
| ```js | |
| const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/auth/refresh`, { | |
| method: 'POST', | |
| credentials: 'include', // sends HttpOnly refresh cookie | |
| }) | |
| const data = await res.json() | |
| const accessToken = data.access_token | |
| ``` | |
| If cookies are still not sent/received, open DevTools network tab and inspect the `Set-Cookie` response header and browser cookie/journal to see why it was blocked (e.g., SameSite/Secure/Domain issues). | |
| Database migration note: | |
| - After pulling these changes, run Alembic migrations to create the `refreshtoken` table: | |
| ```bash | |
| alembic upgrade head | |
| ``` | |
| (If you deploy to Spaces, ensure your deployment runs the migration step or create the table manually.) |