Skip to content

mgierschdev/unity-firebase-backend-starter

Repository files navigation

Unity Firebase Backend Starter

A secure, emulator-first Firebase backend starter for Unity projects with authentication, Cloud Functions, and Firestore.

License: MIT

Table of Contents

  1. What this repository is
  2. Why it exists
  3. MVP features
  4. Architecture at a glance
  5. Repository structure
  6. Prerequisites
  7. Quickstart (local development)
  8. Example backend API: submitScore
  9. Firestore security model
  10. Unity client integration (overview)
  11. Testing
  12. Verification
  13. Assumptions made for MVP
  14. Sensitive information review
  15. Deployment
  16. What this template does not include
  17. When to use this repository
  18. License

1. What this repository is

This repository is a Firebase backend starter for Unity projects. It provides a secure, emulator-first setup using Firebase Auth, Cloud Functions, and Firestore, intended to be cloned and extended. It is not a full game backend and does not include gameplay logic or real-time servers.


2. Why it exists

Unity developers often need a lightweight backend for authentication, validation, and persistence, but setting up Firebase correctly is time-consuming and error-prone.

This repository exists to:

• Provide a ready-to-use Firebase backend for Unity
• Demonstrate secure server-side validation patterns
• Prevent direct client writes to sensitive data
• Enable fast local development using Firebase emulators

Target users include indie Unity developers, game jam teams, and small projects that need backend validation without running custom servers.


3. MVP features

• Firebase Auth integration (anonymous sign-in supported)
• HTTP Cloud Functions with server-side token validation
• Firestore schema and security rules aligned with backend logic
• Firebase Emulator Suite for local development
• Seeded emulator data for fast testing
• Example backend endpoint: submitScore
• Minimal automated tests against emulators


4. Architecture at a glance

Unity Client
→ Firebase Auth (ID token)
→ HTTPS Cloud Function
→ Firestore (server-validated writes only)

Clients never write directly to protected collections.

Architecture Diagram

graph TB
    subgraph "Unity Client"
        UC[Unity Game]
        FA[Firebase Auth SDK]
    end
    
    subgraph "Firebase Backend"
        AUTH[Firebase Auth Service]
        CF[Cloud Functions]
        FS[Firestore Database]
    end
    
    subgraph "Development Environment"
        EMU[Firebase Emulators]
        EMUAUTH[Emulated Auth]
        EMUCF[Emulated Functions]
        EMUFS[Emulated Firestore]
        SEED[Seeded Test Data]
    end
    
    %% Production Flow
    UC -->|1. Sign In| FA
    FA -->|2. Request Token| AUTH
    AUTH -->|3. ID Token| FA
    FA -->|4. Return Token| UC
    UC -->|5. HTTP Request + Bearer Token| CF
    CF -->|6. Verify Token| AUTH
    CF -->|7. Validate & Process| CF
    CF -->|8. Server Write| FS
    FS -->|9. Success Response| CF
    CF -->|10. JSON Response| UC
    UC -.->|11. Read Only| FS
    
    %% Development Flow
    EMU -.->|Contains| EMUAUTH
    EMU -.->|Contains| EMUCF
    EMU -.->|Contains| EMUFS
    SEED -.->|Imports to| EMUFS
    
    style UC fill:#e1f5ff
    style CF fill:#fff4e1
    style FS fill:#e8f5e9
    style AUTH fill:#fce4ec
    style EMU fill:#f3e5f5
    style SEED fill:#fff9c4
Loading

Data Flow Diagram

