AI Arena competition platform with Topcoder authentication integration.
| Layer | Technology |
|---|---|
| Backend | Java 17, Jersey (JAX-RS), Maven |
| Frontend | HTML5, Vanilla JavaScript (ES6+), CSS3 |
| Authentication | tc-auth-lib, JWT (HS256/RS256) |
| Testing | JUnit 5 (Java), Jest 29.7.0 (JavaScript) |
| Container | Docker, Jetty 11 |
npm run docker:build
npm run docker:runAfter pulling updates:
npm run docker:restartFor testing with Topcoder authentication using the local.topcoder-dev.com domain:
1. Add hosts entry:
npm run hosts:add
# Or manually: echo '127.0.0.1 local.topcoder-dev.com' | sudo tee -a /etc/hosts2. Generate SSL certificates:
npm run ssl:generate3. Trust the certificate (optional, avoids browser warnings):
# macOS
npm run ssl:trust:mac
# Linux
npm run ssl:trust:linux4. Build and run with HTTPS:
npm run docker:restart:https5. Access the application:
Note: The HTTPS Docker setup uses production Topcoder auth URLs to avoid CSP issues with dev auth servers.
npm run devThis starts a development server with mock APIs at http://localhost:8080
For HTTPS development with local.topcoder-dev.com:
# Generate and trust certificates first (see Docker HTTPS section above)
sudo npm run dev:httpsAccess at https://local.topcoder-dev.com/
Note:
sudois required for port 443 on macOS/Linux.
Requires Java 17 and Maven installed.
npm run build
npm start| Page | HTTP | HTTPS (local.topcoder-dev.com) |
|---|---|---|
| Home | http://localhost:8080/ | https://local.topcoder-dev.com/ |
| Arena | http://localhost:8080/arena.html | https://local.topcoder-dev.com/arena.html |
| Admin | http://localhost:8080/admin.html | https://local.topcoder-dev.com/admin.html |
Both arena.html and admin.html include authentication controls in the header:
| Component | State | Description |
|---|---|---|
| Login Button | Unauthenticated | Redirects to Topcoder auth |
| Member Handle | Authenticated | Displays user's Topcoder handle |
| Logout Button | Authenticated | Clears session and redirects |
| Loading Indicator | Loading | Shown during auth check |
- Unauthenticated: Shows "Login" button only
- Authenticated: Shows member handle + "Logout" button
- Loading: Shows spinner during authentication check
- Error: Shows error message with retry option
The frontend uses Topcoder's tc-auth-lib pattern:
src/main/webapp/js/auth/
├── auth-config.js # Environment configuration
├── auth-service.js # Token management, API calls
└── auth-ui.js # UI state management
- V3 Token: Obtained from tc-auth-lib connector (RS256)
- V2 Token: Read from
tcjwtcookie (HS256, legacy) - Auto-refresh: Tokens refreshed before expiration
- Storage: Memory only (not localStorage)
Retrieved from decoded JWT token:
| Field | Required | Usage |
|---|---|---|
handle |
Yes | Displayed in header |
userId |
No | Internal tracking |
roles |
No | Admin access control |
File: src/main/resources/auth.properties
# Development
topcoder.auth.connector.url=https://accounts-auth0.topcoder-dev.com
topcoder.auth.jwks.url=https://topcoder-dev.auth0.com/.well-known/jwks.json
# Production
topcoder.auth.connector.url=https://accounts-auth0.topcoder.com
topcoder.auth.jwks.url=https://topcoder.auth0.com/.well-known/jwks.jsonBackend validates tokens using:
| Token Type | Algorithm | Validation Method |
|---|---|---|
| V2 | HS256 | Shared secret (TC_AUTH_SECRET) |
| V3 | RS256 | Public JWKS (no secret needed) |
Allowed origins (configured in CorsFilter.java):
https://*.topcoder.comhttps://*.topcoder-dev.comhttp://localhost:*
- User clicks Login button
- Frontend generates login URL with return URL
- User redirected to
accounts-auth0.topcoder[-dev].com - User authenticates with Topcoder credentials
- Redirected back with JWT in
tcjwtcookie - Frontend detects token, updates UI to authenticated state
https://accounts-auth0.topcoder-dev.com/?retUrl={encoded_return_url}
- User clicks Logout button
- Frontend clears local authentication state
- Frontend clears member information from memory
- Redirect to Topcoder logout URL
- Cookie cleared, UI shows login button
https://accounts-auth0.topcoder-dev.com/?logout=true&retUrl={encoded_return_url}
Admin features require appropriate roles:
| Role | Access Level |
|---|---|
administrator |
Full admin access |
Topcoder User |
Standard user access |
All admin endpoints:
- Require valid authentication token
- Check user roles before processing
- Return
401for missing/invalid token - Return
403for insufficient permissions
- Stores member handle for authenticated users
- Anonymous registration still supported for testing
- Scores associated with member handle
- Leaderboards display member handles
- Score history available for authenticated users
- Progress persisted by member handle
- Cross-session progress retrieval
- History available for authenticated users
| Error | Cause | User Action |
|---|---|---|
| Invalid Token | Malformed JWT | Re-login |
| Expired Token | Token past expiration | Re-login |
| Network Error | Connection failed | Retry |
| Service Unavailable | Auth service down | Wait and retry |
Loading indicators shown during:
- Initial authentication check
- Token refresh operations
- Member profile retrieval
- Logout process
npm testnpm run test:backendTests cover:
- Valid token validation
- Invalid/expired token handling
- Member profile retrieval
- Role verification
- CORS configuration
npm run test:frontendTests cover:
- Authentication initialization
- Token retrieval and management
- Login/logout URL generation
- UI state transitions
Check authentication status.
Response (Authenticated):
{
"authenticated": true,
"memberInfo": {
"handle": "billsedison",
"userId": "12345",
"roles": ["Topcoder User"]
}
}Response (Unauthenticated):
{
"authenticated": false,
"error": "No authentication token provided"
}Get member profile by handle.
Response:
{
"handle": "billsedison",
"userId": "12345",
"status": "active"
}| Method | Endpoint | Auth Required |
|---|---|---|
| POST | /api/contestants/register |
Yes |
| GET | /api/contestants/registration/{competitionId} |
Yes |
| GET | /api/contestants/my-registrations |
Yes |
| DELETE | /api/contestants/unregister/{competitionId} |
Yes |
| Method | Endpoint | Auth Required |
|---|---|---|
| POST | /api/scores/submit |
Yes |
| GET | /api/scores/leaderboard/{competitionId} |
No |
| GET | /api/scores/my-scores |
Yes |
| GET | /api/scores/my-rank/{competitionId} |
Yes |
| Method | Endpoint | Auth Required |
|---|---|---|
| POST | /api/progress/save |
Yes |
| GET | /api/progress/load/{competitionId} |
Yes |
| GET | /api/progress/history |
Yes |
| DELETE | /api/progress/clear/{competitionId} |
Yes |
| Code | Meaning |
|---|---|
| 200 | Success |
| 401 | Not authenticated |
| 403 | Forbidden (insufficient permissions) |
| 404 | Not found |
| Variable | Description | Required |
|---|---|---|
ENVIRONMENT |
development or production |
No (default: production) |
TC_AUTH_SECRET |
HS256 secret for V2 tokens | Only for V2 tokens |
Note: V3 (RS256) tokens use public JWKS - no secret required.
| Setting | Development | Production |
|---|---|---|
| Auth URL | accounts-auth0.topcoder-dev.com |
accounts-auth0.topcoder.com |
| JWKS URL | topcoder-dev.auth0.com |
topcoder.auth0.com |
| Cookie Domain | localhost |
.topcoder.com |
| Script | Description |
|---|---|
npm run dev |
Start dev server with mock APIs |
npm run dev:https |
Start dev server with HTTPS on port 443 |
npm run build |
Build with Maven |
npm start |
Run production server (Maven/Jetty) |
npm test |
Run all tests |
npm run test:frontend |
Run Jest tests |
npm run test:backend |
Run JUnit tests |
npm run docker:build |
Build Docker image |
npm run docker:run |
Run Docker container (HTTP) |
npm run docker:run:https |
Run Docker container (HTTPS on 443) |
npm run docker:stop |
Stop Docker container |
npm run docker:restart |
Rebuild and restart Docker (HTTP) |
npm run docker:restart:https |
Rebuild and restart Docker (HTTPS) |
npm run docker:logs |
View Docker container logs |
npm run ssl:generate |
Generate self-signed SSL certificates |
npm run ssl:trust:mac |
Trust SSL certificate on macOS |
npm run ssl:trust:linux |
Trust SSL certificate on Linux |
npm run ssl:setup:mac |
Generate + trust certificate (macOS) |
npm run ssl:setup:linux |
Generate + trust certificate (Linux) |
npm run hosts:add |
Add local.topcoder-dev.com to /etc/hosts |
npm run clean |
Clean build artifacts |
src/main/
├── java/com/terra/vibe/arena/
│ ├── api/ # REST endpoints (AuthResource, etc.)
│ ├── auth/ # JWT validation, filters
│ ├── config/ # Auth config, CORS filter
│ ├── model/ # Data models (Contestant, Score, Progress)
│ └── service/ # Business logic services
├── resources/
│ └── auth.properties # Authentication configuration
└── webapp/
├── js/auth/ # Frontend authentication
│ ├── auth-config.js
│ ├── auth-service.js
│ └── auth-ui.js
├── css/ # Stylesheets
├── index.html # Home page
├── arena.html # Contestant interface
└── admin.html # Admin interface
- Token Storage: Tokens stored in memory only, never in localStorage
- HTTPS: Required in production for secure cookies
- CORS: Configured to allow only legitimate origins
- Server Validation: Tokens always validated server-side
- Role Checks: Admin features protected by role verification
- Error Messages: Sensitive information not exposed in errors
| Browser | Supported Versions |
|---|---|
| Chrome/Edge | Latest 2 versions |
| Firefox | Latest 2 versions |
| Safari | Latest 2 versions |
- Token expired → Re-login
- Missing
TC_AUTH_SECRETfor V2 tokens - Invalid token format
- Check origin is allowed in
CorsFilter.java - Ensure credentials included in requests
- Ensure HTTPS in production
- Check cookie domain matches app domain
- Verify SameSite cookie settings
- Normal on localhost due to cross-origin restrictions
- Does not affect production deployment
- Use
npm run devwhich skips iframe auth - For full auth testing, use HTTPS with
local.topcoder-dev.com
- Browser warnings: Trust the certificate using
npm run ssl:trust:macorssl:trust:linux - Certificate not found: Run
npm run ssl:generatefirst - Port 443 permission denied: Use
sudo(required on macOS/Linux for port 443)
- Check return URL is properly encoded
- Verify auth URL matches environment
This project includes security scanning configuration:
- OWASP Dependency Check: Run
mvn org.owasp:dependency-check-maven:checkto scan for vulnerable dependencies - Docker Security: Container runs as non-root user with health checks enabled
- Input Validation: All user inputs validated with regex patterns
| Practice | Implementation |
|---|---|
| Non-root container | USER jetty in Dockerfile |
| Health checks | Docker HEALTHCHECK directive |
| Pinned versions | Specific image/dependency versions |
| CORS validation | Whitelist-based origin checking |
| Token validation | Signature verification required |
| Input sanitization | Regex pattern validation |
Please report security vulnerabilities to security@topcoder.com.
Copyright 2024 AI Arena / Topcoder
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
See the LICENSE file for details.
This project uses third-party dependencies with permissive open-source licenses. See THIRD-PARTY-LICENSES.md and NOTICE for details.