🗑️ Remove outdated documentation files and consolidate content into a single README for improved organization and maintainability
This commit is contained in:
355
docs/projects/Pokedex.Online/api-reference/oauth-setup.md
Normal file
355
docs/projects/Pokedex.Online/api-reference/oauth-setup.md
Normal file
@@ -0,0 +1,355 @@
|
||||
# Challonge OAuth Setup Guide
|
||||
|
||||
Complete guide to implementing OAuth authentication for Challonge API v2.1 APPLICATION scope.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Development Setup (5 minutes)
|
||||
|
||||
1. **Register OAuth Application**
|
||||
- Visit https://connect.challonge.com
|
||||
- Create new application
|
||||
- Set redirect URI: `http://localhost:5173/oauth/callback`
|
||||
- Note your Client ID and Client Secret
|
||||
|
||||
2. **Configure Environment**
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Edit `.env`:
|
||||
```bash
|
||||
# Frontend (Vite variables)
|
||||
VITE_CHALLONGE_CLIENT_ID=your_client_id_here
|
||||
VITE_CHALLONGE_REDIRECT_URI=http://localhost:5173/oauth/callback
|
||||
|
||||
# Backend (OAuth Proxy)
|
||||
CHALLONGE_CLIENT_ID=your_client_id_here
|
||||
CHALLONGE_CLIENT_SECRET=your_client_secret_here
|
||||
CHALLONGE_REDIRECT_URI=http://localhost:5173/oauth/callback
|
||||
OAUTH_PROXY_PORT=3001
|
||||
```
|
||||
|
||||
3. **Install Dependencies**
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
4. **Run Development Servers**
|
||||
```bash
|
||||
# Option 1: Run both servers with one command
|
||||
npm run dev:full
|
||||
|
||||
# Option 2: Run separately in two terminals
|
||||
# Terminal 1 - Frontend
|
||||
npm run dev
|
||||
|
||||
# Terminal 2 - OAuth Proxy
|
||||
npm run oauth-proxy
|
||||
```
|
||||
|
||||
5. **Test OAuth Flow**
|
||||
- Visit http://localhost:5173/challonge-test
|
||||
- Click "Connect with OAuth"
|
||||
- Authorize the app on Challonge
|
||||
- You'll be redirected back with tokens
|
||||
- Now you can use APPLICATION scope!
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ Vue Frontend │
|
||||
│ localhost:5173 │
|
||||
└────────┬────────┘
|
||||
│
|
||||
├─→ User clicks "Connect with OAuth"
|
||||
│ Redirect to Challonge authorization URL
|
||||
│
|
||||
├─→ User authorizes on Challonge
|
||||
│ Redirect back to /oauth/callback?code=xxx&state=yyy
|
||||
│
|
||||
├─→ Frontend calls /api/oauth/token
|
||||
│
|
||||
┌────────▼────────┐
|
||||
│ OAuth Proxy │
|
||||
│ localhost:3001 │
|
||||
└────────┬────────┘
|
||||
│
|
||||
├─→ Exchange code for tokens (includes client_secret)
|
||||
│ POST https://api.challonge.com/oauth/token
|
||||
│
|
||||
└─→ Return tokens to frontend
|
||||
Frontend stores in localStorage
|
||||
Creates v2.1 client with Bearer token
|
||||
```
|
||||
|
||||
## Files Created
|
||||
|
||||
### Backend
|
||||
- **server/oauth-proxy.js** - Express server for OAuth token exchange
|
||||
- `/oauth/token` - Exchange authorization code
|
||||
- `/oauth/refresh` - Refresh expired tokens
|
||||
- `/health` - Health check endpoint
|
||||
|
||||
### Frontend
|
||||
- **src/composables/useChallongeOAuth.js** - OAuth state management
|
||||
- Token storage and retrieval
|
||||
- Authorization URL generation
|
||||
- Automatic token refresh
|
||||
- CSRF protection
|
||||
|
||||
- **src/views/OAuthCallback.vue** - OAuth redirect handler
|
||||
- Processes authorization callback
|
||||
- Displays loading/success/error states
|
||||
- Auto-redirects to Challonge Test
|
||||
|
||||
### Configuration
|
||||
- **vite.config.js** - Added `/api/oauth` proxy
|
||||
- **src/router/index.js** - Added `/oauth/callback` route
|
||||
- **package.json** - Added dependencies and scripts
|
||||
- **.env.example** - OAuth configuration template
|
||||
|
||||
## Environment Variables
|
||||
|
||||
### Frontend (Vite - PUBLIC)
|
||||
```bash
|
||||
VITE_CHALLONGE_CLIENT_ID=xxx # OAuth Client ID (public)
|
||||
VITE_CHALLONGE_REDIRECT_URI=xxx # Callback URL
|
||||
```
|
||||
|
||||
### Backend (OAuth Proxy - PRIVATE)
|
||||
```bash
|
||||
CHALLONGE_CLIENT_ID=xxx # OAuth Client ID
|
||||
CHALLONGE_CLIENT_SECRET=xxx # OAuth Client Secret (NEVER expose)
|
||||
CHALLONGE_REDIRECT_URI=xxx # Must match registered URL
|
||||
OAUTH_PROXY_PORT=3001 # Proxy server port
|
||||
```
|
||||
|
||||
### Production (Optional)
|
||||
```bash
|
||||
NODE_ENV=production
|
||||
FRONTEND_URL=https://yourdomain.com
|
||||
```
|
||||
|
||||
## Production Deployment
|
||||
|
||||
### Option 1: Express Server (Simple)
|
||||
|
||||
Deploy `server/oauth-proxy.js` to:
|
||||
- Heroku
|
||||
- Railway
|
||||
- DigitalOcean App Platform
|
||||
- AWS EC2/ECS
|
||||
|
||||
Update production `.env`:
|
||||
```bash
|
||||
NODE_ENV=production
|
||||
FRONTEND_URL=https://yourdomain.com
|
||||
CHALLONGE_CLIENT_ID=xxx
|
||||
CHALLONGE_CLIENT_SECRET=xxx
|
||||
CHALLONGE_REDIRECT_URI=https://yourdomain.com/oauth/callback
|
||||
PORT=3000
|
||||
```
|
||||
|
||||
Update frontend build environment:
|
||||
```bash
|
||||
VITE_CHALLONGE_CLIENT_ID=xxx
|
||||
VITE_CHALLONGE_REDIRECT_URI=https://yourdomain.com/oauth/callback
|
||||
```
|
||||
|
||||
### Option 2: Serverless Functions (Scalable)
|
||||
|
||||
Convert `server/oauth-proxy.js` to serverless functions:
|
||||
|
||||
**Netlify Functions** (`netlify/functions/oauth-token.js`):
|
||||
```javascript
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
export async function handler(event) {
|
||||
if (event.httpMethod !== 'POST') {
|
||||
return { statusCode: 405, body: 'Method Not Allowed' };
|
||||
}
|
||||
|
||||
const { code } = JSON.parse(event.body);
|
||||
|
||||
const response = await fetch('https://api.challonge.com/oauth/token', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({
|
||||
grant_type: 'authorization_code',
|
||||
client_id: process.env.CHALLONGE_CLIENT_ID,
|
||||
client_secret: process.env.CHALLONGE_CLIENT_SECRET,
|
||||
code: code,
|
||||
redirect_uri: process.env.CHALLONGE_REDIRECT_URI,
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
return {
|
||||
statusCode: response.status,
|
||||
body: JSON.stringify(data),
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
**Vercel Functions** (`api/oauth/token.js`):
|
||||
```javascript
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
export default async function handler(req, res) {
|
||||
if (req.method !== 'POST') {
|
||||
return res.status(405).json({ error: 'Method Not Allowed' });
|
||||
}
|
||||
|
||||
const { code } = req.body;
|
||||
|
||||
const response = await fetch('https://api.challonge.com/oauth/token', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({
|
||||
grant_type: 'authorization_code',
|
||||
client_id: process.env.CHALLONGE_CLIENT_ID,
|
||||
client_secret: process.env.CHALLONGE_CLIENT_SECRET,
|
||||
code: code,
|
||||
redirect_uri: process.env.CHALLONGE_REDIRECT_URI,
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
res.status(response.status).json(data);
|
||||
}
|
||||
```
|
||||
|
||||
### Option 3: Cloudflare Workers (Edge)
|
||||
|
||||
```javascript
|
||||
export default {
|
||||
async fetch(request, env) {
|
||||
if (request.method !== 'POST') {
|
||||
return new Response('Method Not Allowed', { status: 405 });
|
||||
}
|
||||
|
||||
const { code } = await request.json();
|
||||
|
||||
const response = await fetch('https://api.challonge.com/oauth/token', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: new URLSearchParams({
|
||||
grant_type: 'authorization_code',
|
||||
client_id: env.CHALLONGE_CLIENT_ID,
|
||||
client_secret: env.CHALLONGE_CLIENT_SECRET,
|
||||
code: code,
|
||||
redirect_uri: env.CHALLONGE_REDIRECT_URI,
|
||||
}),
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
### ✅ DO
|
||||
- Store client_secret ONLY on backend (never in frontend)
|
||||
- Use HTTPS in production
|
||||
- Validate state parameter for CSRF protection
|
||||
- Store tokens in localStorage (XSS protection via CSP)
|
||||
- Set appropriate token expiration
|
||||
- Implement token refresh before expiration
|
||||
- Use environment variables for secrets
|
||||
|
||||
### ❌ DON'T
|
||||
- Never commit `.env` to version control
|
||||
- Never expose client_secret in frontend code
|
||||
- Never log tokens in production
|
||||
- Don't use OAuth without SSL in production
|
||||
- Don't store tokens in cookies (CSRF risk)
|
||||
|
||||
## Testing
|
||||
|
||||
### Test OAuth Flow
|
||||
1. Start both servers: `npm run dev:full`
|
||||
2. Visit http://localhost:5173/challonge-test
|
||||
3. Click "Connect with OAuth"
|
||||
4. Should redirect to Challonge
|
||||
5. Authorize the app
|
||||
6. Should redirect back to callback
|
||||
7. Should see success message
|
||||
8. Should redirect to Challonge Test
|
||||
9. OAuth status should show "Connected"
|
||||
10. Try listing tournaments with "Show all tournaments" checked
|
||||
|
||||
### Test Token Refresh
|
||||
```javascript
|
||||
// In browser console after connecting
|
||||
const { refreshToken } = useChallongeOAuth();
|
||||
await refreshToken(); // Should refresh token
|
||||
```
|
||||
|
||||
### Test Logout
|
||||
```javascript
|
||||
// In browser console
|
||||
const { logout } = useChallongeOAuth();
|
||||
logout(); // Should clear tokens
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Missing required environment variables"
|
||||
- Check `.env` file exists in project root
|
||||
- Verify `CHALLONGE_CLIENT_ID` and `CHALLONGE_CLIENT_SECRET` are set
|
||||
- Restart OAuth proxy after changing `.env`
|
||||
|
||||
### "Invalid state parameter"
|
||||
- Clear browser storage and try again
|
||||
- Verify redirect URI matches exactly
|
||||
|
||||
### "Token exchange failed"
|
||||
- Check client ID and secret are correct
|
||||
- Verify redirect URI matches registered URL exactly
|
||||
- Check OAuth proxy is running on port 3001
|
||||
- Look at OAuth proxy console for error details
|
||||
|
||||
### "CORS errors"
|
||||
- Verify Vite proxy is configured correctly
|
||||
- Check OAuth proxy CORS settings
|
||||
- Ensure frontend URL is allowed in production
|
||||
|
||||
### "Token expired"
|
||||
- Token should auto-refresh when needed
|
||||
- Manually refresh: `useChallongeOAuth().refreshToken()`
|
||||
- If refresh fails, user must re-authenticate
|
||||
|
||||
## API Scopes
|
||||
|
||||
Available scopes for Challonge OAuth:
|
||||
|
||||
- `tournaments:read` - Read tournament data
|
||||
- `tournaments:write` - Create/update tournaments
|
||||
- `participants:read` - Read participant data
|
||||
- `participants:write` - Manage participants
|
||||
- `matches:read` - Read match data
|
||||
- `matches:write` - Update match results
|
||||
- `user:read` - Read user profile
|
||||
|
||||
Default scope in app: `tournaments:read tournaments:write`
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. ✅ Basic OAuth flow working
|
||||
2. ✅ Token storage and refresh
|
||||
3. ✅ APPLICATION scope access
|
||||
4. 🔄 Add scope selector in UI (optional)
|
||||
5. 🔄 Implement token refresh UI indicator
|
||||
6. 🔄 Add "time until expiration" display
|
||||
7. 🔄 Deploy to production
|
||||
8. 🔄 Add more scopes as needed
|
||||
|
||||
## Support
|
||||
|
||||
- Challonge API Docs: https://challonge.apidog.io
|
||||
- OAuth 2.0 Spec: https://oauth.net/2/
|
||||
- Register Apps: https://connect.challonge.com
|
||||
Reference in New Issue
Block a user