Terminare le connessioni di un membro
L'autorizzazione del canale controlla le sottoscrizioni ma non assegna un'identità a livello di connessione. Senza quell'identità, effettuare il sign-out altrove non chiude un socket esistente né rimuove le sue sottoscrizioni ai canali.
Chiama signin() per assegnare alla connessione un member_id dal tuo backend. L'operazione di disconnessione può quindi chiudere tutte le connessioni che quel membro detiene sull'app.
Usa questo flusso dopo un sign-out remoto, una revoca di token, un ban, un cambio di password o la rimozione di un posto nello spazio di lavoro.
1. Effettua il sign-in della connessione
Indirizza il client a un endpoint sul tuo backend e chiama signin() una sola volta:
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à appartiene alla connessione. Chiama signin() una sola volta: il client effettua di nuovo il sign-in dopo ogni riconnessione.
Il sign-in non autorizza le sottoscrizioni ai canali. I canali privati e di presenza continuano a chiamare il tuo endpoint di autorizzazione del canale. Una connessione senza identità membro può sottoscriversi a qualsiasi canale approvato da quell'endpoint. Vedi Autorizzazione dei canali.
2. Firma l'identità dal tuo backend
Il client invia l'ID di connessione in una richiesta POST:
Esempio di codice
{ "connection_id": "26896.319537" }Il tuo endpoint risponde con l'identità come JSON stringa, più una firma su quella stringa esatta:
Esempio di codice
{
"auth": "your-app-key:8f9a…",
"member_data": "{\"member_id\":\"u_42\",\"member_info\":{\"name\":\"Ada\"}}"
}La stringa da firmare è <connection_id>::member::<member_data>, con due due punti su ciascun lato di member. Applica HMAC-SHA256 con l'app secret, codifica in esadecimale e aggiungi come prefisso l'app key:
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];
}Firma la stringa member_data esatta che restituisci. Riserializzare l'oggetto può modificarne i byte e invalidare la firma.
member_id è il valore preso di mira dall'operazione di disconnessione. Accetta fino a 128 caratteri URL-safe, incluso + : @ . _ -, ma non / ? # % né spazi bianchi. Se il tuo identificatore contiene caratteri non supportati, mappalo su un valore sicuro e stabile prima di firmare. L'edge rifiuta un member ID non valido, lasciando la connessione senza un'identità che l'operazione di disconnessione possa prendere di mira.
member_info è opzionale. Per il sign-in della connessione, viene restituito a quel client anziché trasmesso a un canale di presenza.
L'identità può anche includere un array watchlist di member id. Nelle app con watchlist_events abilitato, la connessione viene informata quando quei membri vanno online o offline; vedi Eventi della watchlist.
La stringa firmata qui è volutamente diversa dalla stringa firmata da una sottoscrizione di presenza, così un'autorizzazione di presenza non può mai essere riutilizzata per rivendicare un'identità, anche se entrambi i payload si chiamano member_data.
3. Disconnetti il membro
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'operazione chiude tutte le connessioni con sign-in attivo per quel membro sull'app, incluse altre schede e dispositivi. Non chiude connessioni anonime né connessioni assegnate a un altro membro.
Cosa vede il client
La connessione si chiude con il codice 4009 e non si riconnette automaticamente:
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()
}Mostra uno stato di sign-out quando l'autenticazione è terminata. Chiamare bird.connect() avvia una nuova connessione che effettua il sign-in tramite il tuo endpoint, quindi riconnettiti solo dopo che lo stato di autorizzazione del membro cambia.
Un errore di sign-in non chiude il socket. Il client segnala l'errore separatamente e lascia la connessione senza identità membro. Dopo una riconnessione, il client lo segnala tramite signin_error perché la promise signin() originale è già stata risolta.
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 connessione può ancora ricevere eventi dai canali autorizzati, ma le operazioni di member-event e di disconnessione non possono prenderla di mira. Nel client browser, bird.signedInMember è null in questo stato.
Impedire la riconnessione
L'operazione di disconnessione chiude le connessioni correnti senza creare un blocco persistente. Lo stesso client può connettersi di nuovo.
Revoca la sessione o registra il ban prima di disconnettere il membro. Il tuo endpoint di autorizzazione del membro può quindi restituire 403 Forbidden se il client si riconnette.
Prossimi passi
- Autorizzazione dei canali descrive l'altra firma che il tuo backend calcola, per le sottoscrizioni private e di presenza.
- Disconnettere un membro è il riferimento API completo per la richiesta.
- Inviare eventi a un membro è l'altra operazione indirizzata al membro.
- Canali di presenza spiega perché un membro può avere più connessioni.
Risorse correlate
Prosegui con la documentazione, le guide e gli esempi per questo argomento. Le risorse sono in inglese.
Esplora la funzionalitàRealtimeSegui il percorso di apprendimentoBuild your first integrationGuida all'implementazioneSend your first realtime event
Prova l'esercitazione e ottieni un brief di implementazione