strat-gameplay-webapp/frontend-sba
Cal Corum e90a907e9e CLAUDE: Implement server-side OAuth flow with HttpOnly cookies
Fixes iPad Safari authentication issue where async JavaScript is blocked
on OAuth callback pages after cross-origin redirects (Cloudflare + Safari ITP).

**Problem**: iPad Safari blocks all async operations (Promises, setTimeout,
onMounted) on the OAuth callback page, preventing frontend token exchange.

**Solution**: Move entire OAuth flow to backend with HttpOnly cookies,
eliminating JavaScript dependency on callback page.

## Backend Changes (7 files)

### New Files
- app/services/oauth_state.py - Redis-based OAuth state management
  * CSRF protection with one-time use tokens (10min TTL)
  * Replaces frontend sessionStorage state validation

- app/utils/cookies.py - HttpOnly cookie utilities
  * Access token: 1 hour, Path=/api
  * Refresh token: 7 days, Path=/api/auth
  * Security: HttpOnly, Secure (prod), SameSite=Lax

### Modified Files
- app/api/routes/auth.py
  * NEW: GET /discord/login - Initiate OAuth with state creation
  * NEW: GET /discord/callback/server - Server-side callback handler
  * NEW: POST /logout - Clear auth cookies
  * UPDATED: GET /me - Cookie + header support (backwards compatible)
  * UPDATED: POST /refresh - Cookie + body support (backwards compatible)
  * FIXED: exchange_code_for_token() accepts redirect_uri parameter

- app/config.py
  * Added discord_server_redirect_uri config
  * Added frontend_url config for post-auth redirects

- app/websocket/handlers.py
  * Updated connect handler to parse cookies from environ
  * Falls back to auth object for backwards compatibility

- .env.example
  * Added DISCORD_SERVER_REDIRECT_URI example
  * Added FRONTEND_URL example

## Frontend Changes (10 files)

### Core Auth Changes
- store/auth.ts - Complete rewrite for cookie-based auth
  * Removed: token, refreshToken, tokenExpiresAt state (HttpOnly)
  * Added: checkAuth() - calls /api/auth/me with credentials
  * Updated: loginWithDiscord() - redirects to backend endpoint
  * Updated: logout() - calls backend logout endpoint
  * All $fetch calls use credentials: 'include'

- pages/auth/callback.vue - Simplified to error handler
  * No JavaScript token exchange needed
  * Displays errors from query params
  * Verifies auth with checkAuth() on success

- plugins/auth.client.ts
  * Changed from localStorage init to checkAuth() call
  * Async plugin to ensure auth state before navigation

- middleware/auth.ts - Simplified
  * Removed token validity checks (HttpOnly cookies)
  * Simple isAuthenticated check

### Cleanup Changes
- composables/useWebSocket.ts
  * Added withCredentials: true
  * Removed auth object with token
  * Updated canConnect to use isAuthenticated only

- layouts/default.vue, layouts/game.vue, pages/index.vue, pages/games/[id].vue
  * Removed initializeAuth() calls (handled by plugin)

## Documentation
- OAUTH_IPAD_ISSUE.md - Problem analysis and investigation notes
- OAUTH_SERVER_SIDE_IMPLEMENTATION.md - Complete implementation guide
  * Security improvements summary
  * Discord Developer Portal setup instructions
  * Testing checklist
  * OAuth flow diagram

## Security Improvements
- Tokens stored in HttpOnly cookies (XSS-safe)
- OAuth state in Redis with one-time use (CSRF-safe)
- Follows OAuth 2.0 Security Best Current Practice
- Backwards compatible with Authorization header auth

## Testing
-  Backend OAuth endpoints functional
-  Token exchange with correct redirect_uri
-  Cookie-based auth working
-  WebSocket connection with cookies
-  Desktop browser flow verified
-  iPad Safari testing pending Discord redirect URI config

## Next Steps
1. Add Discord redirect URI in Developer Portal:
   https://gameplay-demo.manticorum.com/api/auth/discord/callback/server