sequenceDiagram
    participant Unity as Unity Client
    participant Auth as Firebase Auth
    participant CF as Cloud Function
    participant FS as Firestore
    
    Note over Unity,FS: Score Submission Flow
    
    Unity->>Auth: 1. Sign in (anonymous/email)
    Auth-->>Unity: 2. User credentials
    
    Unity->>Auth: 3. Get ID Token
    Auth-->>Unity: 4. ID Token (JWT)
    
    Unity->>CF: 5. POST /submitScore<br/>{score: 1234}<br/>Header: Bearer {token}
    
    CF->>Auth: 6. Verify ID Token
    Auth-->>CF: 7. Decoded token (uid)
    
    alt Valid Token & Score
        CF->>CF: 8. Validate score<br/>(positive integer, max limit)
        CF->>FS: 9. Write /users/{uid}
        CF->>FS: 10. Write /leaderboard/{uid}
        FS-->>CF: 11. Write confirmed
        CF-->>Unity: 12. Success response<br/>{success: true, score: 1234}
    else Invalid Request
        CF-->>Unity: Error response<br/>(401/400/500)
    end
    
    Note over Unity,FS: Read Operations
    Unity->>FS: Read own user data<br/>(authenticated)
    FS-->>Unity: User document
    
    Unity->>FS: Read leaderboard<br/>(authenticated, read-only)
    FS-->>Unity: Leaderboard entries
Loading

5. Repository structure

unity-firebase-backend-starter/
│
├── functions/                    # Cloud Functions source code
│   ├── src/
│   │   └── index.ts             # Main functions (submitScore endpoint)
│   ├── test/
│   │   └── submitScore.test.ts  # Automated tests
│   ├── lib/                     # Compiled JavaScript (generated)
│   ├── package.json             # Node.js dependencies and scripts
│   ├── tsconfig.json            # TypeScript configuration
│   ├── tsconfig.dev.json        # TypeScript dev configuration
│   └── .eslintrc.js             # ESLint configuration
│
├── emulator-data/               # Seeded data for local emulators
│
├── firestore.rules              # Firestore security rules
├── firestore.indexes.json       # Firestore database indexes
├── firebase.json                # Firebase project configuration
├── .firebaserc                  # Firebase project aliases
├── LICENSE                      # MIT License
├── DISCLOSURE.md                # AI-assisted development disclosure
└── README.md                    # This file

Key Files

File Purpose
functions/src/index.ts Cloud Functions implementation (submitScore)
functions/test/submitScore.test.ts Automated tests for backend validation
firestore.rules Security rules preventing direct client writes
firebase.json Emulator configuration and project settings
emulator-data/ Pre-seeded test data for quick local development

6. Prerequisites

• Node.js 16
• Firebase CLI
• Unity 2021 or newer

Install Firebase CLI if needed:

npm install -g firebase-tools

7. Quickstart (local development)

Install backend dependencies:

npm --prefix functions install

Build Cloud Functions:

npm --prefix functions run build

Start Firebase emulators:

npm --prefix functions run serve

This starts local emulators for Auth, Firestore, and Cloud Functions.


8. Example backend API: submitScore

Endpoint

POST /submitScore

Authentication

• Firebase ID token required
• Token validated server-side

Request body

{
  "score": 1234
}

Validation rules

• User must be authenticated
• Score must be a positive integer
• Maximum score enforced server-side
• Optional cooldown between submissions

Firestore writes

/users/{uid}
/leaderboard/{uid}

All writes are performed exclusively by Cloud Functions.


9. Firestore security model

• Users can read their own user document
• Users cannot write leaderboard entries directly
• Leaderboard data is read-only from the client
• Server writes bypass client restrictions

See firestore.rules for exact definitions.

Security Rules Diagram

graph LR
    subgraph "Client Operations"
        C["Unity Client<br/>Authenticated User"]
    end
    
    subgraph "Firestore Collections"
        U["/users/UID"]
        L["/leaderboard/UID"]
    end
    
    subgraph "Server Operations"
        CF["Cloud Functions<br/>Admin SDK"]
    end
    
    %% Client permissions
    C -->|✅ READ own document| U
    C -.->|❌ WRITE denied| U
    C -->|✅ READ all entries| L
    C -.->|❌ WRITE denied| L
    
    %% Server permissions
    CF -->|✅ WRITE validated data| U
    CF -->|✅ WRITE validated data| L
    
    style C fill:#e1f5ff
    style U fill:#e8f5e9
    style L fill:#e8f5e9
    style CF fill:#fff4e1
Loading

Rule Explanation

Users Collection (/users/{uid})

  • Read: Allowed only if authenticated AND requesting own document (request.auth.uid == userId)
  • Write: Denied for all clients (only Cloud Functions can write)

