Granularna zgoda OAuth dla gier: implementacja uprawnień na poziomie scope'ów w backendzie
W skrócie
Poznaj task-based OAuth consent dla gier: wdróż granularne uprawnienia scope-level w backendzie, zwiększ zaufanie graczy i konwersję logowania.
Każdy indie deweloper zna ten moment, gdy gracz zawaha się przed ekranem uprawnień. Twoja gra prosi o dostęp do listy znajomych, adresu e-mail i historii zakupów — a gracz klika „Odmów”. To wahanie nie jest irracjonalne; to racjonalna reakcja na wybór „wszystko albo nic”, który odbiera się jako naruszenie prywatności. To tarcie bezpośrednio wpływa na współczynnik konwersji i zaufanie graczy.
Ostatnia aktualizacja systemu OAuth w Cloudflare wprowadza potężne rozwiązanie: zadaniową, granularną zgodę (task-based consent). Zamiast zmuszać graczy do zatwierdzania każdego uprawnienia, którego Twoja gra może potrzebować, możesz teraz oznaczyć konkretne scope'y jako opcjonalne. Dzięki temu gracze mogą przyznać tylko te uprawnienia, na które są gotowi w kontekście bieżącego zadania — to zmiana paradygmatu w przepływach autoryzacji w grach.
Problem uprawnień „wszystko albo nic” w grach
Tradycyjna zgoda OAuth jest binarna. Gdy Twoja gra żąda scope'ów takich jak profile.read, friends.list i inventory.write, gracz widzi pojedynczy przycisk „Zatwierdź”. Jeśli nie chcą przyznać dostępu inventory.write narzędziu trzeciej strony, ich jedyną opcją jest odrzucenie całego żądania.
To tworzy kilka konkretnych problemów dla deweloperów gier:
- Wysoki wskaźnik porzuceń: Gracze świadomi bezpieczeństwa po prostu opuszczą Twoją grę, zamiast przyznawać szeroki dostęp.
- Niedobór uprawnień: Aby uniknąć porzuceń, deweloperzy często żądają mniej scope'ów, niż faktycznie potrzebują, co ogranicza funkcjonalność.
- Erozja zaufania: Gracze zaczynają kojarzyć proces logowania w Twojej grze z utratą kontroli, co szkodzi długoterminowej retencji.
Sedno problemu polega na tym, że gracz autoryzujący aplikację towarzyszącą do podstawowego śledzenia statystyk nie powinien być zmuszany do przyznania jej możliwości modyfikowania loadoutu czy wydawania waluty w grze.
Jak działa zadaniowa zgoda OAuth (task-based consent)
Nowy model pozwala deweloperom skonfigurować klienta OAuth z dwoma typami scope'ów: wymaganymi i opcjonalnymi. Gdy gracz rozpoczyna przepływ autoryzacji, widzi pełną listę żądanych uprawnień, ale może odznaczyć te oznaczone jako opcjonalne.
Kluczowym szczegółem technicznym jest to, że ta ocena odbywa się dla każdego żądania autoryzacji osobno, a nie względem całego skonfigurowanego zestawu scope'ów klienta. To kluczowe dla gier, gdzie różne funkcje wymagają różnych uprawnień.
Rozważmy backend gry z następującymi scope'ami:
player.profile.read(wymagany do podstawowego logowania)player.inventory.read(opcjonalny, dla aplikacji towarzyszącej)player.inventory.write(opcjonalny, dla menedżera loadoutu)match.history.read(opcjonalny, do śledzenia statystyk)
Gracz korzystający z prostego narzędzia do śledzenia statystyk zażądałby tylko player.profile.read i match.history.read. Ekran zgody pokazałby oba, ale ponieważ match.history.read jest opcjonalny, gracz mógłby go odznaczyć i kontynuować z ograniczonym tokenem. Scope'y inventory w ogóle by się nie pojawiły, ponieważ nie zostały zażądane w tym konkretnym przepływie.
Implementacja granularnej zgody w backendzie Twojej gry
Przejdźmy przez praktyczną implementację. Użyjemy generycznego przepływu OAuth 2.0, który możesz zaadaptować do swojego backendu, niezależnie od tego, czy to rozwiązanie customowe, czy usługa taka jak horizOn.
Krok 1: Skonfiguruj klienta OAuth z opcjonalnymi scope'ami
Rejestrując swoją aplikację OAuth w serwerze autoryzacji (takim jak Cloudflare lub własnym), definiujesz, które scope'y są wymagane, a które opcjonalne. Oto przykładowa konfiguracja:
{
"client_id": "your_game_client_id",
"scopes": {
"required": ["player.profile.read"],
"optional": [
"player.inventory.read",
"player.inventory.write",
"match.history.read",
"match.history.write"
]
},
"redirect_uris": ["https://yourgame.com/callback"]
}
To informuje serwer autoryzacji: „Gdy ten klient żąda uprawnień, player.profile.read musi być zawsze przyznany, jeśli został zażądany, ale pozostałe zależą od użytkownika”.
Krok 2: Obsłuż żądanie i odpowiedź autoryzacji
Klient Twojej gry inicjuje przepływ OAuth, żądając scope'ów potrzebnych do bieżącego zadania. Krytyczny moment następuje po tym, jak gracz zatwierdzi lub zmodyfikuje żądanie. Musisz sprawdzić przyznane scope'y w odpowiedzi, a nie zakładać, że otrzymałeś wszystko, o co prosiłeś.
Oto uproszczony przykład w pseudokodzie do obsługi callbacku:
// After the player is redirected back to your game with an authorization code
async function handleOAuthCallback(authorizationCode) {
// Exchange the code for tokens
const tokenResponse = await fetch('/oauth/token', {
method: 'POST',
body: JSON.stringify({
code: authorizationCode,
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
redirect_uri: REDIRECT_URI,
grant_type: 'authorization_code'
})
});
const tokens = await tokenResponse.json();
// CRITICAL: Check the granted scopes
const grantedScopes = tokens.scope.split(' ');
// Now, adapt your game's functionality based on what was actually granted
if (grantedScopes.includes('player.inventory.read')) {
enableInventoryViewer();
} else {
disableInventoryViewer();
showLimitedFunctionalityMessage();
}
if (grantedScopes.includes('match.history.read')) {
enableStatTracking();
} else {
disableStatTracking();
}
// Store the token with its specific scope set
storeUserSession({
accessToken: tokens.access_token,
scopes: grantedScopes,
// ... other token data
});
}
Krok 3: Zaprojektuj UI gry pod częściowe przyznanie uprawnień
Doświadczenie użytkownika nie kończy się na ekranie OAuth. Twoja gra musi elegancko obsłużyć token z mniejszą liczbą uprawnień, niż idealnie byś chciał.
Najlepsze praktyki UI/UX:
- Bądź transparentny: Jeśli funkcja jest wyłączona z powodu braku uprawnień, powiedz graczowi dlaczego i jak może przyznać dostęp później.
- Zapewnij ścieżkę rozszerzenia uprawnień: Dodaj przycisk „Przyznaj więcej uprawnień” w menu ustawień, który ponownie inicjuje przepływ OAuth z opcjonalnymi scope'ami.
- Degraduj z gracją: Aplikacja do śledzenia statystyk bez
match.history.writepowinna nadal pokazywać statystyki, tylko bez możliwości zapisywania niestandardowych raportów.
5 najlepszych praktyk dla zgody OAuth w grach
Żądaj minimalnego zestawu scope'ów: Dla każdej funkcji określ absolutne minimum wymaganych scope'ów. Wszystko inne oznacz jako opcjonalne. Przeglądarka leaderboardów potrzebuje tylko
match.history.read, a niematch.history.write.Kontekstualizuj żądania uprawnień: Nie żądaj wszystkich możliwych scope'ów przy logowaniu. Żądaj
inventory.writedopiero, gdy gracz faktycznie spróbuje użyć edytora loadoutu. To buduje zaufanie poprzez kontekst.Przechowuj zestawy scope'ów dla każdej sesji: Gracz może przyznać różne scope'y różnym aplikacjom towarzyszącym. Twój backend musi powiązać każdy token dostępu z konkretnymi przyznanymi scope'ami i egzekwować je na poziomie API.
Audytuj definicje scope'ów: Regularnie przeglądaj listę scope'ów. Czy są scope'y zdefiniowane na wczesnym etapie rozwoju, które nie są już używane? Wycofaj je. Mniejsza, czystsza lista scope'ów jest mniej onieśmielająca.
Implementuj walidację scope'ów na każdym endpointcie: Twoje API musi sprawdzać, czy przychodzący token dostępu ma wymagany scope dla żądanego zasobu. To nie podlega negocjacjom w kwestii bezpieczeństwa. Token z tylko
player.profile.readmusi być zablokowany przed wywołaniem/api/inventory.
Zbudowanie całego tego przepływu — konfiguracji klienta, dynamicznych ekranów zgody, obsługi tokenów świadomej scope'ów i walidacji backendu — to znaczące przedsięwzięcie. Wymaga głębokiej integracji z serwerem autoryzacji i starannego zarządzania stanem. W tym miejscu usługa backendowa taka jak horizOn może zaoszczędzić tygodnie pracy developerskiej. System autoryzacji horizOn został zaprojektowany z myślą o tych nowoczesnych wzorcach granularnej zgody, oferując prekonfigurowane endpointy i SDK, które obsługują walidację scope'ów i częściowe przyznawanie uprawnień od ręki.
Implikacje bezpieczeństwa: dlaczego to ważne dla backendów gier
Granularna zgoda to nie tylko ulepszenie UX; to wzorzec architektury bezpieczeństwa. Ograniczając promień rażenia skompromitowanego tokena, chronisz swoich graczy i ekonomię gry. Jeśli złośliwa aplikacja trzeciej strony zdołała nakłonić gracza do przyznania tylko match.history.read, nie może dotknąć jego ekwipunku ani waluty. Ta zasada najmniejszych uprawnień (least privilege) jest fundamentalna dla bezpiecznego projektowania systemów. Aby głębiej zgłębić temat architektury backendów odpornych na kompromitacje, zobacz naszą analizę wycieku danych Star Citizen.
Podsumowanie: budowanie zaufania poprzez kontrolę
Przejście od modelu „wszystko albo nic” do zadaniowej zgody OAuth to korzyść zarówno dla graczy, jak i deweloperów. Gracze zyskują kontrolę, której oczekują, co przekłada się na wyższe wskaźniki autoryzacji i zaufanie. Deweloperzy otrzymują dokładniejsze zestawy uprawnień, umożliwiające bogatsze integracje bez obawy o odstraszenie użytkowników.
Zacznij od audytu swojej obecnej implementacji OAuth. Określ, które scope'y są naprawdę niezbędne dla podstawowej funkcjonalności, a które można oznaczyć jako opcjonalne. Zaimplementuj logikę serwerową do obsługi częściowych przyznań i zaktualizuj UI gry, aby jasno komunikować graczom, co daje każde uprawnienie.
Dając graczom wybór, nie ograniczasz swojej gry — budujesz fundament zaufania, który wspiera długoterminowe zaangażowanie i zdrowszy ekosystem dla narzędzi zewnętrznych i aplikacji towarzyszących.
Źródło: Od modelu „wszystko albo nic” do zadaniowej zgody OAuth