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_verifiedfalsedö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.
| Durum | Anlamı |
|---|---|
400 | E-posta biçimi ya da parola politikası ihlali |
409 | Adres bu ortamda kayıtlı (gövde adresi tekrar etmez) |
429 | IP 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 (
403düz metin); hangisi olduğu sızmaz. - Parolası doğru ama banlı hesap
403ve{"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
429alı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.
| Durum | Anlamı |
|---|---|
400 | E-posta, parola ya da ad doğrulaması |
401 | Ortam başlığı ya da oturum yok |
403 | Oturum etkin değil, başka ortama ait ya da CSRF reddi |
409 | Adres bu ortamda başka bir hesapta kayıtlı; işlem geri alınır, misafir oturumu bozulmaz |
422 | Oyuncu artık misafir değil (yinelenen ya da eşzamanlı istek) |
429 | IP 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
POST /v1/auth/forgot-passwordile sıfırlama e-postası istenir. Hesap olsa da olmasa da yanıt aynı200’dür (hesap varlığı sızmaz).- 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 yoldaGETucu yoktur; yani bağlantıya tıklamak bir sayfa göstermez. Oyununuzda sıfırlamayı sunmak için oyuncunun e-postadakitokendeğ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 });
}
| TypeScript | Unity | Uç |
|---|---|---|
signUpEmail | SignUpEmailAsync | sign-up/email |
signInEmail | SignInEmailAsync | sign-in/email |
upgradeGuest | UpgradeGuestAsync | guest/upgrade/email |
changePassword({ currentPassword, newPassword }) | ChangePasswordAsync | change-password (gövdede old_password) |
requestPasswordReset | RequestPasswordResetAsync | forgot-password |
resetPassword | ResetPasswordAsync | reset-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
403yalnızca CSRF katmanı reddettiyse (yanıtta yeni birx-csrf-tokenyoksa) 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
UnknownOutcomehatası 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. upgradeGuestoturum yokken ağ isteği göndermez; sunucunun kesin ret yanıtları (4xx) misafir oturumunu düşürmez.changePasswordbaşarıdalogoutile aynı geçişi uygular (durumsignedOut).
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
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ı
verifyucu dax-crx-envbaşlığı ister. Tarayıcıda e-postadaki bağlantıya doğrudan tıklamak bu başlığı göndermez ve401alı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.