Skip to content

Steam Auth Tickets

Secure backend authentication via Steam-issued auth tickets. Use this to implement "Sign in with Steam" for multiplayer servers, Supabase, Firebase, Colyseus, or any backend that needs to verify a player's identity.

Why not just use getSteamID()?

getSteamID() returns a display value that any modified client can fake. Auth tickets are cryptographically signed by Steam's servers — your backend verifies them directly with Valve, so a tampered client cannot forge a valid identity.

How it works

  1. Your game calls getAuthTicketForWebApi(identity) — Steam returns a signed ticket
  2. Your game sends the ticketHex to your backend (via fetch, WebSocket, etc.)
  3. Your backend calls Steam Web API ISteamUserAuth/AuthenticateUserTicket with your publisher key to verify the ticket
  4. Steam confirms the player's Steam ID — your backend can trust it

Methods

getAuthTicketForWebApi(identity?)

Request a Steam auth ticket for web API verification. Blocks briefly while Steam generates the ticket (typically < 1 second).

javascript
const result = await steam.getAuthTicketForWebApi('my-game-server');
// {
//   handle: 3,
//   ticketHex: "14000000EA27DA2DE6F9B9CDE7DA720001001016...",
//   identity: "my-game-server"
// }

Parameters:

  • identity (optional) — A string identifying your backend service. Steam includes this in the ticket so your server can verify which service the ticket was intended for. Use a consistent name like "my-game-server" or "production-api".

Returns: { handle, ticketHex, identity }

  • handle — Ticket handle (used to cancel later). 0 if the request failed.
  • ticketHex — The ticket as a hex string. Send this to your backend.
  • identity — The identity string you passed in (or null).

cancelAuthTicket(handle)

Cancel an active auth ticket. Call this when the player logs out or the session ends.

javascript
await steam.cancelAuthTicket(result.handle);

TIP

Steam allows a maximum of 10 active auth tickets per user. Always cancel tickets when they're no longer needed.

Examples

Sign in with Steam (fetch)

javascript
async function signInWithSteam() {
  // 1. Get auth ticket from Steam
  const { handle, ticketHex } = await steam.getAuthTicketForWebApi('my-backend');
  if (!handle) {
    console.error('Failed to get auth ticket');
    return null;
  }

  // 2. Send ticket to your backend for verification
  const response = await fetch('https://api.my-game.com/auth/steam', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ ticket: ticketHex })
  });

  const session = await response.json();
  // session.userId, session.token, etc.

  // 3. Cancel the ticket (backend already verified it)
  await steam.cancelAuthTicket(handle);

  return session;
}

Backend verification (Node.js example)

javascript
// On your server — NOT in the game client
const STEAM_WEB_API_KEY = process.env.STEAM_WEB_API_KEY;
const APP_ID = '480'; // Your Steam App ID

async function verifySteamTicket(ticketHex) {
  const url = `https://api.steampowered.com/ISteamUserAuth/AuthenticateUserTicket/v1/?key=${STEAM_WEB_API_KEY}&appid=${APP_ID}&ticket=${ticketHex}`;
  const res = await fetch(url);
  const data = await res.json();

  if (data.response?.params?.result === 'OK') {
    return {
      steamId: data.response.params.steamid,
      ownerSteamId: data.response.params.ownersteamid,
      vacBanned: data.response.params.vacbanned,
      publisherBanned: data.response.params.publisherbanned
    };
  }
  throw new Error('Steam ticket verification failed');
}

Colyseus / multiplayer server auth

javascript
// Client side (in your GemShell game)
async function joinGameServer() {
  const { ticketHex } = await steam.getAuthTicketForWebApi('colyseus');
  const steamId = await steam.getSteamID();

  const room = await client.joinOrCreate('game-room', {
    steamTicket: ticketHex,
    steamId: steamId
  });
  return room;
}
javascript
// Server side (Colyseus room)
async onAuth(client, options) {
  const verified = await verifySteamTicket(options.steamTicket);
  if (verified.steamId !== options.steamId) {
    throw new Error('Steam ID mismatch');
  }
  return { steamId: verified.steamId };
}