Skip to content

Commit 63927ed

Browse files
rainerstudiosclaude
andcommitted
Remove Passport.js and migrate to Better Auth
Major changes: - Removed Passport.js authentication library - Created dual authentication middleware (lib/dual-auth.js) - Updated Steam API key to 863053349689FA6DE8D1B9D5792A62AF - Created Better Auth setup documentation - Migrated database schema for Better Auth compatibility - Updated Steam inventory endpoints to use dualAuth middleware - Removed passport and express-session from package.json Backend now supports: - Better Auth JWT tokens from Next.js frontend - Shared PostgreSQL database between frontend and backend - Simplified authentication without cross-domain cookie issues 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 672199f commit 63927ed

9 files changed

Lines changed: 779 additions & 35 deletions

File tree

.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Steam Authentication Configuration
2-
STEAM_API_KEY=65223E8BE47C4CDFFE454434252C8012
2+
STEAM_API_KEY=863053349689FA6DE8D1B9D5792A62AF
33
STEAM_RETURN_URL=https://api.xgamingserver.com/auth/steam/return
44
FRONTEND_URL=https://cs2floatchecker.com
55

BETTER_AUTH_SETUP.md

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
# Better Auth Setup Guide
2+
3+
## ✅ Database is Ready!
4+
5+
Your PostgreSQL database has been configured to work with Better Auth. Both your Express backend and Next.js frontend will share the same database.
6+
7+
---
8+
9+
## 📊 Database Connection Details
10+
11+
**Add this to your Next.js `.env` file on Vercel:**
12+
13+
```bash
14+
# PostgreSQL Connection (for Better Auth)
15+
DATABASE_URL="postgresql://cs2user:cs2pass123@178.156.147.69:5432/cs2floatapi"
16+
17+
# Better Auth Secret (must match backend)
18+
BETTER_AUTH_SECRET="cs2float-secret-key-change-in-production"
19+
BETTER_AUTH_URL="https://cs2floatchecker.com"
20+
21+
# Steam API Key
22+
STEAM_API_KEY="863053349689FA6DE8D1B9D5792A62AF"
23+
```
24+
25+
---
26+
27+
## 📦 Install Dependencies in Your Next.js App
28+
29+
```bash
30+
npm install better-auth
31+
npm install @better-auth/steam # Custom Steam plugin
32+
npm install postgres # PostgreSQL adapter
33+
```
34+
35+
---
36+
37+
## 🔧 Better Auth Configuration
38+
39+
Create `lib/auth.ts` in your Next.js app:
40+
41+
```typescript
42+
import { betterAuth } from "better-auth";
43+
import { steamAuth } from "@better-auth/steam"; // From the gist
44+
import { Pool } from "pg";
45+
46+
// PostgreSQL connection
47+
const pool = new Pool({
48+
connectionString: process.env.DATABASE_URL,
49+
});
50+
51+
export const auth = betterAuth({
52+
database: {
53+
provider: "postgres",
54+
pool,
55+
},
56+
57+
secret: process.env.BETTER_AUTH_SECRET!,
58+
baseURL: process.env.BETTER_AUTH_URL!,
59+
60+
// Use the Steam plugin
61+
plugins: [
62+
steamAuth({
63+
apiKey: process.env.STEAM_API_KEY!,
64+
// Steam will redirect back to your Next.js app
65+
callbackURL: `${process.env.BETTER_AUTH_URL}/api/auth/callback/steam`,
66+
}),
67+
],
68+
69+
session: {
70+
expiresIn: 60 * 60 * 24 * 7, // 7 days
71+
updateAge: 60 * 60 * 24, // Update every day
72+
},
73+
});
74+
```
75+
76+
---
77+
78+
## 🎯 Create API Routes in Next.js
79+
80+
### 1. Auth API Route: `app/api/auth/[...all]/route.ts`
81+
82+
```typescript
83+
import { auth } from "@/lib/auth";
84+
import { toNextJsHandler } from "better-auth/next-js";
85+
86+
export const { GET, POST } = toNextJsHandler(auth);
87+
```
88+
89+
### 2. Steam Login Button
90+
91+
```typescript
92+
'use client';
93+
94+
import { signIn } from "better-auth/client";
95+
96+
export function SteamLoginButton() {
97+
const handleLogin = async () => {
98+
await signIn.social({
99+
provider: "steam",
100+
callbackURL: "/dashboard", // Where to go after login
101+
});
102+
};
103+
104+
return (
105+
<button onClick={handleLogin}>
106+
Sign in with Steam
107+
</button>
108+
);
109+
}
110+
```
111+
112+
### 3. Use Auth in Components
113+
114+
```typescript
115+
'use client';
116+
117+
import { useSession } from "better-auth/react";
118+
119+
export function UserProfile() {
120+
const { data: session, isPending } = useSession();
121+
122+
if (isPending) return <div>Loading...</div>;
123+
if (!session) return <div>Not logged in</div>;
124+
125+
return (
126+
<div>
127+
<img src={session.user.image} alt="Avatar" />
128+
<p>Welcome, {session.user.name}</p>
129+
<p>Steam ID: {session.user.steam_id}</p>
130+
</div>
131+
);
132+
}
133+
```
134+
135+
### 4. Make API Calls with Auth
136+
137+
```typescript
138+
import { auth } from "@/lib/auth";
139+
140+
// Get session on server
141+
const session = await auth.api.getSession({
142+
headers: request.headers,
143+
});
144+
145+
// Call your Express backend with Steam ID
146+
const response = await fetch(
147+
`https://api.cs2floatchecker.com/api/portfolio/${session.user.steam_id}`,
148+
{
149+
headers: {
150+
'Authorization': `Bearer ${session.session.token}`,
151+
},
152+
}
153+
);
154+
```
155+
156+
---
157+
158+
## 🔄 Database Schema
159+
160+
Better Auth will use these tables (already created):
161+
162+
- **users** - Stores user profiles (Steam data)
163+
- **sessions** - Active user sessions
164+
- **accounts** - OAuth provider accounts (Steam)
165+
- **verification_tokens** - For email verification (not used for Steam)
166+
167+
---
168+
169+
## 🎯 How It Works
170+
171+
```
172+
1. User clicks "Login with Steam" on cs2floatchecker.com
173+
174+
2. Better Auth redirects to Steam OpenID
175+
176+
3. Steam authenticates user
177+
178+
4. Steam redirects back to: cs2floatchecker.com/api/auth/callback/steam
179+
180+
5. Better Auth:
181+
- Creates/updates user in PostgreSQL
182+
- Creates session in PostgreSQL
183+
- Sets secure cookie (same domain!)
184+
185+
6. User redirected to dashboard
186+
187+
7. Frontend reads session from cookie
188+
189+
8. Frontend calls Express API with session token
190+
```
191+
192+
---
193+
194+
## ✅ Benefits
195+
196+
-**Same domain cookies** - No cross-domain issues!
197+
-**Shared database** - Both apps see same users
198+
-**Simple auth** - Better Auth handles everything
199+
-**Type-safe** - Full TypeScript support
200+
-**Persistent sessions** - Stays logged in across navigation
201+
202+
---
203+
204+
## 🔧 Express Backend Changes
205+
206+
The Express backend will:
207+
- Remove Passport.js (no longer needed)
208+
- Accept Better Auth session tokens
209+
- Verify tokens and extract Steam ID
210+
- Continue serving portfolio data
211+
212+
(I'll update the backend after you confirm frontend is ready)
213+
214+
---
215+
216+
## 📝 Next Steps
217+
218+
1. **Add DATABASE_URL to Vercel** environment variables
219+
2. **Install Better Auth** in your Next.js app
220+
3. **Copy the code above** into your Next.js app
221+
4. **Deploy to Vercel**
222+
5. **Test login** at cs2floatchecker.com
223+
224+
Let me know when you're ready and I'll update the Express backend!

index.js

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -78,31 +78,16 @@ app.use(function (error, req, res, next) {
7878
// =====================================================================
7979
// STEAM AUTHENTICATION SETUP
8080
// =====================================================================
81-
const session = require('express-session');
82-
const passport = require('passport');
83-
const steamAuth = require('./lib/steam-auth');
84-
const steamInventory = require('./lib/steam-inventory');
85-
86-
// Session middleware
87-
app.use(session({
88-
secret: process.env.SESSION_SECRET || 'cs2float-session-secret-change-in-production',
89-
resave: false,
90-
saveUninitialized: false,
91-
cookie: {
92-
maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
93-
secure: process.env.NODE_ENV === 'production',
94-
httpOnly: true,
95-
sameSite: 'lax'
96-
}
97-
}));
81+
// REMOVED: Passport.js authentication - migrating to Better Auth
82+
// const session = require('express-session');
83+
// const passport = require('passport');
84+
// const steamAuth = require('./lib/steam-auth');
9885

99-
// Initialize Passport
100-
app.use(passport.initialize());
101-
app.use(passport.session());
86+
// Use dual authentication middleware (supports Better Auth tokens)
87+
const { dualAuth, optionalAuth } = require('./lib/dual-auth');
88+
const steamInventory = require('./lib/steam-inventory');
10289

103-
// Configure Steam authentication
104-
steamAuth.configureSteamAuth(postgres);
105-
winston.info('Steam authentication configured');
90+
winston.info('Better Auth token verification configured');
10691

10792

10893

@@ -4033,15 +4018,16 @@ function calculateTradeRisk(history) {
40334018
// =====================================================================
40344019
// STEAM AUTHENTICATION ROUTES
40354020
// =====================================================================
4036-
steamAuth.setupAuthRoutes(app, postgres);
4037-
winston.info('Steam authentication routes loaded');
4021+
// REMOVED: Old Passport.js Steam auth routes
4022+
// steamAuth.setupAuthRoutes(app, postgres);
4023+
winston.info('Using Better Auth for authentication (configured in Next.js frontend)');
40384024

40394025
// =====================================================================
40404026
// STEAM INVENTORY ENDPOINTS
40414027
// =====================================================================
40424028

40434029
// Get user's CS2 inventory
4044-
app.get('/api/steam/inventory/:steamId', steamAuth.requireAuth, async (req, res) => {
4030+
app.get('/api/steam/inventory/:steamId', dualAuth, async (req, res) => {
40454031
try {
40464032
const { steamId } = req.params;
40474033

@@ -4067,7 +4053,7 @@ app.get('/api/steam/inventory/:steamId', steamAuth.requireAuth, async (req, res)
40674053
});
40684054

40694055
// Get inventory value estimate
4070-
app.get('/api/steam/inventory/:steamId/value', steamAuth.requireAuth, async (req, res) => {
4056+
app.get('/api/steam/inventory/:steamId/value', dualAuth, async (req, res) => {
40714057
try {
40724058
const { steamId } = req.params;
40734059

@@ -4093,7 +4079,7 @@ app.get('/api/steam/inventory/:steamId/value', steamAuth.requireAuth, async (req
40934079
});
40944080

40954081
// Sync inventory to portfolio
4096-
app.post('/api/steam/inventory/sync', steamAuth.requireAuth, async (req, res) => {
4082+
app.post('/api/steam/inventory/sync', dualAuth, async (req, res) => {
40974083
try {
40984084
const steamId = req.user.steam_id;
40994085
const { selected_items = [] } = req.body;

lib/better-auth-verify.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/**
2+
* Better Auth Token Verification
3+
* Verifies JWT tokens generated by Better Auth in the frontend
4+
*/
5+
6+
const jwt = require('jsonwebtoken');
7+
8+
// This should match your Better Auth JWT secret in frontend
9+
const JWT_SECRET = process.env.BETTER_AUTH_SECRET || process.env.JWT_SECRET || 'cs2float-secret-key-change-in-production';
10+
11+
/**
12+
* Middleware to verify Better Auth JWT tokens
13+
*/
14+
function verifyBetterAuthToken(req, res, next) {
15+
// Check for token in multiple places
16+
const token = req.headers.authorization?.replace('Bearer ', '') ||
17+
req.headers['x-auth-token'] ||
18+
req.query.token ||
19+
req.cookies?.token; // Better Auth typically uses 'token' cookie name
20+
21+
if (!token) {
22+
return res.status(401).json({
23+
success: false,
24+
error: 'Authentication required',
25+
message: 'No authentication token provided'
26+
});
27+
}
28+
29+
try {
30+
// Verify the JWT token
31+
const decoded = jwt.verify(token, JWT_SECRET);
32+
33+
// Add user info to request
34+
req.user = {
35+
steam_id: decoded.steam_id || decoded.steamId || decoded.id,
36+
username: decoded.username || decoded.name,
37+
avatar: decoded.avatar,
38+
...decoded
39+
};
40+
41+
next();
42+
} catch (error) {
43+
console.error('Token verification failed:', error.message);
44+
return res.status(401).json({
45+
success: false,
46+
error: 'Invalid token',
47+
message: 'Authentication token is invalid or expired'
48+
});
49+
}
50+
}
51+
52+
/**
53+
* Optional middleware - doesn't fail if no token
54+
*/
55+
function optionalAuth(req, res, next) {
56+
const token = req.headers.authorization?.replace('Bearer ', '') ||
57+
req.headers['x-auth-token'] ||
58+
req.query.token ||
59+
req.cookies?.token;
60+
61+
if (token) {
62+
try {
63+
const decoded = jwt.verify(token, JWT_SECRET);
64+
req.user = {
65+
steam_id: decoded.steam_id || decoded.steamId || decoded.id,
66+
username: decoded.username || decoded.name,
67+
avatar: decoded.avatar,
68+
...decoded
69+
};
70+
} catch (error) {
71+
// Token invalid, but continue anyway
72+
req.user = null;
73+
}
74+
}
75+
76+
next();
77+
}
78+
79+
module.exports = {
80+
verifyBetterAuthToken,
81+
optionalAuth,
82+
JWT_SECRET
83+
};

0 commit comments

Comments
 (0)