Skip to content

Repository files navigation

Steam owned games verification POC

https://steam-verifier-poc.vercel.app/

A proof-of-concept application that demonstrates Steam authentication and game library integration. Users can authenticate with their Steam account and view their owned games with playtime statistics. It works only with public profiles.

Features

  • Steam OpenID authentication
  • Fetch and display user's Steam game library
  • Show game titles with playtime hours
  • Webhook integration for verification events
  • Cryptographic proof generation using vlayer
  • Optional database storage for verification history
  • Modern, responsive UI with glassmorphic design
  • Secure session management with HTTP-only cookies

Getting Started

Prerequisites

  1. Steam API Key - Get one from Steam Web API
  2. Node.js 18+ installed

Environment Variables

Create a .env.local file in the root directory with:

STEAM_API_KEY=your_steam_api_key_here
APP_URL=http://localhost:3000

# Optional: Database configuration (only if you want to persist verifications)
DATABASE_URL=postgresql://username:password@localhost:5432/database_name

# Optional: CLI verification script target
WEBHOOK_URL=https://your-webhook-endpoint.com/steam-games

WEBHOOK_URL is only read by scripts/test-verification.js. The web UI requires the webhook to be provided via the webhookUrl query parameter instead of an environment variable.

Installation

# Install dependencies
npm install

# Optional: Set up database (only if you want to persist verifications)
npm run db:generate  # Generate database schema
npm run db:migrate   # Apply migrations to your database

# Run the development server
npm run dev

Open http://localhost:3000/?webhookUrl=https://your-webhook-endpoint.com/steam-games&callbackUrl=https://your-dashboard.com/return with your browser (replace both URLs with your own endpoints). The interface blocks sign-in and verification if either parameter is missing or invalid.

How it Works

  1. Steam Authentication: Users click "Sign in with Steam" and are redirected to Steam's OpenID authentication
  2. User Data Retrieval: After successful authentication, the app fetches user profile information from Steam API
  3. Game Library Access: For authenticated users, the app fetches their complete game library using Steam's GetOwnedGames API
  4. Display: Games are displayed sorted by playtime, showing titles and hours played
  5. Verification: Users can trigger verification once the page is opened with both webhookUrl and callbackUrl query parameters. The app generates a cryptographic proof, posts the payload to the provided webhook URL, and then returns the user to the callback URL after success.

API Endpoints

  • GET /api/auth/steam - Initiates Steam OpenID authentication
  • GET /api/auth/steam/callback - Handles Steam authentication callback
  • GET /api/steam/games - Fetches authenticated user's game library (protected route)
  • GET /api/user - Returns current authenticated user from session
  • POST /api/verify - Triggers verification process with webhook delivery and vlayer proof generation

Webhook Integration

When a user successfully completes verification, the application sends a POST request to the webhook that was passed on the landing URL (/?webhookUrl=https://your-endpoint&callbackUrl=https://your-dashboard). The payload structure is:

{
  "steam_user": {
    "id": "76561198000000000",
    "name": "PlayerUsername",
    "image": "https://avatars.steamstatic.com/abcd1234_full.jpg",
    "profileUrl": "https://steamcommunity.com/profiles/76561198000000000/"
  },
  "games": {
    "game_count": 150,
    "games": [
      {
        "appid": 730,
        "name": "Counter-Strike 2",
        "playtime_forever": 2847,
        "img_icon_url": "0123456789abcdef",
        "img_logo_url": "fedcba9876543210",
        "playtime_windows_forever": 2847,
        "playtime_mac_forever": 0,
        "playtime_linux_forever": 0,
        "rtime_last_played": 1703980800,
        "playtime_disconnected": 0
      }
    ]
  },
  "vlayer_proof": {
    "presentation": "{\"presentationJson\":{\"data\":\"0140000000000000005a983a6ce90e1062b4f331502210..00000\",\"meta\":{\"notaryUrl\":\"https://test-notary.vlayer.xyz:443\",\"websocketProxyUrl\":\"\"},\"version\":\"0.1.0-alpha.11\"}}"
  },
  "timestamp": "2024-01-01T12:00:00.000Z"
}

Webhook & Callback Requirements

  • Provide both URLs up front: Append ?webhookUrl=https://your-webhook-endpoint.com/steam-games&callbackUrl=https://your-dashboard.com/return to the main page before trying to sign in or verify. The login CTA is disabled until valid URLs are present.
  • Endpoint: Must accept POST requests with JSON payload.
  • Response: Should return 2xx status code to indicate success.
  • Timeout: Webhook requests timeout after 10 seconds.
  • Retry: No automatic retries are performed; failures are surfaced in the UI and response body.
  • Post-verification redirect: After a successful webhook response, the app shows the success screen briefly and then redirects the browser to the supplied callbackUrl.

Database Integration (Optional)

The application can optionally store verification results in a PostgreSQL database for historical tracking and analytics.

Database Features

  • Optional Configuration: Works with or without database
  • Verification History: Stores complete verification records including:
    • Steam user profile data
    • Game library snapshots
    • vlayer cryptographic proofs
    • Webhook delivery status
    • Timestamps for audit trails

Database Setup

  1. Configure Database URL in your .env.local:

    DATABASE_URL=postgresql://username:password@localhost:5432/database_name
  2. Run Database Migrations:

    npm run db:generate  # Generate schema
    npm run db:migrate   # Apply to database
  3. Database Management:

    npm run db:studio    # Open Drizzle Studio for database browsing

Database Schema

The verifications table includes:

  • User identification (Steam ID, username, avatar)
  • Game data (count, complete library JSON)
  • Verification proof (vlayer cryptographic proof)
  • Webhook status (delivery success, HTTP status)
  • Audit timestamps

Note: If DATABASE_URL is not configured, the application will work normally but verification results won't be persisted.

Technologies Used

  • Next.js 14 - React framework with App Router
  • TypeScript - Type-safe development
  • Tailwind CSS - Utility-first CSS framework
  • Steam Web API - Game data and authentication
  • Axios - HTTP client for API requests
  • Drizzle ORM - Type-safe database toolkit (optional)
  • PostgreSQL - Database for verification storage (optional)

Powered by

Built with ❤️ using vlayer - The verifiable data layer for applications.

License

Copyright 2025 vlayer.xyz

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Releases

Packages

Contributors

Languages