Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Oyuncuyu oyun sunucunuzda doğrulama

Oyun sunucunuz, kendisine gelen bir istek ya da bağlantının hangi oyuncuya ait olduğunu bilmek ister. Bu sayfa iki yolu anlatır: Open Play’in imzaladığı erişim JWT’sini çevrimdışı doğrulamak (JWKS ile) ve oturumu Open Play’e sorarak doğrulamak. Hangi yolun sizin için uygun olduğunu sayfanın sonundaki karşılaştırma tablosu söyler.

Uyarı

Bugünkü SDK sınırı: TypeScript ve Unity SDK’ları erişim JWT’sini uygulamaya açmaz; belirteç yalnızca ham REST giriş yanıtının gövdesinde (tokens.access_token) bulunur. SDK kullanan bir istemci JWT’yi sunucunuza veremez. SDK’lı istemciler için aşağıdaki Yol B (oturum doğrulama) kullanılabilir. Bu eksiklik kayıtlıdır.

Yol A: erişim JWT’sini çevrimdışı doğrulama

Belirteç

Giriş, kayıt, yenileme ve OAuth callback yanıtları tokens.access_token döndürür: EdDSA (Ed25519) ile imzalı, 15 dakikalık compact JWT. Belirteç yalnız gövdededir; çerezde taşınmaz. Süresi dolunca POST /v1/auth/refresh yenisini verir.

Başlık: {"alg":"EdDSA","typ":"JWT","kid":"<anahtar-kimliği>"}. Yük:

AlanAnlamı
subOyuncu kimliği (UUID)
envOrtam kimliği (UUID)
sidOturum kimliği (UUID)
orgEtkin organizasyon (yoksa alan yok)
iat, expÜretim ve bitiş anı: Unix milisaniye (saniye değil)

Uyarı

iat ve exp milisaniyedir ve belirteçte iss/aud yoktur. Standart JWT kütüphaneleri exp’i saniye sayar; milisaniye değerini uzak gelecekte bir tarih sanıp süresi dolmuş belirteci kabul eder. Kütüphane kullanırsanız imzayı ona doğrulatın ama exp denetimini kendiniz yapın (exp > Date.now()).

Anahtarlar (JWKS)

curl -sS "$OPEN_PLAY_URL/v1/auth/jwks"
{"keys":[{"kty":"OKP","crv":"Ed25519","kid":"<anahtar-kimliği>","use":"sig","alg":"EdDSA","x":"<base64url genel anahtar>"}]}

Kimlik gerekmez. Sunucu imzalayıcıyı yayınlamadıysa 404 döner. Yanıtı önbelleğe alın ve yalnızca belirteçteki kid listede yoksa yenileyin; her istekte çekmeyin.

Doğrulama adımları

  1. Belirteci üç parçaya ayırın; başlıktaki alg değeri EdDSA olmalı, aksi halde reddedin.
  2. kid ile JWKS’ten anahtarı bulun; yoksa JWKS’i bir kez yenileyin.
  3. İmzayı header.payload metni üzerinde Ed25519 ile doğrulayın.
  4. exp > şimdi (ms) olduğunu denetleyin.
  5. env değerini kendi ortam kimliğinizle karşılaştırın.

Uyarı

Aynı Open Play sunucusundaki bütün oyunların belirteçleri aynı JWKS ile doğrulanır. env karşılaştırmasını atlarsanız, başka bir oyunun oyuncusu sizin sunucunuzda geçerli görünür. Bu adım zorunludur.

Node.js (yalnız yerleşik node:crypto, bağımlılık yok):

import { createPublicKey, verify, type JsonWebKey } from "node:crypto";

/** Open Play erişim JWT'sinin (EdDSA) yük alanları. `iat` ve `exp` saniye değil, Unix MİLİSANİYEDİR. */
export interface AccessClaims {
  readonly sub: string; // oyuncu kimliği
  readonly env: string; // ortam kimliği
  readonly sid: string; // oturum kimliği
  readonly org?: string;
  readonly iat: number;
  readonly exp: number;
}

interface Jwks {
  readonly keys: ReadonlyArray<JsonWebKey & { readonly kid?: string }>;
}

function decode(part: string): Buffer {
  return Buffer.from(part, "base64url");
}

/**
 * Oyuncunun erişim JWT'sini çevrimdışı doğrular: imza, süre ve ortam eşleşmesi.
 * JWKS'i her istekte çekmeyin; `jwks` parametresini önbellekten verin (anahtar döndürülürse bilinmeyen `kid` gelince yenileyin).
 */
