Authentication API

PadawanForge uses a connected accounts OAuth2 authentication system with support for multiple providers and account linking.

Base Path

/api/auth/

OAuth Providers

Google OAuth

Initiate Google Authentication

GET/POST /api/auth/google

Response:

  • Redirects to Google OAuth consent screen with OpenID Connect support
  • Uses access_type: 'offline' for refresh tokens
  • After consent, redirects to callback URL

Google OAuth Callback

GET /api/auth/callback/google

Query Parameters:

  • code - Authorization code from Google
  • state - CSRF protection token

Response:

  • Creates or updates player session
  • Creates connected account record
  • Redirects to appropriate page based on onboarding status

Discord OAuth

Initiate Discord Authentication

GET/POST /api/auth/discord

Response:

  • Redirects to Discord OAuth consent screen
  • Requests identify and email scopes
  • After consent, redirects to callback URL

Discord OAuth Callback

GET /api/auth/callback/discord

Query Parameters:

  • code - Authorization code from Discord
  • state - CSRF protection token

Response:

  • Creates or updates player session
  • Creates connected account record
  • Redirects to appropriate page based on onboarding status

Provider Information

Available Providers

GET /api/auth/available-providers

Response:

{
  "success": true,
  "providers": {
    "google": {
      "available": true,
      "clientId": "configured",
      "clientSecret": "configured"
    },
    "discord": {
      "available": true,
      "clientId": "configured", 
      "clientSecret": "configured"
    },
    "apple": {
      "available": false,
      "clientId": "missing",
      "clientSecret": "missing"
    },
    "slack": {
      "available": false,
      "clientId": "missing",
      "clientSecret": "missing"
    }
  },
  "availableProviders": ["google", "discord"],
  "totalProviders": 4,
  "configuredProviders": 2
}

Registration Flow

Complete Registration

POST /api/auth/complete-registration

Authentication: Required

Request Body:

{
  "username": "string",
  "birthday": "YYYY-MM-DD" // optional
}

Response:

{
  "success": true,
  "message": "Registration completed successfully",
  "player": {
    "displayName": "string",
    "birthday": "YYYY-MM-DD",
    "registrationCompleted": true
  }
}

Complete Tutorial

POST /api/auth/complete-tutorial

Authentication: Required

Response:

{
  "success": true,
  "message": "Tutorial completed successfully",
  "tutorialCompleted": true,
  "onboardingCompletedAt": "2024-01-15T10:30:00Z"
}

Logout

GET/POST /api/auth/logout

Response:

  • Clears session from KV storage
  • Clears session cookie
  • Redirects to home page

Connected Accounts

List Connected Accounts

GET /api/auth/connected-accounts

Authentication: Required

Response:

{
  "success": true,
  "connectedAccounts": [
    {
      "id": 1,
      "provider": "google",
      "providerUserId": "123456789",
      "providerEmail": "user@gmail.com",
      "providerUsername": "User Name",
      "providerAvatar": "https://...",
      "isPrimary": true,
      "connectedAt": "2024-01-15T10:30:00Z",
      "lastUsed": "2024-01-16T14:20:00Z"
    },
    {
      "id": 2,
      "provider": "discord",
      "providerUserId": "987654321",
      "providerEmail": "user@discord.com", 
      "providerUsername": "DiscordUser#1234",
      "providerAvatar": "https://...",
      "isPrimary": false,
      "connectedAt": "2024-01-16T14:20:00Z",
      "lastUsed": "2024-01-16T14:20:00Z"
    }
  ]
}

Set Primary Provider

POST /api/auth/connected-accounts/set-primary/[provider]

Authentication: Required

Parameters:

  • provider - Provider ID (google, discord only)

Response:

{
  "success": true,
  "message": "discord set as primary account"
}

Disconnect Account

DELETE /api/auth/connected-accounts/disconnect/[provider]

Authentication: Required

Parameters:

  • provider - Provider ID to disconnect

Response:

{
  "success": true,
  "message": "discord account disconnected successfully"
}

Error Cases:

  • Cannot disconnect the only remaining account
  • Cannot disconnect primary account without having another connected account

Session Information

Session data is automatically included in authenticated requests and contains:

