Mastering Photon Engine Custom Authentication in PHP: Hybrid GET/POST Auto-Detection, ResultCode JSON Handshake, and Unity C# Client Architecture
Executive Overview & Architectural Roadmap
When engineering multiplayer titles with Exit Games Photon Engine (Photon Realtime, PUN2, Photon Fusion, or Photon Quantum), securing your game rooms against unauthorized access, session spoofing, and malicious actors is paramount. By default, Photon Cloud allows anonymous connections where any client can assign itself an arbitrary UserId.
To establish an authoritative security perimeter, developers implement Photon Custom Authentication. This architectural pattern offloads user verification to your authoritative web backend (written in PHP), enabling secure validation of user credentials, database sessions, ban statuses, player MMR, and custom inventory tokens before Photon grants entrance to the master server and room matchmaking.
A common stumbling block when engineering a Photon authentication backend is handling HTTP methods. By default, Photon Cloud issues HTTP GET requests with URL query parameters to your authentication endpoint, but your game client or custom webhooks might also send HTTP POST requests containing application/x-www-form-urlencoded or raw application/json payloads.
This masterclass delivers a complete, production-ready blueprint for implementing a Hybrid Auto-Detecting Photon Custom Authentication Gateway in PHP that seamlessly handles both GET and POST requests, emits strict ResultCode and Message JSON envelopes, and integrates with Unity C#.
======================================================================================================
PHOTON CUSTOM AUTHENTICATION 3-WAY HANDSHAKE
======================================================================================================
[ Unity Game Client ] [ Photon Cloud Master ] [ Custom PHP Backend ]
| | |
| 1. ConnectUsingSettings() | |
| AuthValues(type=Custom) | |
| AuthParameters: | |
| "username=alice&token=xyz..." | |
|====================================>| |
| | 2. HTTP GET / POST Webhook Request |
| | https://api.yourdomain.com/auth |
| |===================================>|
| | |
| | | 3. Hybrid Resolver:
| | | - Read GET / POST
| | | - PDO DB Lookup
| | | - Token / HMAC Check
| | | - Ban Verification
| | |
| | 4. HTTP 200 JSON Response Contract |
| | { |
| | "ResultCode": 1, |
| | "UserId": "usr_99182", |
| | "Nickname": "Alice_99", |
| | "Data": { "mmr": 1850 } |
| | } |
| |<===================================|
| 5. Authentication Accepted | |
| OnConnectedToMaster() | |
| OnCustomAuthenticationResponse() | |
|<====================================| |
| | |
======================================================================================================
Module 1: The Photon Custom Authentication Protocol Specification
1.1 How the Authentication Gateway Operates
When a Unity client attempts to connect to Photon Cloud with custom authentication enabled:
- The client constructs an
AuthenticationValues instance with CustomAuthenticationType.Custom and sets query parameters (e.g., username, session token, or ticket).
- Photon Cloud intercepts the connection request at the Name Server / Master Server.
- Photon Cloud issues an HTTP request to your configured PHP endpoint URL.
- Your PHP script validates the request and returns a JSON payload containing a
ResultCode.
- If
ResultCode == 1, Photon accepts the client, binds the authoritative UserId to the player's actor, passes the Data dictionary to the client, and permits room operations.
- If
ResultCode != 1, Photon immediately severs the connection and fires the OnCustomAuthenticationFailed callback on the Unity client with your custom Message.
1.2 The Photon JSON Response Schema
Photon Cloud requires your PHP backend to return a strict JSON envelope with the following schema:
| JSON Field Name |
Type |
Mandatory |
Description |
ResultCode |
Integer |
YES |
Status code: 1 = Approved/Success, 2 = Invalid Credentials/Parameters, 3 = User Banned, 0 = Internal Server Error. |
Message |
String |
Optional |
Human-readable diagnostic string returned to the game client upon success or failure. |
UserId |
String |
Optional |
Authoritative persistent user ID bound to the player across all Photon rooms and matchmaking filters. |
Nickname |
String |
Optional |
Overrides the player's display name inside Photon rooms. |
Data |
Object / Dict |
Optional |
Custom key-value pairs (e.g. player level, MMR rating, team ID, inventory tokens) delivered to Unity via OnCustomAuthenticationResponse. |
Success Response Example:
<span class="token punctuation">{</span>
<span class="token property">"ResultCode"</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
<span class="token property">"Message"</span><span class="token operator">:</span> <span class="token string">"Authentication successful."</span><span class="token punctuation">,</span>
<span class="token property">"UserId"</span><span class="token operator">:</span> <span class="token string">"player_8829104"</span><span class="token punctuation">,</span>
<span class="token property">"Nickname"</span><span class="token operator">:</span> <span class="token string">"Valkyrie"</span><span class="token punctuation">,</span>
<span class="token property">"Data"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"account_tier"</span><span class="token operator">:</span> <span class="token string">"VIP_Gold"</span><span class="token punctuation">,</span>
<span class="token property">"mmr"</span><span class="token operator">:</span> <span class="token number">2150</span><span class="token punctuation">,</span>
<span class="token property">"inventory_token"</span><span class="token operator">:</span> <span class="token string">"inv_sec_88f9104b20a1"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
Failure Response Example (Invalid Credentials / Expired Session):
<span class="token punctuation">{</span>
<span class="token property">"ResultCode"</span><span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">,</span>
<span class="token property">"Message"</span><span class="token operator">:</span> <span class="token string">"Invalid session token or authentication ticket has expired."</span>
<span class="token punctuation">}</span>
Banned Player Response Example:
<span class="token punctuation">{</span>
<span class="token property">"ResultCode"</span><span class="token operator">:</span> <span class="token number">3</span><span class="token punctuation">,</span>
<span class="token property">"Message"</span><span class="token operator">:</span> <span class="token string">"Account suspended due to terms of service violation. Contact support."</span>
<span class="token punctuation">}</span>
Module 2: Designing the Hybrid GET / POST Request Engine
2.1 The Dilemma: GET vs POST in Photon Cloud
In the Photon Cloud Dashboard, when you register a Custom Authentication provider:
- Default Behavior: Photon Cloud sends an HTTP GET request with the parameters concatenated to your URL as query strings:
https://api.yourdomain.com/photon_auth.php?username=alice&token=abc123.
- POST Configuration: If configured in the dashboard or invoked from custom microservices, Photon issues an HTTP POST with
application/x-www-form-urlencoded or application/json.
If your PHP script naively inspects only $_POST, all default Photon connections will fail with empty parameters. Conversely, if it only checks $_GET, modern JSON POST payloads will be ignored.
2.2 The Unified Hybrid Parameter Extractor
To achieve 100% compatibility across all Photon configurations, our PHP architecture implements a Hybrid Parameter Resolver:
<span class="token php language-php"><span class="token delimiter important"><?php</span>
<span class="token comment">// Unified Hybrid Parameter Extraction Function</span>
<span class="token keyword">function</span> <span class="token function-definition function">resolveRequestParameters</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">array</span>
<span class="token punctuation">{</span>
<span class="token variable">$params</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// 1. Ingest URL query string parameters (Default Photon GET behavior)</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">empty</span><span class="token punctuation">(</span><span class="token variable">$_GET</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token variable">$_GET</span> <span class="token keyword">as</span> <span class="token variable">$key</span> <span class="token operator">=></span> <span class="token variable">$value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token variable">$params</span><span class="token punctuation">[</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token variable">$key</span><span class="token punctuation">)</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">is_string</span><span class="token punctuation">(</span><span class="token variable">$value</span><span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token function">trim</span><span class="token punctuation">(</span><span class="token variable">$value</span><span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token variable">$value</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// 2. Ingest Standard Form POST data (application/x-www-form-urlencoded)</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">empty</span><span class="token punctuation">(</span><span class="token variable">$_POST</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token variable">$_POST</span> <span class="token keyword">as</span> <span class="token variable">$key</span> <span class="token operator">=></span> <span class="token variable">$value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token variable">$params</span><span class="token punctuation">[</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token variable">$key</span><span class="token punctuation">)</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">is_string</span><span class="token punctuation">(</span><span class="token variable">$value</span><span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token function">trim</span><span class="token punctuation">(</span><span class="token variable">$value</span><span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token variable">$value</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// 3. Ingest Raw JSON POST Body (application/json)</span>
<span class="token variable">$rawInput</span> <span class="token operator">=</span> <span class="token function">file_get_contents</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'php://input'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">empty</span><span class="token punctuation">(</span><span class="token variable">$rawInput</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token variable">$jsonData</span> <span class="token operator">=</span> <span class="token function">json_decode</span><span class="token punctuation">(</span><span class="token variable">$rawInput</span><span class="token punctuation">,</span> <span class="token constant boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">is_array</span><span class="token punctuation">(</span><span class="token variable">$jsonData</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token variable">$jsonData</span> <span class="token keyword">as</span> <span class="token variable">$key</span> <span class="token operator">=></span> <span class="token variable">$value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token variable">$params</span><span class="token punctuation">[</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token variable">$key</span><span class="token punctuation">)</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">is_string</span><span class="token punctuation">(</span><span class="token variable">$value</span><span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token function">trim</span><span class="token punctuation">(</span><span class="token variable">$value</span><span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token variable">$value</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token variable">$params</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></span>
This function normalizes all incoming requests into a single associative array, guaranteeing seamless execution whether Photon Cloud calls your endpoint via GET, standard POST, or JSON POST.
Module 3: Full Production PHP Implementation (photon_auth.php)
Let us build the complete, production-ready custom authentication script.
3.1 Database User Table Schema (MySQL)
<span class="token keyword">CREATE</span> <span class="token keyword">TABLE</span> <span class="token keyword">IF</span> <span class="token operator">NOT</span> <span class="token keyword">EXISTS</span> game_users <span class="token punctuation">(</span>
user_id <span class="token keyword">INT</span> <span class="token keyword">UNSIGNED</span> <span class="token keyword">AUTO_INCREMENT</span> <span class="token keyword">PRIMARY</span> <span class="token keyword">KEY</span><span class="token punctuation">,</span>
photon_uid <span class="token keyword">VARCHAR</span><span class="token punctuation">(</span><span class="token number">64</span><span class="token punctuation">)</span> <span class="token operator">NOT</span> <span class="token boolean">NULL</span> <span class="token keyword">UNIQUE</span><span class="token punctuation">,</span>
username <span class="token keyword">VARCHAR</span><span class="token punctuation">(</span><span class="token number">48</span><span class="token punctuation">)</span> <span class="token operator">NOT</span> <span class="token boolean">NULL</span> <span class="token keyword">UNIQUE</span><span class="token punctuation">,</span>
password_hash <span class="token keyword">VARCHAR</span><span class="token punctuation">(</span><span class="token number">255</span><span class="token punctuation">)</span> <span class="token operator">NOT</span> <span class="token boolean">NULL</span><span class="token punctuation">,</span>
session_token <span class="token keyword">VARCHAR</span><span class="token punctuation">(</span><span class="token number">128</span><span class="token punctuation">)</span> <span class="token keyword">DEFAULT</span> <span class="token boolean">NULL</span><span class="token punctuation">,</span>
token_expires_at <span class="token keyword">DATETIME</span> <span class="token keyword">DEFAULT</span> <span class="token boolean">NULL</span><span class="token punctuation">,</span>
mmr_rating <span class="token keyword">INT</span> <span class="token keyword">UNSIGNED</span> <span class="token operator">NOT</span> <span class="token boolean">NULL</span> <span class="token keyword">DEFAULT</span> <span class="token number">1000</span><span class="token punctuation">,</span>
account_tier <span class="token keyword">VARCHAR</span><span class="token punctuation">(</span><span class="token number">32</span><span class="token punctuation">)</span> <span class="token operator">NOT</span> <span class="token boolean">NULL</span> <span class="token keyword">DEFAULT</span> <span class="token string">'Standard'</span><span class="token punctuation">,</span>
is_banned <span class="token keyword">TINYINT</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">NOT</span> <span class="token boolean">NULL</span> <span class="token keyword">DEFAULT</span> <span class="token number">0</span><span class="token punctuation">,</span>
ban_reason <span class="token keyword">VARCHAR</span><span class="token punctuation">(</span><span class="token number">255</span><span class="token punctuation">)</span> <span class="token keyword">DEFAULT</span> <span class="token boolean">NULL</span><span class="token punctuation">,</span>
created_at <span class="token keyword">DATETIME</span> <span class="token operator">NOT</span> <span class="token boolean">NULL</span> <span class="token keyword">DEFAULT</span> <span class="token keyword">CURRENT_TIMESTAMP</span><span class="token punctuation">,</span>
<span class="token keyword">INDEX</span> idx_auth_token <span class="token punctuation">(</span>photon_uid<span class="token punctuation">,</span> session_token<span class="token punctuation">)</span>
<span class="token punctuation">)</span> <span class="token keyword">ENGINE</span><span class="token operator">=</span><span class="token keyword">InnoDB</span> <span class="token keyword">DEFAULT</span> <span class="token keyword">CHARSET</span><span class="token operator">=</span>utf8mb4 <span class="token keyword">COLLATE</span><span class="token operator">=</span>utf8mb4_unicode_ci<span class="token punctuation">;</span>
3.2 Authoritative PHP Custom Auth Server (photon_auth.php)
<span class="token php language-php"><span class="token delimiter important"><?php</span>
<span class="token keyword">declare</span><span class="token punctuation">(</span>strict_types<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">/**
* Authoritative Photon Custom Authentication Endpoint
* Fully compliant with Exit Games Photon Cloud Authentication Protocol
* Hybrid GET / POST auto-detection with JSON ResultCode response
*/</span>
<span class="token comment">// 1. Set Strict JSON Headers & Security Directives</span>
<span class="token function">header</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Content-Type: application/json; charset=utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">header</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'X-Content-Type-Options: nosniff'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">header</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Cache-Control: no-store, no-cache, must-revalidate, max-age=0'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">header</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Pragma: no-cache'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 2. Photon ResultCode Constants</span>
<span class="token keyword">final</span> <span class="token keyword">class</span> <span class="token class-name-definition class-name">PhotonResultCode</span>
<span class="token punctuation">{</span>
<span class="token keyword">public</span> <span class="token keyword">const</span> <span class="token constant">ERROR_GENERIC</span> <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">const</span> <span class="token constant">SUCCESS</span> <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">const</span> <span class="token constant">ERROR_INVALID_PARAMS</span> <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">const</span> <span class="token constant">ERROR_USER_BANNED</span> <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 3. Safe JSON Response Helper</span>
<span class="token keyword">function</span> <span class="token function-definition function">emitPhotonResponse</span><span class="token punctuation">(</span><span class="token keyword type-hint">int</span> <span class="token variable">$resultCode</span><span class="token punctuation">,</span> <span class="token keyword type-hint">string</span> <span class="token variable">$message</span><span class="token punctuation">,</span> <span class="token operator">?</span><span class="token keyword type-hint">string</span> <span class="token variable">$userId</span> <span class="token operator">=</span> <span class="token constant">null</span><span class="token punctuation">,</span> <span class="token operator">?</span><span class="token keyword type-hint">string</span> <span class="token variable">$nickname</span> <span class="token operator">=</span> <span class="token constant">null</span><span class="token punctuation">,</span> <span class="token keyword type-hint">array</span> <span class="token variable">$data</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span>
<span class="token punctuation">{</span>
<span class="token variable">$response</span> <span class="token operator">=</span> <span class="token punctuation">[</span>
<span class="token string single-quoted-string">'ResultCode'</span> <span class="token operator">=></span> <span class="token variable">$resultCode</span><span class="token punctuation">,</span>
<span class="token string single-quoted-string">'Message'</span> <span class="token operator">=></span> <span class="token variable">$message</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$resultCode</span> <span class="token operator">===</span> <span class="token class-name static-context">PhotonResultCode</span><span class="token operator">::</span><span class="token constant">SUCCESS</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$userId</span> <span class="token operator">!==</span> <span class="token constant">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token variable">$response</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'UserId'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token variable">$userId</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$nickname</span> <span class="token operator">!==</span> <span class="token constant">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token variable">$response</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'Nickname'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token variable">$nickname</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">empty</span><span class="token punctuation">(</span><span class="token variable">$data</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token variable">$response</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'Data'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token variable">$data</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">echo</span> <span class="token function">json_encode</span><span class="token punctuation">(</span><span class="token variable">$response</span><span class="token punctuation">,</span> <span class="token class-name">JSON_UNESCAPED_SLASHES</span> <span class="token operator">|</span> <span class="token class-name">JSON_UNESCAPED_UNICODE</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">exit</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 4. Global Exception & Error Catching</span>
<span class="token function">set_exception_handler</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name class-name-fully-qualified type-declaration"><span class="token punctuation">\</span>Throwable</span> <span class="token variable">$e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">error_log</span><span class="token punctuation">(</span><span class="token string double-quoted-string">"[Photon Auth Error] "</span> <span class="token operator">.</span> <span class="token variable">$e</span><span class="token operator">-></span><span class="token function">getMessage</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">.</span> <span class="token string double-quoted-string">" in "</span> <span class="token operator">.</span> <span class="token variable">$e</span><span class="token operator">-></span><span class="token function">getFile</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">.</span> <span class="token string double-quoted-string">":"</span> <span class="token operator">.</span> <span class="token variable">$e</span><span class="token operator">-></span><span class="token function">getLine</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">emitPhotonResponse</span><span class="token punctuation">(</span><span class="token class-name static-context">PhotonResultCode</span><span class="token operator">::</span><span class="token constant">ERROR_GENERIC</span><span class="token punctuation">,</span> <span class="token string double-quoted-string">"An internal authentication server error occurred."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 5. Database Connection Factory (PDO with Prepared Statements)</span>
<span class="token keyword">function</span> <span class="token function-definition function">getDatabaseConnection</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token class-name return-type">PDO</span>
<span class="token punctuation">{</span>
<span class="token variable">$host</span> <span class="token operator">=</span> <span class="token function">getenv</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'DB_HOST'</span><span class="token punctuation">)</span> <span class="token operator">?</span><span class="token punctuation">:</span> <span class="token string single-quoted-string">'127.0.0.1'</span><span class="token punctuation">;</span>
<span class="token variable">$port</span> <span class="token operator">=</span> <span class="token function">getenv</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'DB_PORT'</span><span class="token punctuation">)</span> <span class="token operator">?</span><span class="token punctuation">:</span> <span class="token string single-quoted-string">'3306'</span><span class="token punctuation">;</span>
<span class="token variable">$db</span> <span class="token operator">=</span> <span class="token function">getenv</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'DB_NAME'</span><span class="token punctuation">)</span> <span class="token operator">?</span><span class="token punctuation">:</span> <span class="token string single-quoted-string">'unreliablecode_games'</span><span class="token punctuation">;</span>
<span class="token variable">$user</span> <span class="token operator">=</span> <span class="token function">getenv</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'DB_USER'</span><span class="token punctuation">)</span> <span class="token operator">?</span><span class="token punctuation">:</span> <span class="token string single-quoted-string">'root'</span><span class="token punctuation">;</span>
<span class="token variable">$pass</span> <span class="token operator">=</span> <span class="token function">getenv</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'DB_PASS'</span><span class="token punctuation">)</span> <span class="token operator">?</span><span class="token punctuation">:</span> <span class="token string single-quoted-string">'250304'</span><span class="token punctuation">;</span>
<span class="token variable">$charset</span> <span class="token operator">=</span> <span class="token string single-quoted-string">'utf8mb4'</span><span class="token punctuation">;</span>
<span class="token variable">$dsn</span> <span class="token operator">=</span> <span class="token string double-quoted-string">"mysql:host=<span class="token interpolation"><span class="token punctuation">{</span><span class="token variable">$host</span><span class="token punctuation">}</span></span>;port=<span class="token interpolation"><span class="token punctuation">{</span><span class="token variable">$port</span><span class="token punctuation">}</span></span>;dbname=<span class="token interpolation"><span class="token punctuation">{</span><span class="token variable">$db</span><span class="token punctuation">}</span></span>;charset=<span class="token interpolation"><span class="token punctuation">{</span><span class="token variable">$charset</span><span class="token punctuation">}</span></span>"</span><span class="token punctuation">;</span>
<span class="token variable">$options</span> <span class="token operator">=</span> <span class="token punctuation">[</span>
<span class="token class-name static-context">PDO</span><span class="token operator">::</span><span class="token constant">ATTR_ERRMODE</span> <span class="token operator">=></span> <span class="token class-name static-context">PDO</span><span class="token operator">::</span><span class="token constant">ERRMODE_EXCEPTION</span><span class="token punctuation">,</span>
<span class="token class-name static-context">PDO</span><span class="token operator">::</span><span class="token constant">ATTR_DEFAULT_FETCH_MODE</span> <span class="token operator">=></span> <span class="token class-name static-context">PDO</span><span class="token operator">::</span><span class="token constant">FETCH_ASSOC</span><span class="token punctuation">,</span>
<span class="token class-name static-context">PDO</span><span class="token operator">::</span><span class="token constant">ATTR_EMULATE_PREPARES</span> <span class="token operator">=></span> <span class="token constant boolean">false</span><span class="token punctuation">,</span> <span class="token comment">// Enforces true server-side binary prepared statements</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">PDO</span><span class="token punctuation">(</span><span class="token variable">$dsn</span><span class="token punctuation">,</span> <span class="token variable">$user</span><span class="token punctuation">,</span> <span class="token variable">$pass</span><span class="token punctuation">,</span> <span class="token variable">$options</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 6. Hybrid GET / POST Parameter Ingestion</span>
<span class="token keyword">function</span> <span class="token function-definition function">extractAuthenticationPayload</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">array</span>
<span class="token punctuation">{</span>
<span class="token variable">$payload</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// Ingest URL GET query parameters (Default Photon Cloud behavior)</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">empty</span><span class="token punctuation">(</span><span class="token variable">$_GET</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token variable">$_GET</span> <span class="token keyword">as</span> <span class="token variable">$k</span> <span class="token operator">=></span> <span class="token variable">$v</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token variable">$payload</span><span class="token punctuation">[</span><span class="token function">strtolower</span><span class="token punctuation">(</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword type-casting">string</span><span class="token punctuation">)</span><span class="token variable">$k</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">is_string</span><span class="token punctuation">(</span><span class="token variable">$v</span><span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token function">trim</span><span class="token punctuation">(</span><span class="token variable">$v</span><span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token variable">$v</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// Ingest Standard Form POST parameters</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">empty</span><span class="token punctuation">(</span><span class="token variable">$_POST</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token variable">$_POST</span> <span class="token keyword">as</span> <span class="token variable">$k</span> <span class="token operator">=></span> <span class="token variable">$v</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token variable">$payload</span><span class="token punctuation">[</span><span class="token function">strtolower</span><span class="token punctuation">(</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword type-casting">string</span><span class="token punctuation">)</span><span class="token variable">$k</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">is_string</span><span class="token punctuation">(</span><span class="token variable">$v</span><span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token function">trim</span><span class="token punctuation">(</span><span class="token variable">$v</span><span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token variable">$v</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// Ingest Raw JSON payload from Request Body</span>
<span class="token variable">$rawBody</span> <span class="token operator">=</span> <span class="token function">file_get_contents</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'php://input'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">empty</span><span class="token punctuation">(</span><span class="token variable">$rawBody</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token variable">$json</span> <span class="token operator">=</span> <span class="token function">json_decode</span><span class="token punctuation">(</span><span class="token variable">$rawBody</span><span class="token punctuation">,</span> <span class="token constant boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">is_array</span><span class="token punctuation">(</span><span class="token variable">$json</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token variable">$json</span> <span class="token keyword">as</span> <span class="token variable">$k</span> <span class="token operator">=></span> <span class="token variable">$v</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token variable">$payload</span><span class="token punctuation">[</span><span class="token function">strtolower</span><span class="token punctuation">(</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword type-casting">string</span><span class="token punctuation">)</span><span class="token variable">$k</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">is_string</span><span class="token punctuation">(</span><span class="token variable">$v</span><span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token function">trim</span><span class="token punctuation">(</span><span class="token variable">$v</span><span class="token punctuation">)</span> <span class="token punctuation">:</span> <span class="token variable">$v</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token variable">$payload</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// =========================================================================</span>
<span class="token comment">// MAIN AUTHENTICATION LOGIC</span>
<span class="token comment">// =========================================================================</span>
<span class="token variable">$params</span> <span class="token operator">=</span> <span class="token function">extractAuthenticationPayload</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Strategy A: Authenticate via Session Token / Ticket (Recommended for Production)</span>
<span class="token variable">$sessionToken</span> <span class="token operator">=</span> <span class="token variable">$params</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'token'</span><span class="token punctuation">]</span> <span class="token operator">??</span> <span class="token variable">$params</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'session_token'</span><span class="token punctuation">]</span> <span class="token operator">??</span> <span class="token variable">$params</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'ticket'</span><span class="token punctuation">]</span> <span class="token operator">??</span> <span class="token constant">null</span><span class="token punctuation">;</span>
<span class="token variable">$photonUid</span> <span class="token operator">=</span> <span class="token variable">$params</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'uid'</span><span class="token punctuation">]</span> <span class="token operator">??</span> <span class="token variable">$params</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'userid'</span><span class="token punctuation">]</span> <span class="token operator">??</span> <span class="token variable">$params</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'username'</span><span class="token punctuation">]</span> <span class="token operator">??</span> <span class="token constant">null</span><span class="token punctuation">;</span>
<span class="token comment">// Strategy B: Authenticate via Raw Username & Password (Direct Login)</span>
<span class="token variable">$rawUsername</span> <span class="token operator">=</span> <span class="token variable">$params</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'username'</span><span class="token punctuation">]</span> <span class="token operator">??</span> <span class="token variable">$params</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'user'</span><span class="token punctuation">]</span> <span class="token operator">??</span> <span class="token constant">null</span><span class="token punctuation">;</span>
<span class="token variable">$rawPassword</span> <span class="token operator">=</span> <span class="token variable">$params</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'password'</span><span class="token punctuation">]</span> <span class="token operator">??</span> <span class="token variable">$params</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'pass'</span><span class="token punctuation">]</span> <span class="token operator">??</span> <span class="token constant">null</span><span class="token punctuation">;</span>
<span class="token comment">// Validate that at least one authentication strategy has sufficient parameters</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">empty</span><span class="token punctuation">(</span><span class="token variable">$sessionToken</span><span class="token punctuation">)</span> <span class="token operator">&&</span> <span class="token punctuation">(</span><span class="token keyword">empty</span><span class="token punctuation">(</span><span class="token variable">$rawUsername</span><span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token keyword">empty</span><span class="token punctuation">(</span><span class="token variable">$rawPassword</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">emitPhotonResponse</span><span class="token punctuation">(</span>
<span class="token class-name static-context">PhotonResultCode</span><span class="token operator">::</span><span class="token constant">ERROR_INVALID_PARAMS</span><span class="token punctuation">,</span>
<span class="token string double-quoted-string">"Missing authentication parameters. Expected 'token' or 'username' + 'password'."</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token variable">$pdo</span> <span class="token operator">=</span> <span class="token function">getDatabaseConnection</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Execute Authentication Lookup</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">empty</span><span class="token punctuation">(</span><span class="token variable">$sessionToken</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// =============================================================</span>
<span class="token comment">// Token-Based Validation</span>
<span class="token comment">// =============================================================</span>
<span class="token variable">$stmt</span> <span class="token operator">=</span> <span class="token variable">$pdo</span><span class="token operator">-></span><span class="token function">prepare</span><span class="token punctuation">(</span><span class="token string double-quoted-string">"
SELECT user_id, photon_uid, username, mmr_rating, account_tier, is_banned, ban_reason, token_expires_at
FROM game_users
WHERE session_token = :token
LIMIT 1
"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token variable">$stmt</span><span class="token operator">-></span><span class="token function">execute</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'token'</span> <span class="token operator">=></span> <span class="token variable">$sessionToken</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token variable">$user</span> <span class="token operator">=</span> <span class="token variable">$stmt</span><span class="token operator">-></span><span class="token function">fetch</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token variable">$user</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">emitPhotonResponse</span><span class="token punctuation">(</span><span class="token class-name static-context">PhotonResultCode</span><span class="token operator">::</span><span class="token constant">ERROR_INVALID_PARAMS</span><span class="token punctuation">,</span> <span class="token string double-quoted-string">"Invalid or expired session token."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// Verify token expiration</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">empty</span><span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'token_expires_at'</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">&&</span> <span class="token function">strtotime</span><span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'token_expires_at'</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator"><</span> <span class="token function">time</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">emitPhotonResponse</span><span class="token punctuation">(</span><span class="token class-name static-context">PhotonResultCode</span><span class="token operator">::</span><span class="token constant">ERROR_INVALID_PARAMS</span><span class="token punctuation">,</span> <span class="token string double-quoted-string">"Authentication session has expired. Please log in again."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token comment">// =============================================================</span>
<span class="token comment">// Direct Username / Password Validation</span>
<span class="token comment">// =============================================================</span>
<span class="token variable">$stmt</span> <span class="token operator">=</span> <span class="token variable">$pdo</span><span class="token operator">-></span><span class="token function">prepare</span><span class="token punctuation">(</span><span class="token string double-quoted-string">"
SELECT user_id, photon_uid, username, password_hash, mmr_rating, account_tier, is_banned, ban_reason
FROM game_users
WHERE username = :username
LIMIT 1
"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token variable">$stmt</span><span class="token operator">-></span><span class="token function">execute</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'username'</span> <span class="token operator">=></span> <span class="token variable">$rawUsername</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token variable">$user</span> <span class="token operator">=</span> <span class="token variable">$stmt</span><span class="token operator">-></span><span class="token function">fetch</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token variable">$user</span> <span class="token operator">||</span> <span class="token operator">!</span><span class="token function">password_verify</span><span class="token punctuation">(</span><span class="token variable">$rawPassword</span><span class="token punctuation">,</span> <span class="token variable">$user</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'password_hash'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">emitPhotonResponse</span><span class="token punctuation">(</span><span class="token class-name static-context">PhotonResultCode</span><span class="token operator">::</span><span class="token constant">ERROR_INVALID_PARAMS</span><span class="token punctuation">,</span> <span class="token string double-quoted-string">"Invalid username or password."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// =============================================================</span>
<span class="token comment">// Check Account Ban Status</span>
<span class="token comment">// =============================================================</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword type-casting">int</span><span class="token punctuation">)</span><span class="token variable">$user</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'is_banned'</span><span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token variable">$banMsg</span> <span class="token operator">=</span> <span class="token operator">!</span><span class="token keyword">empty</span><span class="token punctuation">(</span><span class="token variable">$user</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'ban_reason'</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token operator">?</span> <span class="token string double-quoted-string">"Account suspended: "</span> <span class="token operator">.</span> <span class="token variable">$user</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'ban_reason'</span><span class="token punctuation">]</span>
<span class="token punctuation">:</span> <span class="token string double-quoted-string">"Account suspended due to policy violation."</span><span class="token punctuation">;</span>
<span class="token function">emitPhotonResponse</span><span class="token punctuation">(</span><span class="token class-name static-context">PhotonResultCode</span><span class="token operator">::</span><span class="token constant">ERROR_USER_BANNED</span><span class="token punctuation">,</span> <span class="token variable">$banMsg</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// =============================================================</span>
<span class="token comment">// Construct Custom Client Data Payload</span>
<span class="token comment">// =============================================================</span>
<span class="token variable">$customClientData</span> <span class="token operator">=</span> <span class="token punctuation">[</span>
<span class="token string single-quoted-string">'mmr'</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token keyword type-casting">int</span><span class="token punctuation">)</span><span class="token variable">$user</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'mmr_rating'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token string single-quoted-string">'tier'</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token keyword type-casting">string</span><span class="token punctuation">)</span><span class="token variable">$user</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'account_tier'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token string single-quoted-string">'auth_time'</span> <span class="token operator">=></span> <span class="token function">time</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token string single-quoted-string">'session_auth'</span> <span class="token operator">=></span> <span class="token function">hash_hmac</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'sha256'</span><span class="token punctuation">,</span> <span class="token variable">$user</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'photon_uid'</span><span class="token punctuation">]</span> <span class="token operator">.</span> <span class="token string single-quoted-string">'|'</span> <span class="token operator">.</span> <span class="token function">time</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string single-quoted-string">'GAME_SERVER_SHARED_SECRET_KEY'</span><span class="token punctuation">)</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// =============================================================</span>
<span class="token comment">// Emit Successful Handshake</span>
<span class="token comment">// =============================================================</span>
<span class="token function">emitPhotonResponse</span><span class="token punctuation">(</span>
<span class="token class-name static-context">PhotonResultCode</span><span class="token operator">::</span><span class="token constant">SUCCESS</span><span class="token punctuation">,</span>
<span class="token string double-quoted-string">"Authentication successful."</span><span class="token punctuation">,</span>
<span class="token punctuation">(</span><span class="token keyword type-casting">string</span><span class="token punctuation">)</span><span class="token variable">$user</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'photon_uid'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">(</span><span class="token keyword type-casting">string</span><span class="token punctuation">)</span><span class="token variable">$user</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'username'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token variable">$customClientData</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></span>
Module 4: Unity C# Client Implementation (PUN2 & Photon Realtime)
Let us now engineer the Unity C# client component that initiates the connection, supplies the parameters, and processes the server response.
4.1 Creating the Custom Authentication Manager (PhotonCustomAuthClient.cs)
<span class="token keyword">using</span> <span class="token namespace">System</span><span class="token punctuation">;</span>
<span class="token keyword">using</span> <span class="token namespace">System<span class="token punctuation">.</span>Collections<span class="token punctuation">.</span>Generic</span><span class="token punctuation">;</span>
<span class="token keyword">using</span> <span class="token namespace">UnityEngine</span><span class="token punctuation">;</span>
<span class="token keyword">using</span> <span class="token namespace">Photon<span class="token punctuation">.</span>Pun</span><span class="token punctuation">;</span>
<span class="token keyword">using</span> <span class="token namespace">Photon<span class="token punctuation">.</span>Realtime</span><span class="token punctuation">;</span>
<span class="token keyword">namespace</span> <span class="token namespace">UnreliableCode<span class="token punctuation">.</span>Networking</span>
<span class="token punctuation">{</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">PhotonCustomAuthClient</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">MonoBehaviourPunCallbacks</span></span>
<span class="token punctuation">{</span>
<span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Header</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token string">"Photon Custom Authentication Settings"</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span>
<span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Tooltip</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token string">"The session token obtained from your login Web API"</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span>
<span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">SerializeField</span></span><span class="token punctuation">]</span> <span class="token keyword">private</span> <span class="token class-name"><span class="token keyword">string</span></span> sessionToken <span class="token operator">=</span> <span class="token string">"demo_token_88921"</span><span class="token punctuation">;</span>
<span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">SerializeField</span></span><span class="token punctuation">]</span> <span class="token keyword">private</span> <span class="token class-name"><span class="token keyword">string</span></span> playerUsername <span class="token operator">=</span> <span class="token string">"Player_Alex"</span><span class="token punctuation">;</span>
<span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">Header</span><span class="token attribute-arguments"><span class="token punctuation">(</span><span class="token string">"Connection Status"</span><span class="token punctuation">)</span></span></span><span class="token punctuation">]</span>
<span class="token punctuation">[</span><span class="token attribute"><span class="token class-name">SerializeField</span></span><span class="token punctuation">]</span> <span class="token keyword">private</span> <span class="token class-name"><span class="token keyword">bool</span></span> autoConnectOnStart <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token keyword">private</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>autoConnectOnStart<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token function">ConnectWithCustomAuth</span><span class="token punctuation">(</span>playerUsername<span class="token punctuation">,</span> sessionToken<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">/// <summary></span>
<span class="token comment">/// Initiates connection to Photon Cloud using custom PHP authentication</span>
<span class="token comment">/// </summary></span>
<span class="token keyword">public</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">ConnectWithCustomAuth</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> username<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> token<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
Debug<span class="token punctuation">.</span><span class="token function">Log</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$"[PhotonAuth] Initiating custom authentication for user: </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">username</span><span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 1. Instantiate AuthenticationValues with Custom Type</span>
<span class="token class-name">AuthenticationValues</span> authValues <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">AuthenticationValues</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
authValues<span class="token punctuation">.</span>AuthType <span class="token operator">=</span> CustomAuthenticationType<span class="token punctuation">.</span>Custom<span class="token punctuation">;</span>
<span class="token comment">// 2. Set Auth Parameters (These are passed to your PHP endpoint)</span>
<span class="token comment">// Photon formats these as query string parameters by default: "?username=...&token=..."</span>
authValues<span class="token punctuation">.</span><span class="token function">SetAuthParameters</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$"username=</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">Uri<span class="token punctuation">.</span><span class="token function">EscapeDataString</span><span class="token punctuation">(</span>username<span class="token punctuation">)</span></span><span class="token punctuation">}</span></span><span class="token string">&token=</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">Uri<span class="token punctuation">.</span><span class="token function">EscapeDataString</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span></span><span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 3. Assign to PhotonNetwork and Connect</span>
PhotonNetwork<span class="token punctuation">.</span>AuthValues <span class="token operator">=</span> authValues<span class="token punctuation">;</span>
PhotonNetwork<span class="token punctuation">.</span>AutomaticallySyncScene <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token comment">// Connect using photon project settings</span>
PhotonNetwork<span class="token punctuation">.</span><span class="token function">ConnectUsingSettings</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// =========================================================================</span>
<span class="token comment">// PHOTON CALLBACK HANDLERS</span>
<span class="token comment">// =========================================================================</span>
<span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">OnConnectedToMaster</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
Debug<span class="token punctuation">.</span><span class="token function">Log</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$"<color=green>[PhotonAuth] Successfully Connected to Master Server!</color>"</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Debug<span class="token punctuation">.</span><span class="token function">Log</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$"Authoritative UserId bound by PHP: </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">PhotonNetwork<span class="token punctuation">.</span>LocalPlayer<span class="token punctuation">.</span>UserId</span><span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Debug<span class="token punctuation">.</span><span class="token function">Log</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$"Synchronized Nickname: </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">PhotonNetwork<span class="token punctuation">.</span>NickName</span><span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">OnCustomAuthenticationResponse</span><span class="token punctuation">(</span><span class="token class-name">Dictionary<span class="token punctuation"><</span><span class="token keyword">string</span><span class="token punctuation">,</span> <span class="token keyword">object</span><span class="token punctuation">></span></span> data<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
Debug<span class="token punctuation">.</span><span class="token function">Log</span><span class="token punctuation">(</span><span class="token string">"<color=cyan>[PhotonAuth] Custom Authentication Server Data Received!</color>"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>data <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">||</span> data<span class="token punctuation">.</span>Count <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
Debug<span class="token punctuation">.</span><span class="token function">Log</span><span class="token punctuation">(</span><span class="token string">"[PhotonAuth] No custom data payload returned in response."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token class-name">KeyValuePair<span class="token punctuation"><</span><span class="token keyword">string</span><span class="token punctuation">,</span> <span class="token keyword">object</span><span class="token punctuation">></span></span> pair <span class="token keyword">in</span> data<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
Debug<span class="token punctuation">.</span><span class="token function">Log</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$" -> Key: </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">pair<span class="token punctuation">.</span>Key</span><span class="token punctuation">}</span></span><span class="token string"> | Value: </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">pair<span class="token punctuation">.</span>Value</span><span class="token punctuation">}</span></span><span class="token string"> (Type: </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">pair<span class="token punctuation">.</span>Value<span class="token punctuation">?.</span><span class="token function">GetType</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>Name</span><span class="token punctuation">}</span></span><span class="token string">)"</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// Extract custom MMR and Account Tier</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>data<span class="token punctuation">.</span><span class="token function">TryGetValue</span><span class="token punctuation">(</span><span class="token string">"mmr"</span><span class="token punctuation">,</span> <span class="token keyword">out</span> <span class="token class-name"><span class="token keyword">object</span></span> mmrObj<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token class-name"><span class="token keyword">int</span></span> playerMMR <span class="token operator">=</span> Convert<span class="token punctuation">.</span><span class="token function">ToInt32</span><span class="token punctuation">(</span>mmrObj<span class="token punctuation">)</span><span class="token punctuation">;</span>
Debug<span class="token punctuation">.</span><span class="token function">Log</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$"[PhotonAuth] Authoritative MMR Loaded: </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">playerMMR</span><span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>data<span class="token punctuation">.</span><span class="token function">TryGetValue</span><span class="token punctuation">(</span><span class="token string">"tier"</span><span class="token punctuation">,</span> <span class="token keyword">out</span> <span class="token class-name"><span class="token keyword">object</span></span> tierObj<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token class-name"><span class="token keyword">string</span></span> tier <span class="token operator">=</span> tierObj<span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Debug<span class="token punctuation">.</span><span class="token function">Log</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$"[PhotonAuth] Account Tier Loaded: </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">tier</span><span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">OnCustomAuthenticationFailed</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> debugMessage<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
Debug<span class="token punctuation">.</span><span class="token function">LogError</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$"<color=red>[PhotonAuth] Custom Authentication Failed!</color>"</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Debug<span class="token punctuation">.</span><span class="token function">LogError</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$"Server Rejection Reason: </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">debugMessage</span><span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Handle UI error display or return user to login screen</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">override</span> <span class="token return-type class-name"><span class="token keyword">void</span></span> <span class="token function">OnDisconnected</span><span class="token punctuation">(</span><span class="token class-name">DisconnectCause</span> cause<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
Debug<span class="token punctuation">.</span><span class="token function">LogWarning</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$"[PhotonAuth] Disconnected from Photon Cloud: </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">cause</span><span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
Module 5: Photon Fusion 2.0 Integration Nuances
In Photon Fusion, custom authentication is supplied via AuthenticationValues inside the StartGameArgs struct when starting the network runner:
<span class="token keyword">using</span> <span class="token namespace">System</span><span class="token punctuation">;</span>
<span class="token keyword">using</span> <span class="token namespace">System<span class="token punctuation">.</span>Threading<span class="token punctuation">.</span>Tasks</span><span class="token punctuation">;</span>
<span class="token keyword">using</span> <span class="token namespace">UnityEngine</span><span class="token punctuation">;</span>
<span class="token keyword">using</span> <span class="token namespace">Fusion</span><span class="token punctuation">;</span>
<span class="token keyword">using</span> <span class="token namespace">Photon<span class="token punctuation">.</span>Realtime</span><span class="token punctuation">;</span>
<span class="token keyword">namespace</span> <span class="token namespace">UnreliableCode<span class="token punctuation">.</span>FusionAuth</span>
<span class="token punctuation">{</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">FusionCustomAuthLauncher</span> <span class="token punctuation">:</span> <span class="token type-list"><span class="token class-name">MonoBehaviour</span></span>
<span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token class-name">NetworkRunner</span> runner<span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">async</span> <span class="token return-type class-name">Task</span> <span class="token function">StartFusionSession</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword">string</span></span> username<span class="token punctuation">,</span> <span class="token class-name"><span class="token keyword">string</span></span> sessionToken<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>runner <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
runner <span class="token operator">=</span> gameObject<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">AddComponent</span><span class="token generic class-name"><span class="token punctuation"><</span>NetworkRunner<span class="token punctuation">></span></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// Configure Custom Authentication Values</span>
<span class="token class-name">AuthenticationValues</span> customAuth <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token constructor-invocation class-name">AuthenticationValues</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
customAuth<span class="token punctuation">.</span>AuthType <span class="token operator">=</span> CustomAuthenticationType<span class="token punctuation">.</span>Custom<span class="token punctuation">;</span>
customAuth<span class="token punctuation">.</span><span class="token function">SetAuthParameters</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$"username=</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">Uri<span class="token punctuation">.</span><span class="token function">EscapeDataString</span><span class="token punctuation">(</span>username<span class="token punctuation">)</span></span><span class="token punctuation">}</span></span><span class="token string">&token=</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">Uri<span class="token punctuation">.</span><span class="token function">EscapeDataString</span><span class="token punctuation">(</span>sessionToken<span class="token punctuation">)</span></span><span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Launch Fusion Session</span>
<span class="token class-name">StartGameResult</span> result <span class="token operator">=</span> <span class="token keyword">await</span> runner<span class="token punctuation">.</span><span class="token function">StartGame</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token constructor-invocation class-name">StartGameArgs</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
GameMode <span class="token operator">=</span> GameMode<span class="token punctuation">.</span>AutoHostOrClient<span class="token punctuation">,</span>
SessionName <span class="token operator">=</span> <span class="token string">"CompetitiveRoom_EU1"</span><span class="token punctuation">,</span>
AuthValues <span class="token operator">=</span> customAuth
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>result<span class="token punctuation">.</span>Ok<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
Debug<span class="token punctuation">.</span><span class="token function">Log</span><span class="token punctuation">(</span><span class="token string">"[Fusion] Successfully authenticated and joined Fusion room!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">else</span>
<span class="token punctuation">{</span>
Debug<span class="token punctuation">.</span><span class="token function">LogError</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$"[Fusion] StartGame failed: </span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">result<span class="token punctuation">.</span>ShutdownReason</span><span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
Module 6: Configuring the Photon Cloud Dashboard
To activate your PHP authentication script in Photon Cloud:
- Navigate to the Photon Engine Management Dashboard (
https://dashboard.photonengine.com).
- Select your application and click Manage.
- Scroll down to the Custom Authentication section and click Add Provider.
- Configure the provider settings:
- Authentication Type:
Custom
- Authentication URL:
https://api.yourdomain.com/photon_auth.php
- Key / Value Parameters (Optional): Leave empty if parameters are provided dynamically by the Unity client, or define static secret keys (e.g.,
secret=SERVER_API_TOKEN).
- Reject non-authenticated clients: Check Enable (Crucial: prevents unauthenticated clients from connecting).
- Click Save Changes.
Module 7: Production Security Hardening & Diagnostic Testing
7.1 Testing the PHP Gateway with cURL
Before testing in Unity, verify that your PHP script handles both GET and POST requests accurately:
Test 1: Testing Default Photon GET Request
<span class="token function">curl</span> <span class="token parameter variable">-i</span> <span class="token string">"http://localhost/photon_auth.php?username=Alex&token=demo_token_88921"</span>
Expected Output:
HTTP/<span class="token number">1.1</span> <span class="token number">200</span> OK
Content-Type<span class="token operator">:</span> application/json; charset=utf<span class="token number">-8</span>
X-Content-Type-Options<span class="token operator">:</span> nosniff
<span class="token punctuation">{</span>
<span class="token property">"ResultCode"</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
<span class="token property">"Message"</span><span class="token operator">:</span> <span class="token string">"Authentication successful."</span><span class="token punctuation">,</span>
<span class="token property">"UserId"</span><span class="token operator">:</span> <span class="token string">"usr_99182"</span><span class="token punctuation">,</span>
<span class="token property">"Nickname"</span><span class="token operator">:</span> <span class="token string">"Alex"</span><span class="token punctuation">,</span>
<span class="token property">"Data"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"mmr"</span><span class="token operator">:</span> <span class="token number">1000</span><span class="token punctuation">,</span>
<span class="token property">"tier"</span><span class="token operator">:</span> <span class="token string">"Standard"</span><span class="token punctuation">,</span>
<span class="token property">"auth_time"</span><span class="token operator">:</span> <span class="token number">1788026700</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
Test 2: Testing POST Request with JSON Body
<span class="token function">curl</span> <span class="token parameter variable">-i</span> <span class="token parameter variable">-X</span> POST <span class="token string">"http://localhost/photon_auth.php"</span> <span class="token punctuation">\</span>
<span class="token parameter variable">-H</span> <span class="token string">"Content-Type: application/json"</span> <span class="token punctuation">\</span>
<span class="token parameter variable">-d</span> <span class="token string">'{"username": "Alex", "token": "demo_token_88921"}'</span>
Test 3: Testing Banned / Invalid User Rejection
<span class="token function">curl</span> <span class="token parameter variable">-i</span> <span class="token string">"http://localhost/photon_auth.php?username=UnknownPlayer&token=invalid_token_999"</span>
Expected Output:
HTTP/<span class="token number">1.1</span> <span class="token number">200</span> OK
Content-Type<span class="token operator">:</span> application/json; charset=utf<span class="token number">-8</span>
<span class="token punctuation">{</span>
<span class="token property">"ResultCode"</span><span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">,</span>
<span class="token property">"Message"</span><span class="token operator">:</span> <span class="token string">"Invalid or expired session token."</span>
<span class="token punctuation">}</span>
Module 8: Troubleshooting & Photon ResultCode Matrix
| ResultCode |
Name |
Photon Cloud Action |
Common Root Cause & Solution |
1 |
SUCCESS |
Connects client to Master Server; binds UserId and delivers Data. |
Everything operating normally. |
2 |
INVALID_PARAMS |
Immediately disconnects client; fires OnCustomAuthenticationFailed. |
Missing parameter, expired session token, or invalid password. |
3 |
USER_BANNED |
Immediately disconnects client; fires OnCustomAuthenticationFailed. |
Player has active moderation ban record in database. |
0 |
ERROR_GENERIC |
Disconnects client with error message. |
PHP runtime fatal exception, unhandled PDO error, or database timeout. |
| HTTP 404 / 500 |
HTTP Failure |
Disconnects client with internal error. |
Photon could not reach endpoint URL; verify SSL certificate and routing. |
Conclusion & Architecture Summary
Implementing a robust Photon Custom Authentication gateway in PHP provides authoritative control over who enters your multiplayer matchmaking ecosystem. By implementing hybrid auto-detection, your PHP endpoint gracefully handles Photon's default URL GET query parameters while remaining fully compatible with modern JSON POST payloads.
Coupled with strict PDO prepared statements, token expiration verification, and the OnCustomAuthenticationResponse callback in Unity, you establish an enterprise-grade multiplayer security architecture for your game.
Happy game development, and build authoritatively!
Authored by the UnreliableCode Security & Multiplayer Engineering Team for unreliablecode.net