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

E-posta ve parola

E-posta ve parola, oyuncuya cihazlar arası kalıcı bir hesap verir. Bu sayfada kayıt, giriş, misafirden kalıcı hesaba terfi, parola değiştirme ve sıfırlama akışlarını, istek ve yanıt örnekleriyle ve SDK çağrılarıyla bulacaksınız. Tüm çağrılar ortak kuralları (ortam başlığı, CSRF) izler.

Kurallar

  • E-posta kırpılır ve küçük harfe çevrilir; tam bir @ içermeli ve alan kısmında nokta bulunmalıdır. Aynı ortamda bir adres yalnız bir hesapta olabilir.
  • Parola 8–128 karakter (Unicode karakter sayılır, bayt değil). Parola Argon2id ile saklanır.
  • Görünen ad zorunludur; 1–100 karakter kullanın (sunucu bu sınırı misafir terfisinde uygular). Oyuncu sonradan adını 2–24 karakter kuralıyla değiştirebilir (Misafir girişi › Görünen ad).
  • Bugün e-posta doğrulama ucu yoktur; kayıtta email_verified false döner.
  • SDK’lar istek göndermeden önce yalın sınır denetimi yapar (e-posta 3–320, parola en çok 1024, görünen ad en çok 256 birim; kontrol karakteri yok). Asıl politika sunucudadır.

Kayıt

POST /v1/auth/sign-up/email
content-type: application/json
x-crx-env: <ortam-kimliği>
x-csrf-token: <csrf-belirteci>

{"email":"[email protected]","password":"<en az 8 karakter>","display_name":"Ayşe"}

201 ve ortak giriş zarfı (is_new_player: true, player.is_guest: false, player.email dolu) + oturum çerezleri.

DurumAnlamı
400E-posta biçimi ya da parola politikası ihlali
409Adres bu ortamda kayıtlı (gövde adresi tekrar etmez)
429IP başına 10 / 60 sn ya da adres başına 5 / 15 dk aşıldı

Giriş

POST /v1/auth/sign-in/email
content-type: application/json
x-crx-env: <ortam-kimliği>
x-csrf-token: <csrf-belirteci>

{"email":"[email protected]","password":"<parola>"}

200 ve giriş zarfı (is_new_player: false).

  • Yanlış parola ile bilinmeyen adres aynı yanıtı alır (403 düz metin); hangisi olduğu sızmaz.
  • Parolası doğru ama banlı hesap 403 ve {"code":"account_banned","message":"account banned"} alır; çerez silinmez.
  • Aynı adres + IP için 15 dakikada 10 başarısız giriş hesabı kilitler; kilitliyken doğru parola da 429 alır. Başarılı giriş hakkı iade eder. IP başına ayrıca 5 / 60 sn sınırı vardır.
  • İstekte başka bir oyuncunun (örneğin aynı tarayıcıdaki eski misafirin) kullanılabilir oturumu varsa, giriş başarılı olduktan sonra o oturum ailesi iptal edilir. Aynı oyuncunun oturumuna dokunulmaz.

Misafir terfisi

Misafir oyuncuyu aynı player.id ile kalıcı hesaba çevirir; ilerleme korunur. Misafir oturumu gerekir (çerez ya da Authorization: Bearer <oturum-belirteci>).

POST /v1/auth/guest/upgrade/email
content-type: application/json
x-crx-env: <ortam-kimliği>
x-csrf-token: <csrf-belirteci>

{"email":"[email protected]","password":"<parola>","display_name":"Ayşe"}

200; aynı player.id, is_guest: false, yalnız yeni oturum çifti. Terfi tek bir veritabanı işlemidir: kimlik eklenir, misafir sırrı emekliye ayrılır, eski oturumlar iptal edilir ve yeni oturum açılır.

DurumAnlamı
400E-posta, parola ya da ad doğrulaması
401Ortam başlığı ya da oturum yok
403Oturum etkin değil, başka ortama ait ya da CSRF reddi
409Adres bu ortamda başka bir hesapta kayıtlı; işlem geri alınır, misafir oturumu bozulmaz
422Oyuncu artık misafir değil (yinelenen ya da eşzamanlı istek)
429IP 10 / 60 sn, misafir oyuncu 30 / 60 sn ya da adres 5 / 15 dk aşıldı

Yanıt kaybolursa (bağlantı koptu) eski misafir oturumları iptal edilmiş olabilir; kurtarma yolu normal e-posta girişidir.

Parola değiştirme

Oturum gerekir. Eski parola doğrulanır; başarıda tüm oturumlar (bu dahil) iptal edilir ve çerezler silinir; oyuncu yeniden giriş yapar.