Leaderboard Collection (/leaderboard/{uid})

  • Read: Allowed for any authenticated user
  • Write: Denied for all clients (only Cloud Functions can write)

Default Rule

  • All other collections: Read and write denied

10. Unity client integration (overview)

Typical Unity flow:

• Initialize Firebase
• Sign in anonymously
• Fetch Firebase ID token
• Call HTTPS endpoint with Authorization header
• Handle JSON response

Unity Integration Flow

flowchart TD
    Start([Unity Game Starts]) --> Init[Initialize Firebase SDK]
    Init --> SignIn[Sign In User<br/>Anonymous or Email]
    SignIn --> GetToken[Get ID Token from<br/>FirebaseAuth]
    GetToken --> PrepReq[Prepare HTTP Request<br/>POST /submitScore]
    PrepReq --> AddAuth[Add Authorization Header<br/>Bearer TOKEN]
    AddAuth --> AddBody[Add JSON Body<br/>score: value]
    AddBody --> Send[Send UnityWebRequest]
    Send --> WaitResp{Wait for Response}
    
    WaitResp -->|Success 200| ParseSuccess[Parse JSON Response]
    WaitResp -->|Error 4xx/5xx| ParseError[Parse Error Response]
    
    ParseSuccess --> UpdateUI[Update UI<br/>Show Success]
    ParseError --> ShowError[Show Error Message]
    
    UpdateUI --> End([Continue Game])
    ShowError --> End
    
    style Start fill:#e1f5ff
    style End fill:#e1f5ff
    style ParseSuccess fill:#e8f5e9
    style ParseError fill:#ffebee
    style Send fill:#fff4e1
Loading

Example Unity C# Integration Pseudo-code

// Pseudo-flow:
FirebaseAuthGetIdToken
UnityWebRequest → submitScore
Parse response

A minimal Unity C# example can be added separately or embedded later.


11. Testing

Run tests:

npm --prefix functions run test

Included tests validate:

• Unauthenticated requests are rejected
• Request validation (method, headers, body)
• Score validation (type, range, integer requirement)

Testing Architecture

graph TB
    subgraph "Test Suite"
        T[Mocha Test Runner]
        TC1[Test: Unauthorized Request]
        TC2[Test: Invalid Method]
        TC3[Test: Invalid Score Type]
        TC4[Test: Negative Score]
        TC5[Test: Score Too High]
        TC6[Test: Valid Score]
    end
    
    subgraph "Firebase Test Environment"
        FT[Firebase Functions Test]
        EA[Emulated Auth]
        EF[Emulated Functions]
        EFS[Emulated Firestore]
    end
    
    T --> TC1
    T --> TC2
    T --> TC3
    T --> TC4
    T --> TC5
    T --> TC6
    
    TC1 --> FT
    TC2 --> FT
    TC3 --> FT
    TC4 --> FT
    TC5 --> FT
    TC6 --> FT
    
    FT --> EA
    FT --> EF
    FT --> EFS
    
    EF -.->|Validates using| EA
    EF -.->|Writes to| EFS
    
    style T fill:#e1f5ff
    style FT fill:#fff4e1
    style EA fill:#fce4ec
    style EF fill:#fff4e1
    style EFS fill:#e8f5e9
Loading

12. Verification

This section describes how to verify the MVP is working correctly.

Prerequisites

• Java 21 or higher (required for Firebase Emulators) • Node.js 16 or higher • Firebase CLI installed globally

Build and Test

# Install dependencies
npm --prefix functions install

# Build the functions
npm --prefix functions run build

# Run tests
npm --prefix functions run test

Expected output: All tests should pass, validating:

  • Authentication requirements are enforced
  • Invalid requests are rejected with appropriate error codes
  • Score validation works correctly (positive integers only, maximum enforced)

Local Emulator Testing

# Start emulators (requires Java 21+)
firebase emulators:start --import=./emulator-data

The emulators will start on:

  • Auth: http://localhost:9099
  • Firestore: http://localhost:8080
  • Functions: http://localhost:5001
  • Emulator UI: http://localhost:4000

You can test the submitScore endpoint manually using curl:

# This should return 401 Unauthorized (no token)
curl -X POST http://localhost:5001/fir-unitygamebussbackend/us-central1/submitScore \
  -H "Content-Type: application/json" \
  -d '{"score": 1234}'

13. Assumptions made for MVP

The following assumptions were made during MVP implementation:

  1. Maximum Score: Set to 999999 as a reasonable upper bound. Can be configured in functions/src/index.ts.

  2. Cooldown: The README mentioned "optional cooldown between submissions" but this was not implemented as it was marked optional. The MVP allows unlimited submissions from authenticated users.

  3. Seeded Emulator Data: The existing emulator data is preserved and imported on emulator start, but no additional seed data was created for the MVP.

  4. Error Responses: All error responses follow a consistent JSON format with error and message fields for client-side error handling.

  5. CORS: CORS headers are set to allow all origins (*) for development convenience. In production, this should be restricted to specific domains.

  6. Anonymous Auth: Firebase Auth with anonymous sign-in is supported but not explicitly implemented or tested in the backend (server accepts any valid Firebase ID token).


14. Sensitive information review

Status: ✅ Complete

Files Reviewed:

  • Source code (functions/src/)
  • Configuration files (firebase.json, firestore.rules, firestore.indexes.json, .firebaserc)
  • Environment files (.env - none present)
  • Package files (package.json, package-lock.json)
  • Test files (functions/test/)
  • Emulator data (emulator-data/)

Findings:

  • ✅ No API keys or secrets found in source code
  • ✅ No credentials in configuration files
  • ✅ Project ID in .firebaserc is a Firebase project identifier (public, not sensitive)
  • ✅ No environment variables with secrets
  • .gitignore properly configured to exclude sensitive files (.env, Firebase cache)
  • ✅ Emulator data contains only test/seed data, no production credentials

Recommendations:

  • Before production deployment, create a .env file for sensitive configuration (do not commit it)
  • Store production API keys and service account credentials outside of version control
  • Use Firebase project-specific service accounts for production deployments
  • Rotate any credentials if you suspect they may have been exposed

15. Deployment

Select Firebase project:

firebase use <project-id>

Deploy backend and rules:

firebase deploy

Always verify behavior locally using emulators before deploying.

Deployment Flow

flowchart TD
    Start([Ready to Deploy]) --> Local[Test Locally with Emulators]
    Local --> AllPass{All Tests Pass?}
    
    AllPass -->|No| Fix[Fix Issues]
    Fix --> Local
    
    AllPass -->|Yes| Build[Build Functions<br/>npm run build]
    Build --> SelectProj[Select Firebase Project<br/>firebase use project-id]
    SelectProj --> Deploy[Deploy to Firebase<br/>firebase deploy]
    
    Deploy --> DeployWhat{What to Deploy?}
    
    DeployWhat -->|Functions Only| DF[firebase deploy --only functions]
    DeployWhat -->|Rules Only| DR[firebase deploy --only firestore:rules]
    DeployWhat -->|Everything| DA[firebase deploy]
    
    DF --> Verify
    DR --> Verify
    DA --> Verify
    
    Verify[Verify in Production] --> Success{Working?}
    
    Success -->|Yes| Done([Deployment Complete])
    Success -->|No| Rollback[Check Logs & Rollback]
    Rollback --> Fix
    
    style Start fill:#e1f5ff
    style Done fill:#e8f5e9
    style AllPass fill:#fff9c4
    style Success fill:#fff9c4
    style Rollback fill:#ffebee
    style Deploy fill:#fff4e1
Loading

16. What this template does not include

• Multiplayer matchmaking
• Real-time authoritative game servers
• Advanced anti-cheat systems
• Payments or receipt validation

These are intentionally out of scope.


17. When to use this repository

Use this template if you need:

• Server-validated scores or progression
• Secure storage for Unity games
• Fast local iteration with emulators
• A lightweight Firebase backend

Do not use it if you need:

• MMO-scale infrastructure
• Low-latency real-time simulation


18. License

MIT. See LICENSE file for details.

See also DISCLOSURE.md for important information about AI-assisted development and security responsibilities.

About

A secure, emulator-first Firebase backend starter for Unity projects with authentication, Cloud Functions, and Firestore.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors