Fermer les connexions d'un membre
L'autorisation de canal contrôle les abonnements, mais n'attribue pas d'identité au niveau de la connexion. Sans cette identité, une déconnexion effectuée ailleurs ne ferme pas un socket existant et ne supprime pas ses abonnements aux canaux.
Appelez signin() pour attribuer à la connexion un member_id depuis votre backend. L'opération de déconnexion peut alors fermer toutes les connexions que ce membre détient sur l'application.
Utilisez ce flux après une déconnexion à distance, une révocation de jeton, un bannissement, un changement de mot de passe ou un retrait de siège dans l'espace de travail.
1. Connecter la connexion
Dirigez le client vers un endpoint sur votre propre backend et appelez signin() une seule fois :
import { BirdRealtime } from "@messagebird/realtime";
const bird = new BirdRealtime({
appKey: "your-app-key",
region: "us1",
memberAuthEndpoint: "/bird/auth/member",
});
const member = await bird.signin();
console.log("signed in as", member.member_id);import BirdRealtime
let bird = BirdRealtime(options: .init(
appKey: "your-app-key",
region: "us1",
memberAuthEndpoint: URL(string: "https://your-backend.example.com/bird/auth/member")
))
let member = try await bird.signin()
print("signed in as", member.memberId)import com.bird.realtime.BirdRealtime
import com.bird.realtime.BirdRealtimeOptions
val bird = BirdRealtime(
BirdRealtimeOptions(
appKey = "your-app-key",
region = "us1",
memberAuthEndpoint = "https://your-backend.example.com/bird/auth/member",
)
)
val member = bird.signin() // suspending
println("signed in as ${member.memberId}")L'identité appartient à la connexion. Appelez signin() une seule fois ; le client se reconnecte après chaque reconnexion.
La connexion n'autorise pas les abonnements aux canaux. Les canaux privés et de présence appellent toujours votre endpoint d'autorisation de canal. Une connexion sans identité de membre peut s'abonner à tout canal approuvé par cet endpoint. Voir Autoriser les canaux.
2. Signer l'identité depuis votre backend
Le client envoie l'identifiant de connexion dans une requête POST :
Exemple de code
{ "connection_id": "26896.319537" }Votre endpoint répond avec l'identité sous forme de JSON chaîne, accompagnée d'une signature portant sur cette chaîne exacte :
Exemple de code
{
"auth": "your-app-key:8f9a…",
"member_data": "{\"member_id\":\"u_42\",\"member_info\":{\"name\":\"Ada\"}}"
}La chaîne à signer est <connection_id>::member::<member_data>, avec deux deux-points de chaque côté de member. Appliquez HMAC-SHA256 avec le secret de l'application, encodez en hexadécimal et préfixez la clé de l'application :
import { createHmac } from "node:crypto";
app.post("/bird/auth/member", (req, res) => {
const { connection_id } = req.body;
// Your own decision: who is this caller, and may they connect at all?
const user = getUserFromSession(req);
if (!user) return res.sendStatus(403);
const memberData = JSON.stringify({
member_id: user.id,
member_info: { name: user.name },
});
const sig = createHmac("sha256", process.env.BIRD_REALTIME_SECRET)
.update(`${connection_id}::member::${memberData}`)
.digest("hex");
res.json({ auth: `${process.env.BIRD_REALTIME_KEY}:${sig}`, member_data: memberData });
});import hmac, hashlib, json, os
def sign_in(connection_id: str, user) -> dict:
key = os.environ["BIRD_REALTIME_KEY"]
secret = os.environ["BIRD_REALTIME_SECRET"].encode()
member_data = json.dumps({"member_id": user.id, "member_info": {"name": user.name}})
to_sign = f"{connection_id}::member::{member_data}"
sig = hmac.new(secret, to_sign.encode(), hashlib.sha256).hexdigest()
return {"auth": f"{key}:{sig}", "member_data": member_data}func signIn(connectionID string, user User) (map[string]string, error) {
key := os.Getenv("BIRD_REALTIME_KEY")
secret := []byte(os.Getenv("BIRD_REALTIME_SECRET"))
memberData, err := json.Marshal(map[string]any{
"member_id": user.ID,
"member_info": map[string]string{"name": user.Name},
})
if err != nil {
return nil, err
}
mac := hmac.New(sha256.New, secret)
mac.Write([]byte(connectionID + "::member::" + string(memberData)))
return map[string]string{
"auth": key + ":" + hex.EncodeToString(mac.Sum(nil)),
"member_data": string(memberData),
}, nil
}function signIn(string $connectionId, User $user): array
{
$key = getenv('BIRD_REALTIME_KEY');
$secret = getenv('BIRD_REALTIME_SECRET');
$memberData = json_encode(['member_id' => $user->id, 'member_info' => ['name' => $user->name]]);
$sig = hash_hmac('sha256', "{$connectionId}::member::{$memberData}", $secret);
return ['auth' => "{$key}:{$sig}", 'member_data' => $memberData];
}Signez la chaîne member_data exacte que vous retournez. Re-sérialiser l'objet peut modifier ses octets et invalider la signature.
member_id est la valeur ciblée par l'opération de déconnexion. Elle accepte jusqu'à 128 caractères sûrs pour les URL, y compris + : @ . _ -, mais pas / ? # % ni les espaces. Si votre identifiant contient des caractères non pris en charge, convertissez-le en une valeur sûre et stable avant de signer. Le serveur edge rejette un identifiant de membre invalide, laissant la connexion sans identité que l'opération de déconnexion puisse cibler.
member_info est facultatif. Pour la connexion d'un membre, il est renvoyé à ce client plutôt que diffusé sur un canal de présence.
L'identité peut aussi contenir un tableau watchlist d'identifiants de membres. Sur les applications avec watchlist_events activé, la connexion est alors informée lorsque ces membres se connectent ou se déconnectent ; voir Événements de liste de suivi.
La chaîne signée ici est volontairement différente de celle qu'un abonnement de présence signe, de sorte qu'une autorisation de présence ne puisse jamais être rejouée pour revendiquer une identité, même si les deux charges utiles s'appellent member_data.
3. Déconnecter le membre
await bird.realtime.members.disconnect("rap_01krdgeqcxet5s7t44vh8rt9mg", "u_42");client.realtime.members.disconnect("rap_01krdgeqcxet5s7t44vh8rt9mg", "u_42")if err := client.Realtime.Members.Disconnect(context.Background(), "rap_01krdgeqcxet5s7t44vh8rt9mg", "u_42"); err != nil {
log.Fatal(err)
}$bird->realtime->members->disconnect('rap_01krdgeqcxet5s7t44vh8rt9mg', 'u_42');curl -X POST \
https://us1.platform.bird.com/v1/realtime/apps/rap_01krdgeqcxet5s7t44vh8rt9mg/members/u_42/disconnect \
-H "Authorization: Bearer $BIRD_API_KEY" \
-H "X-Realtime-Key: $BIRD_REALTIME_KEY" \
-H "X-Realtime-Secret: $BIRD_REALTIME_SECRET"L'opération ferme toutes les connexions authentifiées de ce membre sur l'application, y compris les autres onglets et appareils. Elle ne ferme pas les connexions anonymes ni les connexions attribuées à un autre membre.
Ce que le client observe
La connexion se ferme avec le code 4009 et ne se reconnecte pas automatiquement :
bird.connection.bind("error", (e) => {
if (e.code === 4009) showSignedOutScreen();
});bird.onError { error in
if error.code == 4009 { showSignedOutScreen() }
}bird.onError { error ->
if (error.code == 4009) showSignedOutScreen()
}Affichez un état déconnecté lorsque l'authentification a pris fin. L'appel à bird.connect() démarre une nouvelle connexion qui s'authentifie via votre endpoint ; ne reconnectez donc qu'après un changement de l'état d'autorisation du membre.
Un échec de connexion ne ferme pas le socket. Le client signale l'échec séparément et laisse la connexion sans identité de membre. Après une reconnexion, le client le signale via signin_error car la promesse signin() d'origine a déjà été résolue.
bird.connection.bind("signin_error", (e) => {
console.warn("connection has no identity:", e.message);
});bird.onSigninError { error in
print("connection has no identity:", error.message)
}bird.onSigninError { error ->
println("connection has no identity: ${error.message}")
}La connexion peut toujours recevoir des événements des canaux autorisés, mais les opérations d'événements de membre et de déconnexion ne peuvent pas la cibler. Dans le client navigateur, bird.signedInMember vaut null dans cet état.
Empêcher la reconnexion
L'opération de déconnexion ferme les connexions en cours sans créer de blocage persistant. Le même client peut se reconnecter.
Révoquez la session ou enregistrez le bannissement avant de déconnecter le membre. Votre endpoint d'autorisation de membre peut alors renvoyer 403 Forbidden si le client se reconnecte.
Étapes suivantes
- Autoriser les canaux couvre l'autre signature que votre backend calcule, pour les abonnements privés et de présence.
- Déconnecter un membre est la référence API complète pour la requête.
- Envoyer des événements à un membre est l'autre opération adressée à un membre.
- Canaux de présence explique pourquoi un même membre peut détenir plusieurs connexions.
Ressources associées
Poursuivez avec la documentation, les guides et les exemples sur ce sujet. Les ressources sont en anglais.
Explorer la fonctionnalitéRealtimeSuivre le parcours d'apprentissageBuild your first integrationGuide d'implémentationSend your first realtime event
Essayez la pratique et obtenez un guide d'implémentation