export function verifyAccessToken(token: string, jwks: Jwks, expectedEnvironmentId: string, nowMs: number = Date.now()): AccessClaims {
  const parts = token.split(".");
  const [header, payload, signature] = parts;
  if (parts.length !== 3 || header === undefined || payload === undefined || signature === undefined) {
    throw new Error("Biçimi bozuk JWT.");
  }
  const head = JSON.parse(decode(header).toString("utf8")) as { alg?: string; kid?: string };
  if (head.alg !== "EdDSA") throw new Error("Beklenmeyen algoritma.");
  const jwk = jwks.keys.find((key) => key.kid === head.kid);
  if (jwk === undefined) throw new Error("Bilinmeyen anahtar kimliği; JWKS'i yenileyin.");
  const publicKey = createPublicKey({ key: jwk, format: "jwk" });
  const signed = Buffer.from(`${header}.${payload}`, "utf8");
  if (!verify(null, signed, publicKey, decode(signature))) throw new Error("İmza doğrulanamadı.");

  const claims = JSON.parse(decode(payload).toString("utf8")) as AccessClaims;
  if (claims.exp <= nowMs) throw new Error("Belirtecin süresi dolmuş.");
  // JWKS tüm oyunlar için ortaktır: başka bir ortamın oyuncusunu kabul etmemek için `env` mutlaka karşılaştırılır.
  if (claims.env !== expectedEnvironmentId) throw new Error("Belirteç başka bir ortama ait.");
  return claims;
}

/** JWKS'i çeker (kimlik gerekmez). */
export async function fetchJwks(baseUrl: string): Promise<Jwks> {
  const response = await fetch(`${baseUrl}/v1/auth/jwks`);
  if (!response.ok) throw new Error(`JWKS okunamadı: ${response.status}`);
  return (await response.json()) as Jwks;
}

Sınırlar

  • İptal görmez. Çevrimdışı doğrulama oturumun kapatıldığını, iptal edildiğini ya da oyuncunun banlandığını bilemez; belirteç exp’ine kadar (en çok 15 dakika) geçerli görünür. İptal duyarlı olması gereken işlemlerde Yol B’yi kullanın ya da bu 15 dakikalık pencereyi kabul edin.
  • Anahtar döndürme. Anahtar değişimi sunucuyu yeniden başlatır; yeni kid JWKS’te görünür. Önbelleğiniz bilinmeyen kid görünce yenilenmelidir.

Yol B: oturumu Open Play’e sorma

Oyuncunun oturum belirtecini (çerez değeri ya da Authorization: Bearer belirteci) ve ortam kimliğini Open Play’e ileterek oyuncuyu çözersiniz. Tarayıcı oyununda oyunun origin’ine giden isteklerde oturum çerezi (__Secure-crx.session) zaten gelir; sunucunuz bu değeri okuyup Open Play’e Bearer olarak iletebilir.

curl -sS "$OPEN_PLAY_URL/v1/auth/session" \
  -H "Authorization: Bearer $PLAYER_SESSION_TOKEN" \
  -H "x-crx-env: $OPEN_PLAY_ENV"

200 ve {"environment_id","player_id","session_id","is_guest","displayName","email",…}. İptal edilmiş, süresi dolmuş ya da banlı oturum 401 verir. GET olduğu için CSRF belirteci gerekmez.

Uyarı

Oturum belirteci bir yetkidir. Açık metin günlüğe yazmayın, başka servislere yaymayın ve yalnızca TLS üzerinden iletin.

Hangi yolu seçmeliyim?

Yol A: JWT çevrimdışıYol B: oturum sorgusu
Open Play’e istekYok (JWKS önbellekte)Her doğrulamada bir istek
İptal/ban görürHayır (en çok 15 dk gecikme)Evet
Belirteç kaynağıYalnız ham REST giriş yanıtı; SDK vermezÇerez ya da Bearer oturum belirteci; SDK’lı istemciyle de çalışır (tarayıcıda çerez)
Ortam doğrulamasıenv talebini siz karşılaştırırsınızOrtam, istekteki x-crx-env ile sınanır
Ne zaman?Çok yüksek istek hacmi, iptal gecikmesi kabul edilebilirVarsayılan öneri; oyuncu kimliği kritik işlemler

Sunucu-sunucu çağrılarında oyuncu yerine sunucu anahtarı kullanılır (Kavramlar).