Cette page n’est pas encore traduite : la version anglaise est affichée.
Auth & Players
La connexion est une étape que vous pouvez surcharger, pas une boîte noire. Fournisseurs, sessions, liaison d’identités, bannissements. Chaque point du parcours — avant et après la connexion, avant et après une liaison, avant et après une fusion, à chaque changement de statut — est un point d’extension déclaré, d’un type déclaré : une barrière, qui peut refuser l’étape, ou un observateur, qui ne le peut pas.
Quand l’utiliser
- Les joueurs doivent se connecter (appareil, e-mail, Apple, Google, Steam ou méthode personnalisée), et la création du compte à la première connexion (sign-in) est une simple option, pas un second parcours.
- Un compte invité doit pouvoir évoluer plus tard :
Linkajoute Steam sans perdre la progression, et une fusion (merge) réunit deux comptes en un seul joueur. - Une règle doit s’exécuter là où personne ne peut la contourner : une barrière (gate) par région avant la connexion, un pack de départ après la connexion qui a créé le joueur.
- La modération doit agir immédiatement : révoquer les sessions, suspendre, bannir un appareil, avec un événement
bannedque reçoivent tous les systèmes actifs. - Le contexte déclaré (région, plateforme, build) doit parvenir à chaque hook suivant, sans que chacun doive relire le joueur pour l’obtenir.
- Il n’existe rien de plus léger pour le remplacer. Tous les autres modules identifient leur appelant grâce à celui-ci, et
authne peut pas être désactivé tant que l’un d’eux a besoin d’un acteur joueur : le configurateur de modules refuse et nomme les modules qui en dépendent.
Qui fait quoi
| Acteur | Ce qu’il fait sur cette page |
|---|---|
player | se connecte, lie ou délie des identités, renouvelle ses identifiants (credential), se déconnecte |
moderator | révoque des sessions ; bannit, suspend ou réintègre des joueurs |
backend-service | filtre la connexion par région ; crée les premières lignes d’un nouveau joueur ; consulte et révoque des sessions |
En bref
SignIn par fournisseur, la création à la première connexion en option ; Link ajoute Steam// client — one call per provider; create-on-first-sign-in is a flag
var session = await PlayServ.Auth.SignIn(Provider.Device, create: true);
await PlayServ.Auth.Link(Provider.Steam); // one player, many identities// client — one call per provider; create-on-first-sign-in is a flag
const session = await PlayServ.auth.signIn(Provider.Device, { create: true });
await PlayServ.auth.link(Provider.Steam); // one player, many identities# client — one call per provider; create-on-first-sign-in is a flag
session = await playserv.auth.sign_in(Provider.DEVICE, create=True)
await playserv.auth.link(Provider.STEAM) # one player, many identitiesLa déclaration par attributs en Go n’est pas encore tranchée (O-1). Les exemples arriveront quand la forme d’écriture sera choisie.
// client — one call per provider; create-on-first-sign-in is a flag
Client->Auth->SignInWithProvider(FPSProviderId::Device, Credential,
TPSOnResult<FPSSession>::CreateWeakLambda(this, [this](const TPSResult<FPSSession>& Result)
{
if (!Result.HasValue()) { return; }
// one player, many identities — add Steam to the same account
Client->Auth->Providers->Link(FPSProviderId::Steam, SteamCredential);
}));
// co_await support ships later: a built-in SDK coroutine wrapper that respects Unreal's GC and threading.// client — one call per provider; create-on-first-sign-in is a flag
var session = await PlayServ.Auth.SignIn(Provider.Device, create: true);
await PlayServ.Auth.Link(Provider.Steam); // one player, many identitiesChaque point se personnalise là où il est déclaré ; les formes que peut prendre un handler sont réunies dans Extensibility :
[Before(Auth.SignIn)] // a gate: it may refuse, and it is fail-closed
public static Verdict GateRegion(SignInAttempt a) =>
a.Region == "sanctioned"
? Hook.Reject(Problem.Forbidden, "region not served")
: Hook.Continue(a);
[After(Auth.SignIn, created: true)] // an observer: it watches, it cannot refuse
public static async Task GrantStarterPack(Player player)
{
await player.Inventory.Grant("chest.gold", count: 1);
}// a gate: it may refuse, and it is fail-closed
export const gateRegion = before(Auth.signIn, (a: SignInAttempt) =>
a.region === 'sanctioned'
? Hook.reject(Problem.forbidden, 'region not served')
: Hook.continue(a));
// an observer: it watches, it cannot refuse
export const grantStarterPack = after(Auth.signIn, { created: true },
async (player: Player) => {
await player.inventory.grant('chest.gold', { count: 1 });
});@before(auth.sign_in) # a gate: it may refuse, and it is fail-closed
def gate_region(a: SignInAttempt) -> Verdict:
if a.region == "sanctioned":
return Hook.reject(Problem.FORBIDDEN, "region not served")
return Hook.continue_(a)
@after(auth.sign_in, created=True) # an observer: it watches, it cannot refuse
async def grant_starter_pack(player: Player):
await player.inventory.grant("chest.gold", count=1)La déclaration par attributs en Go n’est pas encore tranchée (O-1). Les exemples arriveront quand la forme d’écriture sera choisie.
Une surcharge comme un hook sont des fonctions cloud : elles s’exécutent sur la plateforme, pas dans le moteur. Écrivez-les en C#, TypeScript ou Python — Unreal s’abonne aux événements qu’elles produisent. Des fonctions écrites côté moteur sont prévues : graphes Blueprint et C++ (traduit vers un langage de script validé par la plateforme). Les unes comme les autres seront analysées et publiées comme n’importe quelle déclaration ; l’exécution reste sur la plateforme.
Une surcharge comme un hook sont des fonctions cloud : elles s’exécutent sur la plateforme, pas dans le moteur. Écrivez-les en C#, TypeScript ou Python — Unity s’abonne aux événements qu’elles produisent.
La forme déclarée est exactement ce qu’affiche le panneau : chaque point montre ses handlers, leur type et l’ordre résolu. Le type détermine ce qui se passe quand un handler échoue :
| Type | Quand le handler lui-même échoue | En cas de refus |
|---|---|---|
| une barrière | l’étape est refusée : un contrôle de région injoignable ne vaut pas un contrôle de région réussi | un code du catalogue de la plateforme, accompagné d’un motif lisible. L’appelant se fonde sur le code ; le texte du motif peut changer et être traduit |
| un observateur | l’étape reste acquise : un pack de départ qui n’est pas arrivé coûte un coffre, pas la connexion | il ne peut pas refuser |
Un hook ne décide jamais qui s’est connecté
Une barrière répond par oui ou par non à propos d’une identité que la plateforme a déjà établie. Elle ne désigne pas le joueur, n’attribue pas d’identité et ne remplace pas la confirmation du fournisseur (provider).
Le modèle
Un joueur porte une identité ; ce n’est pas une ligne de votre schéma, et son identifiant est stable et jamais réutilisé — y compris lors d’une fusion : l’id d’un joueur fusionné continue de se résoudre au lieu de devenir une référence pendante. Une liaison (link) est un triplet : fournisseur · sujet externe · joueur.
| Toujours | Ce que c’est |
|---|---|
fournisseur + sujet | est unique, et cette unicité est une source de conflit, pas une interdiction : quand « ce compte est déjà pris », la réponse consiste à choisir une fusion |
au plus une liaison par fournisseur et par joueur | un second compte du même fournisseur est un conflit |
un sujet externe | n’est jamais l’identifiant d’un joueur : il appartient au fournisseur, et l’utiliser comme le nôtre lierait nos ids aux siens |
type d'identité et statut d'accès | sont deux axes distincts : anonymous contre registered en est un ; active / suspended / banned en est un autre, si bien que « anonyme banni » et « enregistré suspendu » s’expriment l’un comme l’autre |
une session et un identifiant | sont deux choses différentes : la session est l’enregistrement ; l’identifiant est ce que vous présentez. Révoquer une session invalide tous ses identifiants et ferme ses abonnements ouverts |
plusieurs sessions simultanées | chacune se révoque indépendamment |
les claims d'un identifiant | sont du contexte déclaré — région, langue — et rien que du contexte. Une claim ne confère jamais d’autorité |
une empreinte d'appareil | n’est pas une identité : ce n’est jamais un motif d’admission, seulement un motif de refus, et elle est stockée et comparée sous une forme irréversible |
Les trois machines à états.
| Machine | États |
|---|---|
| le type d’identité | anonymous → registered, et la transition est à sens unique |
| le statut d’accès | active ⇄ suspended, et active → banned → active pour une levée de bannissement |
| le joueur | alive → merged, où merged est terminal : un joueur fusionné ne se reconnecte plus |
Ce que vous déclarez.
| Déclaration | Ce que c’est |
|---|---|
politique de connexion | si la connexion anonyme est autorisée, et les autres règles qui encadrent la connexion. Elle se déclare comme un attribut sur le point de montage du module — ni dans un fichier de configuration à côté du code, ni construite au runtime |
rôle par défaut | l’ensemble de rôles que reçoit un nouveau joueur à sa première connexion. Ce défaut n’a pas lui-même de valeur par défaut : si vous ne déclarez rien, les nouveaux joueurs arrivent sans aucun rôle, et c’est une déclaration légitime, pas un oubli |
politique de sessions | ce qui se passe quand le plafond de sessions simultanées est atteint : évincer la plus ancienne avec un événement, ou refuser la nouvelle. Pas de valeur par défaut |
politique de suppression | comment la suppression d’un joueur se répercute sur les données qui le référencent |
Où se configure un fournisseur. Dans le plan opérateur, pas dans le code : les identifiants d’un store n’ont rien à faire dans un dépôt. Ce qui est déclaré arrive dans la console d’administration en lecture seule.
Ce qu’apporte l’attribution d’un rôle. Les rôles ne sont pas l’affaire du seul opérateur : l’interface propose l’attribution et le retrait d’un rôle pour un joueur, si bien qu’un jeu peut, depuis son propre code, promouvoir un officier de guilde ou confier ses pouvoirs à l’organisateur d’un tournoi.
| Toujours | Ce que c’est |
|---|---|
ce n'est pas une auto-promotion | l’attribution exige la permission atomique déclarée pour cela, et un acteur qui ne la détient pas reçoit un simple forbidden, pas une opération qui échoue en silence |
l'attribution est idempotente | attribuer un rôle que le joueur détient déjà est un succès, pas un conflit : l’état, c’est l’ensemble des rôles, pas l’historique des appels. Contrairement à la connexion, cette opération n’a donc pas besoin de clé d’idempotence |
un changement de rôle n'est pas instantané | il prend effet sans que l’identifiant soit réémis, et devient observable au plus tard à l’expiration du délai d’obsolescence déclaré pour le cache des droits. Un code qui attribue un rôle puis le vérifie aussitôt sur un client connecté doit donc tenir compte de ce délai |
La composition des rôles et ce qu’ils débloquent sont décrits dans Access & Roles.
Erreurs
- Sans identifiant, ou avec un identifiant expiré, la réponse est not authenticated, et un renouvellement règle le problème. Un identifiant révoqué reçoit la même réponse, mais là, le renouvellement n’y peut rien : seule une nouvelle connexion fonctionne.
- Un identifiant déjà renouvelé et présenté une seconde fois est un conflit : c’est ce qui rend la rotation détectable au lieu de la tolérer en silence.
- Un joueur banni ou suspendu, ainsi qu’une empreinte bannie, reçoivent forbidden, et il est inutile de réessayer.
- Une paire fournisseur+sujet déjà prise est un conflit, qu’on peut réessayer après avoir choisi une fusion ; un second compte du même fournisseur est un conflit qu’aucune nouvelle tentative ne changera.
- Délier la dernière méthode de connexion est un refus de validation : plus personne ne pourrait accéder au compte.
- Fusionner un joueur déjà fusionné est un conflit :
mergedest terminal. - Un fournisseur indisponible répond unavailable, et il vaut la peine de réessayer avec un délai croissant (backoff) ; un fournisseur qui rejette l’identifiant répond not authenticated, ce qui justifie une seule nouvelle tentative, pas une boucle.
- Un dépassement du nombre de tentatives de connexion reçoit une réponse de la catégorie limitation de débit (rate limit), avec un délai.
Limites
Les valeurs chiffrées arriveront avec le chapitre sur les limites de la plateforme ; ce qui se passe à chaque plafond est déjà fixé.
- Sessions simultanées par joueur : selon la politique déclarée, éviction de la plus ancienne avec un événement, ou refus de la nouvelle. Il n’y a pas de valeur par défaut.
- Tentatives de connexion par période, et tentatives de liaison d’une paire déjà prise : une limitation de débit avec un délai, et le compteur de tentatives reste dans l’historique.
- Liaisons par joueur : la liaison d’un fournisseur supplémentaire est refusée comme un conflit.
- Durée de vie d’un identifiant : not authenticated, qu’un renouvellement résout. Durée de vie d’un identifiant de renouvellement : seule une nouvelle connexion.
- Rétention d’un joueur anonyme sans aucune connexion : suppression selon la politique déclarée, avec un événement. La politique se déclare explicitement ; il n’y a pas de valeur par défaut.
- Entrées de la liste des empreintes bannies : un ajout est refusé, et les anciennes entrées ne sont jamais évincées en silence.