POST /v1/auth/change-password
content-type: application/json
x-crx-env: <ortam-kimliği>
x-csrf-token: <csrf-belirteci>

{"old_password":"<mevcut>","new_password":"<yeni>"}

204. Hatalar: 400 yeni parola politikası ihlali, 403 oturum ya da eski parola reddi, 429 IP 10 / 60 sn ya da hesap 6 / 60 sn. Yanlış mevcut parola, giriş kilidinin sayacına da sayılır.

Parola sıfırlama

  1. POST /v1/auth/forgot-password ile sıfırlama e-postası istenir. Hesap olsa da olmasa da yanıt aynı 200’dür (hesap varlığı sızmaz).
  2. E-postadaki token ile POST /v1/auth/reset-password çağrılır. Token tek kullanımlıktır ve 1 saat geçerlidir. Başarıda tüm oturumlar iptal edilir.
POST /v1/auth/forgot-password
content-type: application/json
x-crx-env: <ortam-kimliği>
x-csrf-token: <csrf-belirteci>

{"email":"[email protected]"}
POST /v1/auth/reset-password
content-type: application/json
x-crx-env: <ortam-kimliği>
x-csrf-token: <csrf-belirteci>

{"token":"<64 hex>","new_password":"<yeni>"}

reset-password hataları: 400 yeni parola politikası ihlali (token yanmaz, aynı bağlantıyla yeniden denenebilir), 403 token geçersiz/kullanılmış/süresi dolmuş ya da CSRF (ayrım sızmaz), 429 sınır aşımı (5 / 60 sn, forgot ve magic link ile ortak IP kovası).

Uyarı

Bilinen kısıt: Sıfırlama e-postasındaki bağlantı oyununuzun sayfasına değil, sunucunun API kökündeki /v1/auth/reset-password?token=… adresine gider. Bu yolda GET ucu yoktur; yani bağlantıya tıklamak bir sayfa göstermez. Oyununuzda sıfırlamayı sunmak için oyuncunun e-postadaki token değerini kendi sıfırlama ekranınıza taşıması gerekir (örneğin kendi ters vekilinizde bu yolu bir oyun sayfasına yönlendirmek; bu yönlendirme bu repoda doğrulanmadı). E-posta gönderimi operatörün SMTP ayarına bağlıdır.

SDK

import { CrxError, ErrorKind, type PlayerClient } from "@ferdiunal/open-play-ts";

/** Yeni hesap açar ve oturumu başlatır. Adres kayıtlıysa sunucu 409 döner (`ErrorKind.Http`, status 409). */
export async function register(client: PlayerClient, email: string, password: string, displayName: string): Promise<void> {
  await client.session.signUpEmail({ email, password, displayName });
}

/** Mevcut hesapla girer. Yanlış parola ile bilinmeyen adres aynı yanıtı alır; hangisi olduğu sızmaz. */
export async function login(client: PlayerClient, email: string, password: string): Promise<void> {
  await client.session.signInEmail({ email, password });
}

/**
 * Misafir ilerlemesini koruyarak kalıcı hesaba geçer: aynı `playerId`, yeni oturum.
 * Önce misafir olarak girilmiş olmalıdır; adres başka bir hesapta kayıtlıysa 409 döner ve misafir oturumu bozulmaz.
 */
export async function upgradeGuestToEmail(client: PlayerClient, email: string, password: string, displayName: string): Promise<void> {
  if (client.session.state.status !== "authenticated") await client.session.signInGuest();
  try {
    await client.session.upgradeGuest({ email, password, displayName });
  } catch (error) {
    if (error instanceof CrxError && error.kind === ErrorKind.Http && error.status === 409) {
      throw new Error("Bu e-posta adresi başka bir hesapta kayıtlı.");
    }
    throw error;
  }
}

/** Parola sıfırlama isteği: hesap olsa da olmasa da yanıt aynıdır. */
export async function requestReset(client: PlayerClient, email: string): Promise<void> {
  await client.session.requestPasswordReset({ email });
}

/** E-postadaki token ile yeni parola belirler; başarıda tüm oturumlar kapanır, oyuncu yeniden giriş yapar. */
export async function finishReset(client: PlayerClient, token: string, newPassword: string): Promise<void> {
  await client.session.resetPassword({ token, newPassword });
}

/** Oturum açıkken parola değiştirir; başarıda tüm oturumlar (bu dahil) kapanır. */
export async function changePassword(client: PlayerClient, currentPassword: string, newPassword: string): Promise<void> {
  await client.session.changePassword({ currentPassword, newPassword });
}
TypeScriptUnityUç
signUpEmailSignUpEmailAsyncsign-up/email
signInEmailSignInEmailAsyncsign-in/email
upgradeGuestUpgradeGuestAsyncguest/upgrade/email
changePassword({ currentPassword, newPassword })ChangePasswordAsyncchange-password (gövdede old_password)
requestPasswordResetRequestPasswordResetAsyncforgot-password
resetPasswordResetPasswordAsyncreset-password

