Authentication Guide
ElysIdentity supports three authentication flows, all handled automatically by the component-subsystem pair.
Flow 1: Silent Token Authentication
The most common flow for returning players. Happens automatically on BeginPlay:
UERPIdentityComponentreadssession.tokfrom local storage- Sends token to server via
Server_Authenticate(RawToken) - Server validates HMAC signature and expiry
- Server issues a fresh token (resets expiry window)
- Client stores the refreshed token
No player interaction required.
Flow 2: Login / Register
Triggered when no valid token exists:
- Server calls
Client_RequestLogin(bSessionExpired) - UI shows login/register form (your responsibility)
- Player submits credentials
Server_Login(AccountName, PIN)orServer_Register(AccountName, PIN)- Server validates, issues token on success
PIN Validation Rules
- Length: 4-8 digits
- Characters: Numeric only (0-9)
Account Name Validation Rules
- Length: 1-64 characters
- Characters: A-Z, a-z, 0-9, underscore, hyphen
- Uniqueness: Case-insensitive
Flow 3: PIN Recovery
For forgotten PINs:
Server_RequestRecovery(AccountName)- Server generates 6-character alphanumeric code (uppercase)
- Server fires
OnRecoveryCodeGenerated(AccountName, Code, ExternalIDs)on the subsystem - You deliver the code out-of-band (Discord DM, webhook, admin log, etc.)
- Player enters code + new PIN
Server_RedeemRecovery(AccountName, Code, NewPIN)
tip
Bind to UERPIdentitySubsystem::OnRecoveryCodeGenerated to implement your delivery mechanism. The delegate provides the player's ExternalIDs map for Discord/Steam DM routing.
PIN Lockout
After MaxPINAttempts (default 5) failed attempts, the account is locked for PINLockoutSeconds (default 300s):
- Lockout is per-account, not per-IP
- Lockout state is server-side only (survives reconnects within the window)
- Lockout is not persisted (resets on server restart)
- Successful login resets the counter
External Platform Linking
Link external platform IDs (Steam, Epic, Discord) to a player GUID:
UERPIdentitySubsystem* Identity = GetGameInstance()->GetSubsystem<UERPIdentitySubsystem>();
// Link Steam ID
Identity->LinkExternalID(PlayerGUID, TEXT("Steam"), TEXT("76561198..."));
// Find player by Steam ID
FERPPlayerIdentity* Found = Identity->FindIdentityByExternalID(TEXT("Steam"), TEXT("76561198..."));
// Unlink
Identity->UnlinkExternalID(PlayerGUID, TEXT("Steam"));
Security Model
| Aspect | Implementation |
|---|---|
| PIN storage | Salted SHA-256 (16-char hex salt per account) |
| Session tokens | HMAC-SHA256 signed, wire format: GUID|ExpiresAt|HMAC |
| Token storage | Local session.tok file (tamper-proof via HMAC) |
| Lockout | Server-side per-account tracking |
| PINs on wire | Sent via UE RPCs (encrypted in transit if UE encryption enabled) |