Authentication
User Ids and Player Names
The UserId uniquely identifies a player account across sessions and devices.
It drives everything identity-based in the SDK: matchmaking slot reservations, friend queries, rejoining a room after a disconnect and the PublishUserId room option.
If you do not supply one, the server assigns a random UserId at connect, fine for testing, but stable ids are a prerequisite for friends and rejoin.
The player name is a display name, set through ConnectOptions.Username at connect or SetPlayerName() at any time.
It is visible to other players in the room and entirely independent of the UserId.
Authentication Values
AuthenticationValues travels in ConnectOptions.Auth and carries everything the server needs to authenticate the client: the UserId, the provider Type, a provider-specific Parameters string and an optional Data payload.
| Field | Type | Description |
|---|---|---|
UserId |
StringType |
Unique id of the player. Assigned randomly by the server when left empty. |
Type |
CustomAuthenticationType |
The authentication provider. None (default) skips provider authentication. |
Parameters |
StringType |
Provider-specific parameters, typically formatted as a query string. |
Data |
std::variant |
Optional payload: empty, raw bytes (std::vector<uint8_t>), a string or a RealtimeMap. |
Without a provider, setting a UserId is all it takes:
C++
Task<Result<void>> ConnectAsPlayer(RealtimeClient& client)
{
ConnectOptions options;
options.Auth.UserId = PHOTON_STR("player-1234"); // Type stays CustomAuthenticationType::None.
co_return co_await client.Connect(options);
}
Authentication Providers
CustomAuthenticationType selects the provider the server validates the login against: Custom, Steam, Facebook, Oculus, PlayStation4, PlayStation5, Xbox, Viveport, NintendoSwitch, Epic and FacebookGaming.
The default None skips provider authentication entirely.
Providers are configured per application in the Photon dashboard, so the client never holds provider secrets.
At connect time the client only supplies the provider-specific Parameters and Data the configured provider expects, such as a session ticket.
For Steam, pass the hex-encoded session ticket in Parameters:
C++
Task<Result<void>> ConnectWithSteam(RealtimeClient& client, RealtimeCore::Common::StringType sessionTicket)
{
ConnectOptions options;
options.Auth.Type = CustomAuthenticationType::Steam;
options.Auth.Parameters = PHOTON_STR("ticket=") + sessionTicket;
co_return co_await client.Connect(options);
}
Custom Authentication
Type = CustomAuthenticationType::Custom authenticates against your own web service.
Register the service's URL in the dashboard; on every connect the Photon server forwards the client's parameters to it and lets it accept or reject the login.
The Data payload is a std::variant holding either nothing, raw bytes, a string or a RealtimeMap.
A RealtimeMap payload travels as a string-keyed dictionary, so entries with a numeric key are skipped.
Pick whichever shape your authentication service expects: Parameters suits short key-value pairs, Data suits structured or binary content.
This example combines a query-style parameter string with a binary payload:
C++
Task<Result<void>> ConnectWithCustomAuth(RealtimeClient& client)
{
ConnectOptions options;
options.Auth.UserId = PHOTON_STR("player-1234");
options.Auth.Type = CustomAuthenticationType::Custom;
options.Auth.Parameters = PHOTON_STR("token=abc123&build=42");
options.Auth.Data = std::vector<uint8_t>{0x02, 0x48, 0x69};
co_return co_await client.Connect(options);
}
Multi-Step Authentication
Some providers need a challenge/response round before the login completes.
Subscribe to OnCustomAuthStep to receive the server's parameters for the next step and answer with SendCustomAuthData(AuthenticationValues).
Answer each step from the callback:
C++
auto subscription = client.OnCustomAuthStep.Subscribe(
[&client](const std::unordered_map<RealtimeCore::Common::StringType, RealtimeCore::Common::StringType>& serverParameters) {
const auto challenge = serverParameters.find(PHOTON_STR("challenge"));
if (challenge == serverParameters.end())
{
return;
}
AuthenticationValues answer;
answer.Type = CustomAuthenticationType::Custom;
answer.Parameters = PHOTON_STR("response=") + challenge->second;
client.SendCustomAuthData(answer);
});
Back to top