{
  "id": "session_uuid",
  "playerId": "player_uuid",
  "playerUuid": "public_uuid",
  "defaultProvider": "google",
  "currentProvider": "google", 
  "provider": "google",
  "email": "user@example.com",
  "username": "User Name",
  "avatar": "https://...",
  "level": 5,
  "experience": 1250,
  "birthday": "1990-01-01",
  "location": "San Francisco, CA",
  "gender": "Prefer not to say",
  "registrationCompleted": true,
  "tutorialCompleted": true,
  "onboardingCompletedAt": "2024-01-15T10:30:00Z",
  "createdAt": "2024-01-15T10:30:00Z",
  "expiresAt": "2024-01-22T10:30:00Z"
}

OAuth Configuration

Google OAuth Setup

  1. Create project in Google Cloud Console
  2. Enable Google+ API
  3. Configure OAuth consent screen with OpenID Connect
  4. Create OAuth 2.0 credentials
  5. Set authorized redirect URIs:
    • https://yourdomain.com/api/auth/callback/google
  6. Configure environment variables:
    • OAUTH_GOOGLE_CLIENT_ID
    • OAUTH_GOOGLE_CLIENT_SECRET

Discord OAuth Setup

  1. Create application in Discord Developer Portal
  2. Configure OAuth2 settings
  3. Set redirect URIs:
    • https://yourdomain.com/api/auth/callback/discord
  4. Request required scopes: identify, email
  5. Configure environment variables:
    • OAUTH_DISCORD_CLIENT_ID
    • OAUTH_DISCORD_CLIENT_SECRET

Error Responses

Authentication endpoints return simple error responses:

{
  "error": "Error description"
}

Common Error Types

Unauthorized Access

{
  "error": "Unauthorized"
}

Invalid Provider

{
  "error": "Invalid provider"
}

Registration/Validation Errors

{
  "error": "Display name is required"
}
{
  "error": "Invalid birthday format"
}

Database/System Errors

{
  "error": "Database not available"
}
{
  "error": "Failed to complete registration"
}

Account Management Errors

{
  "error": "Failed to set primary account"
}
{
  "error": "Cannot disconnect the last connected account"
}

Security Features

  • CSRF Protection: State parameter validation for all OAuth flows
  • Secure Sessions: Cloudflare KV-based session storage with automatic expiration
  • Cookie Security: HttpOnly, Secure (production), SameSite=Lax
  • Session Expiration: 7-day automatic expiration with cleanup
  • Provider Validation: Verify OAuth responses with provider APIs
  • Email Verification: Ensure email ownership through OAuth providers
  • Account Isolation: UUID-based public identifiers protect real user IDs

Rate Limits

  • OAuth attempts: 10 attempts per IP per hour
  • Registration completion: 5 attempts per session per hour
  • Account linking operations: 10 operations per user per hour
  • Provider availability checks: Cached for 5 minutes

Connected Accounts Architecture

  1. UUID-Based Identity: Players are identified by UUIDs for privacy
  2. Currently Supported Providers: Only Google and Discord are fully implemented
  3. Primary Provider: One provider serves as the default for the account
  4. Account Linking: Users can connect both Google and Discord to one account
  5. Graceful Fallback: If primary provider fails, system can use secondary accounts
  6. Privacy Protection: Only necessary profile information is stored from OAuth providers

Implementation Notes

Provider Support Status

  • Google: ✅ Fully implemented with OpenID Connect
  • Discord: ✅ Fully implemented with standard OAuth 2.0
  • Apple: ❌ Configuration exists but no endpoints implemented
  • Slack: ❌ Configuration exists but no endpoints implemented

Session Management

  • Sessions are stored in Cloudflare KV with 7-day TTL
  • Session cookies are HttpOnly and secure in production
  • Expired sessions are automatically cleaned up
  • Players can have multiple active sessions

Database Integration

  • Connected accounts are stored in player_connected_accounts table
  • Player data is split across multiple normalized tables
  • UUID-based foreign key relationships ensure data integrity
  • Soft cascading deletes protect against accidental data loss

Future Provider Support

  • Apple and Slack have OAuth configurations ready
  • Implementation requires creating corresponding API endpoints:
    • /api/auth/apple and /api/auth/callback/apple
    • /api/auth/slack and /api/auth/callback/slack
  • Database constraints already support these providers

Migration Support

  • Legacy provider-prefixed IDs are supported during transition
  • Backward compatibility maintained for existing sessions
  • Migration utilities available for seamless rollout
PadawanForge v1.4.1