User Manager - ArtyProf/steamworks-ffi-node GitHub Wiki
Complete reference for Steam User functionality in Steamworks FFI.
The SteamUserManager provides 100% coverage of the ISteamUser interface with 28 functions for authentication, session tickets, license verification, voice recording, and user information.
| Category | Functions | Description |
|---|---|---|
| Login State | 1 | Check Steam login status |
| Session Tickets | 3 | P2P/game server authentication tickets |
| Auth Sessions | 2 | Validate incoming auth tickets |
| License Verification | 1 | Check app/DLC ownership |
| Encrypted Tickets | 2 | Secure backend authentication |
| Security Info | 2 | User security settings and NAT status |
| User Info | 3 | Steam level, badges, data folder |
| Market Eligibility | 1 | Steam Market access status |
| Store Auth URL | 1 | In-game browser authentication |
| Duration Control | 2 | Anti-indulgence compliance (China) |
| Game Advertising | 1 | Advertise game server to friends |
| Voice Recording | 6 | Record and transmit voice chat |
| Cleanup | 1 | Cancel all active tickets |
Check if the user is logged into Steam.
Check if the user is logged into Steam.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_BLoggedOn()- Check login status
Returns: boolean - true if user is logged in
Example:
import SteamworksSDK from 'steamworks-ffi-node';
const steam = SteamworksSDK.getInstance();
if (steam.user.isLoggedOn()) {
console.log('User is logged into Steam');
} else {
console.log('User is offline or not logged in');
}Generate authentication tickets for P2P or game server authentication.
Get an auth session ticket for P2P or game server authentication.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_GetAuthSessionTicket()- Create session ticket
Parameters:
-
identity?: SteamNetworkingIdentityOptions- Optional: restrict ticket to specific recipient (Steam ID, IP, or string)
Returns: GetAuthSessionTicketResult
Type:
interface GetAuthSessionTicketResult {
success: boolean; // Whether the operation was successful
authTicket: number; // The auth ticket handle (0 if failed)
ticketData: Buffer; // The ticket data as a Buffer
ticketSize: number; // The actual ticket size in bytes
error?: string; // Error message if failed
}
interface SteamNetworkingIdentityOptions {
steamId?: string; // Restrict ticket to specific Steam ID
ipAddress?: string; // Restrict ticket to specific IP address (e.g., '192.168.1.100')
genericString?: string; // Restrict ticket to specific service/recipient identifier
}Examples:
// Get an unrestricted ticket (works with any recipient)
const result = steam.user.getAuthSessionTicket();
// Restrict ticket to a specific Steam ID
const result = steam.user.getAuthSessionTicket({
steamId: '76561198001234567'
});
// Restrict ticket to a specific IP address
const result = steam.user.getAuthSessionTicket({
ipAddress: '192.168.1.100'
});
// Restrict ticket to a service identifier
const result = steam.user.getAuthSessionTicket({
genericString: 'my-dedicated-server'
});
if (result.success) {
console.log(`Got ticket handle: ${result.authTicket}`);
console.log(`Ticket size: ${result.ticketSize} bytes`);
// Send to server for validation
sendToServer({
ticket: result.ticketData,
steamId: steam.getSteamId()
});
}Remarks:
- Call
cancelAuthTicket()when done with the ticket - Ticket is valid until cancelled or user logs off
- Maximum ticket size is 8192 bytes
- If
identityis omitted, creates an unrestricted ticket (usable by any recipient) - Identity restrictions add an extra security layer for high-security scenarios
- Restrictions are embedded in the ticket data itself (ticket size remains the same)
Get an auth ticket for Steam Web API authentication.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_GetAuthTicketForWebApi()- Create web API ticket
Parameters:
-
identity?: SteamNetworkingIdentityOptions- Optional: restrict ticket to specific recipient (Steam ID, IP, or string)
Returns: Promise<GetAuthTicketForWebApiResult>
Type:
interface GetAuthTicketForWebApiResult {
success: boolean; // Whether the operation was successful
authTicket: number; // The auth ticket handle (0 if failed)
ticketData: Buffer; // The ticket data as a Buffer
ticketSize: number; // The actual ticket size in bytes
ticketHex: string; // The ticket as a hex string (for web API usage)
error?: string; // Error message if failed
}
interface SteamNetworkingIdentityOptions {
steamId?: string; // Restrict ticket to specific Steam ID
ipAddress?: string; // Restrict ticket to specific IP address (e.g., '192.168.1.100')
genericString?: string; // Restrict ticket to specific service/recipient identifier
}Examples:
// Get an unrestricted web API ticket
const result = await steam.user.getAuthTicketForWebApi();
// Restrict ticket to a specific Steam ID
const result = await steam.user.getAuthTicketForWebApi({
steamId: '76561198001234567'
});
// Restrict ticket to a specific IP address
const result = await steam.user.getAuthTicketForWebApi({
ipAddress: '192.168.1.100'
});
// Restrict ticket to a service identifier
const result = await steam.user.getAuthTicketForWebApi({
genericString: 'my-backend-server'
});
if (result.success) {
// Use hex string for API authentication
const response = await fetch('https://api.example.com/auth', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Steam-Auth-Ticket': result.ticketHex
},
body: JSON.stringify({ steamId: steam.getSteamId() })
});
}Remarks:
Implementation: This method uses the native GetAuthTicketForWebApi() function with proper callback handling via Koffi's registered callbacks. The callback system is automatically registered on first use and cleaned up during shutdown.
Validation: Tickets should be validated using Steam's Web API:
https://api.steampowered.com/ISteamUserAuth/AuthenticateUserTicket/v1/
Identity Parameter: The identity parameter accepts options for restricting the ticket to a specific recipient:
-
steamId- Restrict to specific Steam user (format:"steamid:76561198001234567") -
ipAddress- Restrict to specific IP address (format:"ip:192.168.1.100") -
genericString- Generic service identifier (format:"my-service")
Ticket Format: Returns tickets in the proper Web API format (234 bytes) that validate correctly with Steam's authentication endpoints.
Async Operation: This is a true async operation that waits for Steam's callback. The method polls RunCallbacks() internally with a 5-second timeout.
Cancel an auth ticket previously obtained.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_CancelAuthTicket()- Cancel auth ticket
Parameters:
-
authTicket: number- The ticket handle to cancel
Returns: void
Example:
// Get a ticket
const ticket = steam.user.getAuthSessionTicket();
// ... use the ticket ...
// Clean up when done
steam.user.cancelAuthTicket(ticket.authTicket);Validate incoming authentication tickets from other players.
Begin validating an auth session ticket.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_BeginAuthSession()- Start auth session validation
Parameters:
-
ticketData: Buffer- The raw ticket data received from the client -
steamId: string- The Steam ID of the user who sent the ticket
Returns: BeginAuthSessionResult
Type:
interface BeginAuthSessionResult {
success: boolean; // Whether the initial validation passed
result: EBeginAuthSessionResult; // The result code from BeginAuthSession
error?: string; // Error message if failed
}
enum EBeginAuthSessionResult {
OK = 0, // Ticket is valid for this game and this steamID
InvalidTicket = 1, // Ticket is not valid
DuplicateRequest = 2, // A ticket has already been submitted for this steamID
InvalidVersion = 3, // Ticket is from an incompatible interface version
GameMismatch = 4, // Ticket is not for this game
ExpiredTicket = 5, // Ticket has expired
}Example:
// Server receives ticket from client
function onClientConnect(ticketData: Buffer, clientSteamId: string) {
const result = steam.user.beginAuthSession(ticketData, clientSteamId);
if (result.success) {
console.log(`Auth session started for ${clientSteamId}`);
} else {
console.log(`Auth failed: ${result.error}`);
disconnectClient(clientSteamId, result.result);
}
}End an auth session previously started with beginAuthSession().
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_EndAuthSession()- End auth session
Parameters:
-
steamId: string- The Steam ID of the user whose session to end
Returns: void
Example:
function onClientDisconnect(clientSteamId: string) {
steam.user.endAuthSession(clientSteamId);
console.log(`Ended auth session for ${clientSteamId}`);
}Check if a user owns specific apps or DLC.
Check if a user has a license for a specific app.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_UserHasLicenseForApp()- Check license ownership
Parameters:
-
steamId: string- The Steam ID of the user to check -
appId: number- The App ID to check ownership for
Returns: EUserHasLicenseForAppResult
Type:
enum EUserHasLicenseForAppResult {
HasLicense = 0, // User has a license for specified app
DoesNotHaveLicense = 1, // User does not have a license for the specified app
NoAuth = 2, // User has not been authenticated
}Example:
// Check if user owns a DLC
const dlcResult = steam.user.userHasLicenseForApp(clientSteamId, 12345);
if (dlcResult === EUserHasLicenseForAppResult.HasLicense) {
console.log('User owns the DLC');
} else if (dlcResult === EUserHasLicenseForAppResult.DoesNotHaveLicense) {
console.log('User does not own the DLC');
} else {
console.log('User not authenticated');
}Remarks:
⚠️ Important: This function should only be called after successfully authenticating the user withbeginAuthSession()- The user must be authenticated before their license information is available
- If called before authentication, it will return
NoAuth(2) - Common workflow: Receive ticket →
beginAuthSession()→userHasLicenseForApp()→ Grant/deny access
Complete Authentication Example:
// 1. Receive and validate the user's auth ticket
const authResult = steam.user.beginAuthSession(ticketData, clientSteamId);
if (authResult.success) {
// 2. Now check if they own specific DLC/app
const licenseResult = steam.user.userHasLicenseForApp(clientSteamId, dlcAppId);
if (licenseResult === EUserHasLicenseForAppResult.HasLicense) {
console.log('User authenticated and owns the DLC');
} else if (licenseResult === EUserHasLicenseForAppResult.NoAuth) {
console.log('User not yet authenticated - call beginAuthSession first');
}
// 3. Clean up when done
// steam.user.endAuthSession(clientSteamId);
}Request and retrieve encrypted app tickets for secure backend authentication.
Request an encrypted app ticket from Steam.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_RequestEncryptedAppTicket()- Request encrypted ticket
Parameters:
-
dataToInclude?: Buffer- Optional data to include in the ticket (max 128 bytes)
Returns: Promise<RequestEncryptedAppTicketResult>
Type:
interface RequestEncryptedAppTicketResult {
success: boolean; // Whether the request was successful
error?: string; // Error message if failed
}Example:
// Request an encrypted ticket
const result = await steam.user.requestEncryptedAppTicket();
if (result.success) {
// Now retrieve the ticket
const ticket = steam.user.getEncryptedAppTicket();
if (ticket.success) {
// Send to your backend for verification
sendToBackend(ticket.ticketData);
}
}Get the encrypted app ticket after requesting it.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_GetEncryptedAppTicket()- Retrieve encrypted ticket
Returns: GetEncryptedAppTicketResult
Type:
interface GetEncryptedAppTicketResult {
success: boolean; // Whether the operation was successful
ticketData: Buffer; // The encrypted ticket data
ticketSize: number; // The actual ticket size in bytes
ticketHex: string; // The ticket as a hex string
error?: string; // Error message if failed
}Example:
const result = steam.user.getEncryptedAppTicket();
if (result.success) {
console.log(`Got encrypted ticket (${result.ticketSize} bytes)`);
// Send ticketHex to your backend
authenticateWithBackend(result.ticketHex);
}Get user security settings and network status.
Get the user's security settings.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_BIsPhoneVerified()- Check phone verification -
SteamAPI_ISteamUser_BIsTwoFactorEnabled()- Check 2FA status -
SteamAPI_ISteamUser_BIsPhoneIdentifying()- Check phone identifying -
SteamAPI_ISteamUser_BIsPhoneRequiringVerification()- Check phone verification requirement
Returns: UserSecurityInfo
Type:
interface UserSecurityInfo {
phoneVerified: boolean; // Whether the user's phone number is verified
twoFactorEnabled: boolean; // Whether the user has 2FA enabled
phoneIdentifying: boolean; // Whether the user's phone number is identifying
phoneRequiringVerification: boolean; // Whether the user's phone number needs verification
}Example:
const security = steam.user.getUserSecurityInfo();
if (security.twoFactorEnabled) {
console.log('User has 2FA enabled');
}
if (security.phoneVerified) {
console.log('Phone number is verified');
}Check if the user appears to be behind a NAT.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_BIsBehindNAT()- Check NAT status
Returns: boolean - true if user is behind NAT
Example:
if (steam.user.isBehindNAT()) {
console.log('User is behind NAT - may need relay');
}Get information about the current user.
Get the user's Steam level.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_GetPlayerSteamLevel()- Get Steam level
Returns: number - The user's Steam level, or 0 if not available
Example:
const level = steam.user.getPlayerSteamLevel();
console.log(`Steam Level: ${level}`);Get the user's game badge level.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_GetGameBadgeLevel()- Get badge level
Parameters:
-
series: number- The badge series (usually 1 for games with one badge set) -
foil: boolean- Whether to get the foil badge (true) or regular badge (false)
Returns: number - The badge level, or 0 if none
Example:
// Get regular badge level
const regularLevel = steam.user.getGameBadgeLevel(1, false);
console.log(`Regular badge level: ${regularLevel}`);
// Get foil badge level
const foilLevel = steam.user.getGameBadgeLevel(1, true);
console.log(`Foil badge level: ${foilLevel}`);Get the path to the local user data folder.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_GetUserDataFolder()- Get user data path
Returns: string | null - The path to the user data folder, or null if not available
Example:
const folder = steam.user.getUserDataFolder();
if (folder) {
console.log(`User data folder: ${folder}`);
// Typically: C:\Program Files\Steam\userdata\<steamid>\<appid>\local
}Check if the user can use the Steam Community Market.
Get the user's Steam Community Market eligibility.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_GetMarketEligibility()- Get market eligibility
Returns: Promise<MarketEligibilityResult>
Type:
interface MarketEligibilityResult {
allowed: boolean; // Whether the user is allowed to use the market
notAllowedReason: number; // The reason why the user is not allowed (if not allowed)
allowedAtTime: number; // When the user will be allowed (Unix timestamp)
steamGuardRequiredDays: number; // Days of Steam Guard required
newDeviceCooldownDays: number; // New device cooldown days
}Example:
const eligibility = await steam.user.getMarketEligibility();
if (eligibility.allowed) {
console.log('User can use the Steam Market');
} else {
console.log(`Market restricted: reason ${eligibility.notAllowedReason}`);
}Generate authenticated URLs for in-game browser checkout.
Request an authenticated URL for in-game browser store checkout.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_RequestStoreAuthURL()- Request authenticated URL
Parameters:
-
redirectURL: string- The URL to redirect to after authentication
Returns: Promise<StoreAuthURLResult>
Type:
interface StoreAuthURLResult {
success: boolean; // Whether the request was successful
url: string | null; // The authenticated URL for in-game browser checkout
error?: string; // Error message if failed
}Example:
const result = await steam.user.requestStoreAuthURL('https://store.steampowered.com/');
if (result.success && result.url) {
// Open in-game browser immediately (URL has short lifetime)
openBrowser(result.url);
}Remarks:
- The URL has a very short lifetime (~seconds) to prevent history-snooping attacks
- The resulting auth cookie lasts ~1 day; consider refreshing every 12 hours
Support for anti-indulgence compliance (primarily for China region).
Get duration control status for the current user.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_GetDurationControl()- Get duration control status
Returns: Promise<DurationControlResult>
Type:
interface DurationControlResult {
success: boolean; // Whether the call was successful
appId: number; // App ID generating playtime
applicable: boolean; // Whether duration control applies to this user + game
secondsLast5Hours: number; // Seconds of playtime in last 5 hours
progress: number; // Recommended progress (0 = ok, 1 = exit game)
notification: number; // Notification to show (0 = none)
secondsToday: number; // Playtime on current calendar day in seconds
secondsRemaining: number; // Playtime remaining until regulatory limit in seconds
}Example:
const duration = await steam.user.getDurationControl();
if (duration.applicable) {
console.log(`Time remaining: ${duration.secondsRemaining} seconds`);
if (duration.progress === 1) {
console.log('Player should exit the game');
}
}Set the duration control online state.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_BSetDurationControlOnlineState()- Set online state
Parameters:
-
state: EDurationControlOnlineState- The online state to set
Type:
enum EDurationControlOnlineState {
Invalid = 0, // Default state
Offline = 1, // Player is in offline mode
Online = 2, // Player is online
OnlineHighPri = 3, // Player is online in high priority mode (competitive match)
}Returns: boolean - true if successful
Example:
// Player is in an online match
steam.user.setDurationControlOnlineState(EDurationControlOnlineState.Online);
// Player is in an important competitive match
steam.user.setDurationControlOnlineState(EDurationControlOnlineState.OnlineHighPri);
// Player is playing offline
steam.user.setDurationControlOnlineState(EDurationControlOnlineState.Offline);Advertise game server information to friends.
Advertise the game server to friends for joining.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_AdvertiseGame()- Advertise game server
Parameters:
-
serverSteamId: string- The Steam ID of the game server (use '0' for none) -
serverIP: number- The IP address of the server (in host byte order) -
serverPort: number- The port of the server
Returns: void
Example:
// Advertise that the user is on a game server
steam.user.advertiseGame('90071234567890', ipToInt('192.168.1.100'), 27015);
// Clear the advertisement
steam.user.advertiseGame('0', 0, 0);Record and transmit voice chat audio.
Start voice recording.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_StartVoiceRecording()- Start recording
Returns: void
Example:
// Start recording when push-to-talk key is pressed
steam.user.startVoiceRecording();
// In your game loop, retrieve and send voice data
const voice = steam.user.getVoice();
if (voice.result === EVoiceResult.OK) {
sendToOtherPlayers(voice.voiceData);
}Stop voice recording.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_StopVoiceRecording()- Stop recording
Returns: void
Example:
// Stop recording when push-to-talk key is released
steam.user.stopVoiceRecording();
// Keep fetching voice data until recording fully stops
let voice = steam.user.getVoice();
while (voice.result !== EVoiceResult.NotRecording) {
if (voice.result === EVoiceResult.OK) {
sendToOtherPlayers(voice.voiceData);
}
voice = steam.user.getVoice();
}Get the amount of voice data available.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_GetAvailableVoice()- Get available voice data size
Returns: GetAvailableVoiceResult
Type:
interface GetAvailableVoiceResult {
result: EVoiceResult; // Voice result code
compressedBytes: number; // Number of compressed bytes available
}
enum EVoiceResult {
OK = 0, // Voice call was successful
NotInitialized = 1, // Steam voice chat has not been initialized
NotRecording = 2, // Voice recording is not active
NoData = 3, // No data is available (microphone may be off or silent)
BufferTooSmall = 4, // The provided buffer was too small
DataCorrupted = 5, // Voice data is corrupted
Restricted = 6, // Voice chat is restricted for this user
UnsupportedCodec = 7, // The voice codec is not supported
ReceiverOutOfDate = 8, // The receiver is using an outdated voice codec
ReceiverDidNotAnswer = 9, // The receiver did not answer
}Example:
const available = steam.user.getAvailableVoice();
if (available.result === EVoiceResult.OK && available.compressedBytes > 0) {
console.log(`${available.compressedBytes} bytes of voice data ready`);
}Get recorded voice data.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_GetVoice()- Get recorded voice data
Parameters:
-
bufferSize?: number- Size of the buffer to allocate for voice data (default: 8192)
Returns: GetVoiceResult
Type:
interface GetVoiceResult {
result: EVoiceResult; // Voice result code
voiceData: Buffer | null; // Buffer containing compressed voice data (if successful)
bytesWritten: number; // Number of bytes written to the buffer
}Example:
// In your game loop:
const voice = steam.user.getVoice();
switch (voice.result) {
case EVoiceResult.OK:
// Send compressed voice data to other players
network.broadcast(voice.voiceData);
break;
case EVoiceResult.NoData:
// Microphone is silent, nothing to do
break;
case EVoiceResult.NotRecording:
// Recording has stopped
break;
}Decompress voice data.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_DecompressVoice()- Decompress voice data
Parameters:
-
compressedData: Buffer- The compressed voice data to decompress -
sampleRate: number- The desired output sample rate (11025-48000) -
bufferSize?: number- Size of the output buffer (default: 20480)
Returns: DecompressVoiceResult
Type:
interface DecompressVoiceResult {
result: EVoiceResult; // Voice result code
audioData: Buffer | null; // Buffer containing decompressed PCM audio data
bytesWritten: number; // Number of bytes written to the buffer
}Example:
// Receive compressed voice data from another player
const compressedData = network.receiveVoiceData();
// Decompress at optimal sample rate
const sampleRate = steam.user.getVoiceOptimalSampleRate();
const audio = steam.user.decompressVoice(compressedData, sampleRate);
if (audio.result === EVoiceResult.OK) {
// Play the PCM audio through your audio system
audioPlayer.playPCM(audio.audioData, sampleRate);
}Get the optimal sample rate for voice decompression.
Steamworks SDK Functions:
-
SteamAPI_ISteamUser_GetVoiceOptimalSampleRate()- Get optimal sample rate
Returns: number - The optimal sample rate (typically 11025, 22050, or 44100)
Example:
const optimalRate = steam.user.getVoiceOptimalSampleRate();
console.log(`Optimal sample rate: ${optimalRate} Hz`);
// Use for decompression
const audio = steam.user.decompressVoice(voiceData, optimalRate);Clean up resources when shutting down.
Cancel all active auth tickets.
Returns: void
Example:
// Clean up when shutting down
steam.user.cancelAllTickets();Test files are available in the repository:
-
TypeScript tests:
tests/ts/test-user.ts -
JavaScript tests:
tests/js/test-user.js
Run tests using npm:
# TypeScript tests
npm run test:user:ts
# JavaScript tests
npm run test:user:js