changed the navbar to work.
All checks were successful
Build Frontend / Build Frontend (push) Successful in 35s
All checks were successful
Build Frontend / Build Frontend (push) Successful in 35s
This commit is contained in:
337
NAVBAR_LOGIN_FIX.md
Normal file
337
NAVBAR_LOGIN_FIX.md
Normal file
@@ -0,0 +1,337 @@
|
||||
# Navbar Login Fix - WebSocket Authentication State Update
|
||||
|
||||
## Problem Description
|
||||
|
||||
After successfully logging in via Steam, the WebSocket would connect and receive user data from the server, but the navbar would not update to show the logged-in state.
|
||||
|
||||
### Root Cause
|
||||
|
||||
The WebSocket `connected` message handler was receiving user data (steamId, username, userId) but was only logging it to the console. It was **not updating the auth store**, which the navbar component relies on to display authentication state.
|
||||
|
||||
**Console logs showed:**
|
||||
```
|
||||
🔵 AnnouncementBanner mounted - loading announcements...
|
||||
WebSocket connected
|
||||
WebSocket message received: { type: "connected", data: {...} }
|
||||
Server confirmed connection: { steamId: "...", username: "...", userId: "..." }
|
||||
```
|
||||
|
||||
But the navbar remained in logged-out state because `authStore.isAuthenticated` was still `false`.
|
||||
|
||||
---
|
||||
|
||||
## Solution
|
||||
|
||||
### Changes Made
|
||||
|
||||
#### 1. WebSocket Store (`frontend/src/stores/websocket.js`)
|
||||
- **Modified the `"connected"` message handler** to call `authStore.fetchUser()` when the WebSocket connection is confirmed
|
||||
- **Fixed duplicate `authStore` declarations** by declaring it once at the top of `handleMessage` function
|
||||
- **Added debug logging** to trace the authentication flow
|
||||
|
||||
**Before:**
|
||||
```javascript
|
||||
case "connected":
|
||||
console.log("Server confirmed connection:", payload);
|
||||
break;
|
||||
```
|
||||
|
||||
**After:**
|
||||
```javascript
|
||||
const handleMessage = (data) => {
|
||||
const { type, data: payload, timestamp } = data;
|
||||
const authStore = useAuthStore(); // Declared once at top
|
||||
|
||||
switch (type) {
|
||||
case "connected":
|
||||
console.log("🟢 WebSocket received 'connected' message:", payload);
|
||||
// Fetch updated user data from the auth endpoint
|
||||
console.log("🔵 Calling authStore.fetchUser() from WebSocket connected handler");
|
||||
authStore.fetchUser();
|
||||
break;
|
||||
|
||||
case "balance_update":
|
||||
// Now uses authStore declared at top
|
||||
if (payload?.balance !== undefined) {
|
||||
authStore.updateBalance(payload.balance);
|
||||
}
|
||||
break;
|
||||
// ... rest of cases
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
#### 2. Auth Store (`frontend/src/stores/auth.js`)
|
||||
- **Added debug logging** to trace authentication initialization and user fetch operations
|
||||
|
||||
**Added logs:**
|
||||
```javascript
|
||||
console.log("🔵 fetchUser called - fetching user from /api/auth/me");
|
||||
console.log("✅ fetchUser response:", response.data);
|
||||
console.log("✅ Setting user in auth store:", response.data.user);
|
||||
console.log("🔵 fetchUser complete - isAuthenticated:", isAuthenticated.value);
|
||||
console.log("🔵 Auth store initialize called - isInitialized:", isInitialized.value);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## How It Works Now
|
||||
|
||||
### Authentication Flow After Steam Login
|
||||
|
||||
1. **User clicks "Login to Steam"** button
|
||||
- Frontend redirects to: `${VITE_API_URL}/api/auth/steam`
|
||||
|
||||
2. **Steam OAuth flow completes**
|
||||
- Backend receives callback from Steam
|
||||
- Backend creates session and sets HTTP-only cookie
|
||||
- Backend redirects user back to frontend
|
||||
|
||||
3. **Frontend loads** (`App.vue` `onMounted`)
|
||||
- `authStore.initialize()` → calls `fetchUser()` → requests `/api/auth/me`
|
||||
- `wsStore.connect()` → establishes WebSocket connection
|
||||
|
||||
4. **WebSocket connects successfully**
|
||||
- Backend sends `{ type: "connected", data: { steamId, username, userId } }`
|
||||
|
||||
5. **WebSocket receives "connected" message** ✨ **NEW**
|
||||
- Handler calls `authStore.fetchUser()`
|
||||
- Fetches user data from `/api/auth/me` with credentials
|
||||
- Updates `authStore.user` and sets `isAuthenticated = true`
|
||||
|
||||
6. **Navbar reactively updates** 🎉
|
||||
- `authStore.isAuthenticated` changes from `false` → `true`
|
||||
- Vue's reactivity triggers navbar to show user menu, avatar, balance, etc.
|
||||
|
||||
---
|
||||
|
||||
## Deployment Instructions
|
||||
|
||||
### 1. Build the Frontend
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm run build
|
||||
```
|
||||
|
||||
**Expected output:**
|
||||
```
|
||||
✓ 1588 modules transformed.
|
||||
✓ built in 2.80s
|
||||
```
|
||||
|
||||
### 2. Deploy to Production
|
||||
|
||||
**Option A: Manual deployment on server**
|
||||
```bash
|
||||
# SSH into your server
|
||||
ssh user@your-server
|
||||
|
||||
# Navigate to project
|
||||
cd /path/to/TurboTrades/frontend
|
||||
|
||||
# Pull latest changes
|
||||
git pull origin main
|
||||
|
||||
# Build
|
||||
npm install # if dependencies changed
|
||||
npm run build
|
||||
|
||||
# Copy to web root
|
||||
sudo cp -r dist/* /var/www/html/turbotrades/
|
||||
```
|
||||
|
||||
**Option B: CI/CD Pipeline**
|
||||
```bash
|
||||
# Commit and push changes
|
||||
git add frontend/src/stores/websocket.js frontend/src/stores/auth.js
|
||||
git commit -m "Fix navbar not updating after Steam login - WebSocket auth state sync"
|
||||
git push origin main
|
||||
|
||||
# Your CI/CD pipeline will automatically:
|
||||
# 1. Pull changes
|
||||
# 2. Build frontend
|
||||
# 3. Deploy to production
|
||||
```
|
||||
|
||||
### 3. Clear Browser Cache
|
||||
|
||||
After deployment, users need to hard-refresh to get the new JavaScript bundle:
|
||||
|
||||
- **Windows/Linux:** `Ctrl + Shift + R` or `Ctrl + F5`
|
||||
- **Mac:** `Cmd + Shift + R`
|
||||
- **Or use Incognito/Private mode** for testing
|
||||
|
||||
---
|
||||
|
||||
## Testing the Fix
|
||||
|
||||
### 1. Open Browser Console
|
||||
|
||||
Press `F12` to open DevTools and go to Console tab.
|
||||
|
||||
### 2. Clear Cookies and Storage
|
||||
|
||||
In DevTools:
|
||||
- Go to **Application** tab
|
||||
- Click **Clear storage** → **Clear site data**
|
||||
|
||||
### 3. Attempt Login
|
||||
|
||||
Click "Login to Steam" button and complete authentication.
|
||||
|
||||
### 4. Watch Console Logs
|
||||
|
||||
You should see this sequence:
|
||||
|
||||
```
|
||||
🔵 Auth store initialize called - isInitialized: false
|
||||
🔵 fetchUser called - fetching user from /api/auth/me
|
||||
✅ fetchUser response: { success: true, user: {...} }
|
||||
✅ Setting user in auth store: { steamId: "...", username: "...", ... }
|
||||
🔵 fetchUser complete - isAuthenticated: true
|
||||
|
||||
Connecting to WebSocket: wss://api.turbotrades.dev/ws
|
||||
WebSocket connected
|
||||
🟢 WebSocket received 'connected' message: { steamId: "...", username: "...", userId: "..." }
|
||||
🔵 Calling authStore.fetchUser() from WebSocket connected handler
|
||||
🔵 fetchUser called - fetching user from /api/auth/me
|
||||
✅ fetchUser response: { success: true, user: {...} }
|
||||
✅ Setting user in auth store: { steamId: "...", username: "...", ... }
|
||||
🔵 fetchUser complete - isAuthenticated: true
|
||||
```
|
||||
|
||||
### 5. Verify Navbar Updates
|
||||
|
||||
The navbar should now show:
|
||||
- ✅ Your Steam avatar
|
||||
- ✅ Your username
|
||||
- ✅ Your balance with deposit button
|
||||
- ✅ User dropdown menu with Profile, Inventory, etc.
|
||||
|
||||
---
|
||||
|
||||
## Rollback Plan
|
||||
|
||||
If issues occur after deployment:
|
||||
|
||||
### Quick Rollback
|
||||
```bash
|
||||
# Revert the commits
|
||||
git revert HEAD~2..HEAD
|
||||
|
||||
# Rebuild and redeploy
|
||||
cd frontend
|
||||
npm run build
|
||||
sudo cp -r dist/* /var/www/html/turbotrades/
|
||||
```
|
||||
|
||||
### Remove Debug Logs (Production Cleanup)
|
||||
|
||||
Once confirmed working, you may want to remove the verbose debug logs:
|
||||
|
||||
**In `frontend/src/stores/auth.js`** - remove all `console.log` statements added
|
||||
|
||||
**In `frontend/src/stores/websocket.js`** - remove or reduce debug logs:
|
||||
```javascript
|
||||
case "connected":
|
||||
// Keep minimal logging
|
||||
console.log("WebSocket connected");
|
||||
authStore.fetchUser();
|
||||
break;
|
||||
```
|
||||
|
||||
Then rebuild and redeploy.
|
||||
|
||||
---
|
||||
|
||||
## Additional Notes
|
||||
|
||||
### Why Two `fetchUser()` Calls?
|
||||
|
||||
You might notice `fetchUser()` is called twice:
|
||||
|
||||
1. **On App Mount** (`App.vue` → `authStore.initialize()`)
|
||||
- Handles the case where user already has a valid session
|
||||
- Runs immediately when page loads
|
||||
|
||||
2. **On WebSocket Connected** (new addition)
|
||||
- Handles the case where user just logged in via Steam
|
||||
- Ensures auth state is fresh after Steam OAuth redirect
|
||||
- Provides a fallback if the initial fetch happened before the session cookie was set
|
||||
|
||||
This redundancy is intentional and ensures authentication works reliably in all scenarios.
|
||||
|
||||
### Session Persistence
|
||||
|
||||
The authentication uses HTTP-only cookies set by the backend. These persist across:
|
||||
- Page refreshes
|
||||
- Browser restarts (unless expired)
|
||||
- Tab closures
|
||||
|
||||
The WebSocket connection authenticates using the same session cookie.
|
||||
|
||||
---
|
||||
|
||||
## Related Files
|
||||
|
||||
- `frontend/src/stores/websocket.js` - WebSocket message handling
|
||||
- `frontend/src/stores/auth.js` - Authentication state management
|
||||
- `frontend/src/components/NavBar.vue` - Navbar component (reactive to auth state)
|
||||
- `frontend/src/App.vue` - App initialization flow
|
||||
- `backend/routes/auth.js` - Steam OAuth and session management
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Navbar Still Not Updating
|
||||
|
||||
1. **Clear browser cache completely** (not just refresh)
|
||||
2. **Check browser console for errors**
|
||||
3. **Verify `/api/auth/me` returns user data:**
|
||||
```bash
|
||||
curl -s https://api.turbotrades.dev/api/auth/me -b cookies.txt | jq
|
||||
```
|
||||
4. **Check WebSocket connection:**
|
||||
- Look for "WebSocket connected" in console
|
||||
- Verify no CORS errors
|
||||
|
||||
### "fetchUser called" But No Response
|
||||
|
||||
- **Backend issue:** Check PM2 logs
|
||||
```bash
|
||||
pm2 logs turbotrades-backend --lines 50
|
||||
```
|
||||
- **CORS issue:** Check for CORS errors in browser console
|
||||
- **Session cookie not set:** Check backend logs for Steam OAuth errors
|
||||
|
||||
### WebSocket Doesn't Receive "connected" Message
|
||||
|
||||
- **Backend WebSocket handler issue:** Check `backend/services/websocket.js`
|
||||
- **Nginx not proxying WS correctly:** Verify Nginx config has:
|
||||
```nginx
|
||||
location /ws {
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_pass http://127.0.0.1:3000/ws;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
✅ User can click "Login to Steam" and complete OAuth flow
|
||||
✅ Upon redirect back to site, navbar shows logged-in state
|
||||
✅ User's avatar, username, and balance are displayed
|
||||
✅ WebSocket connects and shows user data in console
|
||||
✅ User can access protected routes (Inventory, Profile, etc.)
|
||||
✅ No console errors related to authentication or WebSocket
|
||||
|
||||
---
|
||||
|
||||
**Status:** Ready for deployment
|
||||
**Last Updated:** 2025-01-10
|
||||
**Build Tested:** ✅ Success
|
||||
**Files Modified:** 2 (websocket.js, auth.js)
|
||||
Reference in New Issue
Block a user