SDK’ların ortak davranışı:

  • Parola ve token yalnız istek gövdesine yazılır; oturum durumuna, olay dinleyicilerine, hata nesnelerine ve günlüğe girmez.
  • Kimlik uçlarında 403 yalnızca CSRF katmanı reddettiyse (yanıtta yeni bir x-csrf-token yoksa) SDK bir kez taze belirteçle yeniden dener.
  • İstek gönderildikten sonra bağlantı kaybolursa giriş uçları en çok bir oturum yoklaması yapar; sonuç belirsizse UnknownOutcome hatası alırsınız. Parola değiştirme ve sıfırlama gibi sonuç döndürmeyen çağrılarda da kör yeniden deneme yapılmaz.
  • upgradeGuest oturum yokken ağ isteği göndermez; sunucunun kesin ret yanıtları (4xx) misafir oturumunu düşürmez.
  • changePassword başarıda logout ile aynı geçişi uygular (durum signedOut).

Unity örneği:

using System.Threading.Tasks;
using OpenPlay;
using OpenPlay.Session;
using OpenPlay.Support;

/// <summary>E-posta ve parola akışları. Parola SecretText ile taşınır; günlüğe ve ToString()'e girmez.</summary>
public static class EmailAuth
{
    public static Task<SessionState> Register(OpenPlayClient client, string email, string password, string displayName) =>
        client.Session.SignUpEmailAsync(new SignUpEmailInput { Email = email, Password = new SecretText(password), DisplayName = displayName });

    public static Task<SessionState> Login(OpenPlayClient client, string email, string password) =>
        client.Session.SignInEmailAsync(new SignInEmailInput { Email = email, Password = new SecretText(password) });

    /// <summary>Misafir ilerlemesini korur: aynı oyuncu, yeni oturum. Adres kayıtlıysa HTTP 409 gelir.</summary>
    public static async Task<SessionState> UpgradeGuest(OpenPlayClient client, string email, string password, string displayName)
    {
        try
        {
            return await client.Session.UpgradeGuestAsync(new UpgradeGuestInput { Email = email, Password = new SecretText(password), DisplayName = displayName });
        }
        catch (OpenPlayException ex) when (ex.Kind == ErrorKind.Http && ex.Status == 409)
        {
            throw new System.InvalidOperationException("Bu e-posta adresi başka bir hesapta kayıtlı.");
        }
    }

    public static Task RequestReset(OpenPlayClient client, string email) =>
        client.Session.RequestPasswordResetAsync(new PasswordResetRequestInput { Email = email });

    /// <summary>E-postadaki token ile yeni parola; başarıda tüm oturumlar kapanır.</summary>
    public static Task FinishReset(OpenPlayClient client, string token, string newPassword) =>
        client.Session.ResetPasswordAsync(new ResetPasswordInput { Token = new SecretText(token), NewPassword = new SecretText(newPassword) });

    /// <summary>Görünen ad kuralı: normalize sonrası 2..24 karakter, saatte 10 değişiklik.</summary>
    public static Task<SessionState> Rename(OpenPlayClient client, string displayName) =>
        client.Session.RenameAsync(displayName);
}

Magic link, e-postaya tek kullanımlık bir bağlantı gönderir. Sunucu uçları vardır, SDK yardımcısı henüz yoktur ve oyun içi bir akış olarak belgelenmemiştir.

POST /v1/auth/sign-in/magic-link
content-type: application/json
x-crx-env: <ortam-kimliği>
x-csrf-token: <csrf-belirteci>

{"email":"[email protected]","name":"Ayşe"}

200 (e-posta varlığı sızmaz); token yalnız e-postadadır, 5 dakika geçerlidir ve tek kullanımlıktır. Sınır: IP 5 / 60 sn, adres 5 / 15 dk. Token GET /v1/auth/magic-link/verify?token=<token> ile tüketilir; başarıda 200, giriş zarfı ve oturum çerezleri döner, geçersiz token 403 verir.

Uyarı

verify ucu da x-crx-env başlığı ister. Tarayıcıda e-postadaki bağlantıya doğrudan tıklamak bu başlığı göndermez ve 401 alır. Bir magic link akışı kurmak istiyorsanız token’ı oyun sayfanızın alıp başlıklı bir istekle doğrulaması gerekir; bu akış SDK’larda ve bu belgede kapsanmaz.