Authentication
The MCE Online layer supports multiple authentication methods through Nakama. All authentication flows are managed by AuthService (in Auth/AuthService.cs) and SessionManager, both initialized automatically by NakamaManager at startup.
Connection States
The ConnectionState enum tracks the full lifecycle of the online connection:
| State | Description |
|---|---|
Disconnected | Not connected and not attempting to connect |
Connecting | Currently attempting to establish connection |
Connected | Successfully connected and authenticated |
Reconnecting | Connection lost, attempting automatic reconnect |
Offline | Running in offline mode (server unavailable or disabled) |
Failed | Connection failed after all retry attempts |
You can subscribe to state changes via NakamaManager.Instance.OnStateChanged.
NakamaManager.Instance.OnStateChanged += (state) =>
{
Debug.Log($"Connection state: {state}");
};
Convenience properties are available on NakamaManager:
IsConnected-- returnstrueonly when state isConnected.IsOffline-- returnstruewhen state isOfflineorDisconnected.
Authentication Methods
MCE supports the following AuthMethod values: Email, DeviceId, Discord, Google, Apple, Facebook, and Custom.
Device Authentication (Auto-Login)
The simplest method. Uses SystemInfo.deviceUniqueIdentifier to create an anonymous account automatically. Ideal for mobile and first-time play.
bool success = await NakamaManager.Instance.ConnectWithDeviceAsync();
Under the hood, AuthService.AuthenticateDeviceAsync() calls Client.AuthenticateDeviceAsync(deviceId, create: true), which creates a new Nakama account on first use and logs into it on subsequent calls. The device ID is truncated in logs for privacy.
Email / Password Authentication
Supports both registration (create: true) and login (create: false).
// Register a new account
bool registered = await NakamaManager.Instance.ConnectWithEmailAsync(
"player@example.com", "securepassword", createAccount: true);
// Login to existing account
bool loggedIn = await NakamaManager.Instance.ConnectWithEmailAsync(
"player@example.com", "securepassword", createAccount: false);
You can also use the lower-level AuthService directly:
OnlineSession session = await NakamaManager.Instance.Auth.AuthenticateEmailAsync(
email, password, create: true);
The returned OnlineSession wraps Nakama's ISession and exposes: UserId, DisplayName, Token, RefreshToken, and ExpiresAt.
SSO Authentication (Discord, Google, Apple)
SSO providers are enabled per-provider in OnlineConfig:
EnableDiscordSSO(default:true)EnableGoogleSSO(default:true)EnableAppleSSO(default:true)
OAuth client IDs are also configured in OnlineConfig (DiscordClientId, GoogleClientId).
// Google
bool success = await NakamaManager.Instance.ConnectWithSSOAsync(
AuthMethod.Google, googleIdToken);
// Apple
bool success = await NakamaManager.Instance.ConnectWithSSOAsync(
AuthMethod.Apple, appleIdentityToken);
// Discord (uses custom auth flow with Discord user ID)
bool success = await NakamaManager.Instance.ConnectWithSSOAsync(
AuthMethod.Discord, discordUserId);
Google and Apple use Nakama's built-in AuthenticateGoogleAsync / AuthenticateAppleAsync. Discord and Facebook route through AuthenticateCustomAsync since Nakama does not have a native Discord auth provider.
Account Linking
Players can link multiple authentication methods to a single account. This lets them start with device auth and later add email or SSO for cross-device access.
bool linked = await NakamaManager.Instance.Auth.LinkAccountAsync(
AuthMethod.Google, googleToken);
bool linked = await NakamaManager.Instance.Auth.LinkAccountAsync(
AuthMethod.Discord, discordToken);
LinkAccountAsync uses Client.LinkGoogleAsync, Client.LinkAppleAsync, or Client.LinkCustomAsync depending on the method.
Session Persistence
SessionManager handles saving and restoring authentication tokens using PlayerPrefs:
- Token key:
mce_nakama_token - Refresh token key:
mce_nakama_refresh
On successful authentication, SaveNakamaSession(session) persists both tokens. On app restart, LoadNakamaSession(client) restores the session via Nakama.Session.Restore(token, refresh). If the restored session is expired, it is cleared automatically.
// Check if a valid session exists
bool hasSession = NakamaManager.Instance.SessionMgr.HasValidSession();
// Manually clear session (logout)
NakamaManager.Instance.SessionMgr.ClearSession();
Post-Authentication Flow
After any successful authentication, NakamaManager.FinalizeConnection() performs the following sequence:
- Stores
Session,UserId,DisplayName, andSessionToken. - Saves the session via
SessionManager. - Creates a WebSocket via
Client.NewSocket(useMainThread: true). - Hooks socket events:
Closed,ReceivedError,ReceivedMatchState,ReceivedChannelMessage,ReceivedNotification,ReceivedMatchmakerMatched,ReceivedStatusPresence. - Connects the socket with
Socket.ConnectAsync(session). - Initializes online services asynchronously:
WorldSync.InitializeAsync()-- joins the world match.Chat.JoinGlobalChannelAsync()-- joins the global chat room.Friends.RefreshFriendsListAsync()-- loads friends and follows their status.Housing.InitializeAsync()-- ifEnableHousingis on.Mods.LoadInstalledModsAsync()-- ifEnableModSupportis on.
- Fires
OnConnectedand registers theOnlineCommandBridge.
Auto-Reconnect
When the socket closes unexpectedly and OnlineConfig.AutoReconnect is true, NakamaManager automatically attempts to reconnect using exponential backoff:
- Delay formula:
min(2 * 2^(attempt-1), 30)seconds. - Maximum attempts:
OnlineConfig.MaxReconnectAttempts(default: 5). - Reconnect restores from the saved session. If the session is expired, it falls back to offline mode.
The state transitions to Reconnecting during attempts.
Offline Fallback
When OnlineConfig.AllowOfflineFallback is true (the default), any connection failure gracefully falls back to ConnectionState.Offline. The entire game continues to work locally -- the online layer is fully optional.
Display Name
After authentication, you can update the player's display name:
bool updated = await NakamaManager.Instance.Auth.UpdateDisplayNameAsync("NewName");
Error Handling
Authentication errors are surfaced through the NakamaManager.OnConnectionError event:
NakamaManager.Instance.OnConnectionError += (errorMessage) =>
{
Debug.LogError($"Connection error: {errorMessage}");
// Show error dialog to the player
};
All auth methods catch exceptions internally and log them with the [MCE Online] or [Auth] prefix.
Configuration Reference
Key settings in OnlineConfig (ScriptableObject at Resources/OnlineConfig):
| Field | Default | Description |
|---|---|---|
ServerHost | 127.0.0.1 | Nakama server hostname |
ServerPort | 7350 | Nakama server port |
ServerKey | defaultkey | Nakama server key |
UseSSL | false | Use HTTPS/WSS |
ConnectionTimeout | 10 | Timeout in seconds |
AutoReconnect | true | Auto-reconnect on disconnect |
MaxReconnectAttempts | 5 | Max retry count |
AllowOfflineFallback | true | Fall back to offline mode on failure |
EnableDiscordSSO | true | Enable Discord auth |
EnableGoogleSSO | true | Enable Google auth |
EnableAppleSSO | true | Enable Apple auth |
Security Best Practices
- Never expose
ServerKeyin builds intended for distribution. Use Nakama's environment-specific keys. - Prefer SSO or email auth for production. Device auth is convenient for development and mobile quick-start but cannot be recovered if the device is wiped.
- Enable
EnableServerAuthorityinOnlineConfigfor production. This routes all state-changing operations (items, money, teleport) through server validation via theOnlineCommandBridge. - Session tokens are stored in
PlayerPrefs. On platforms wherePlayerPrefsis not secure (e.g., PC), consider encrypting the token at rest.