2. Test complete flow on iPad Safari
3. Verify WebSocket auto-reconnection with cookies

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 22:16:30 -06:00
..
.claude CLAUDE: Phases 3.5, F1-F5 Complete - Statistics & Frontend Components 2025-11-14 09:52:30 -06:00
app CLAUDE: Complete Phase 1 - Frontend Infrastructure Setup 2025-10-22 00:24:00 -05:00
assets/css CLAUDE: Complete Phase 1 - Frontend Infrastructure Setup 2025-10-22 00:24:00 -05:00
components test: Skip unstable test suites 2025-11-22 20:18:33 -06:00
composables CLAUDE: Implement server-side OAuth flow with HttpOnly cookies 2025-11-26 22:16:30 -06:00
constants CLAUDE: Standardize decision phase naming and fix frontend type mismatches 2025-11-21 15:40:52 -06:00
coverage test: Skip unstable test suites 2025-11-22 20:18:33 -06:00
layouts CLAUDE: Implement server-side OAuth flow with HttpOnly cookies 2025-11-26 22:16:30 -06:00
middleware CLAUDE: Implement server-side OAuth flow with HttpOnly cookies 2025-11-26 22:16:30 -06:00
pages CLAUDE: Implement server-side OAuth flow with HttpOnly cookies 2025-11-26 22:16:30 -06:00
plugins CLAUDE: Implement server-side OAuth flow with HttpOnly cookies 2025-11-26 22:16:30 -06:00
public CLAUDE: Complete Phase 1 - Frontend Infrastructure Setup 2025-10-22 00:24:00 -05:00
store CLAUDE: Implement server-side OAuth flow with HttpOnly cookies 2025-11-26 22:16:30 -06:00
tests test: Skip unstable test suites 2025-11-22 20:18:33 -06:00
types CLAUDE: Standardize decision phase naming and fix frontend type mismatches 2025-11-21 15:40:52 -06:00
.dockerignore CLAUDE: Initial project setup - documentation and infrastructure 2025-10-21 16:21:13 -05:00
.gitignore CLAUDE: Complete Phase 1 - Frontend Infrastructure Setup 2025-10-22 00:24:00 -05:00
app.vue CLAUDE: Phase F1 Complete - SBa Frontend Foundation with Nuxt 4 Fixes 2025-11-10 15:42:29 -06:00
bun.lock CLAUDE: Implement game creation and lineup submission workflow 2025-11-20 23:57:03 -06:00
CLAUDE.md CLAUDE: Standardize decision phase naming and fix frontend type mismatches 2025-11-21 15:40:52 -06:00
Dockerfile CLAUDE: Initial project setup - documentation and infrastructure 2025-10-21 16:21:13 -05:00
eslint.config.mjs test: Skip unstable test suites 2025-11-22 20:18:33 -06:00
nuxt.config.ts test: Skip unstable test suites 2025-11-22 20:18:33 -06:00
package-lock.json test: Skip unstable test suites 2025-11-22 20:18:33 -06:00
package.json test: Skip unstable test suites 2025-11-22 20:18:33 -06:00
README.md CLAUDE: Complete Phase 1 - Frontend Infrastructure Setup 2025-10-22 00:24:00 -05:00
tailwind.config.js CLAUDE: Phases 3.5, F1-F5 Complete - Statistics & Frontend Components 2025-11-14 09:52:30 -06:00
TEST_STATUS.md Create TEST_STATUS.md 2025-11-23 01:27:16 -06:00
tsconfig.json CLAUDE: Complete Phase 1 - Frontend Infrastructure Setup 2025-10-22 00:24:00 -05:00
vitest.config.ts test: Skip unstable test suites 2025-11-22 20:18:33 -06:00

Nuxt Minimal Starter

Look at the Nuxt documentation to learn more.

Setup

Make sure to install dependencies:

# npm
npm install

# pnpm
pnpm install

# yarn
yarn install

# bun
bun install

Development Server

Start the development server on http://localhost:3000:

# npm
npm run dev

# pnpm
pnpm dev

# yarn
yarn dev

# bun
bun run dev

Production

Build the application for production:

# npm
npm run build

# pnpm
pnpm build

# yarn
yarn build

# bun
bun run build

Locally preview production build:

# npm
npm run preview

# pnpm
pnpm preview

# yarn
yarn preview

# bun
bun run preview

Check out the deployment documentation for more information.