Autoriser les canaux
Tout client disposant de la clé d'application peut s'abonner aux canaux publics. Deux préfixes de nom de canal exigent que votre backend autorise l'abonnement. Vous ne configurez pas les canaux séparément.
Un canal nommé private-… exige que votre backend approuve chaque abonnement. Un canal nommé presence-… fait de même et attache aussi une identité à l'abonné, pour que tous les membres du canal puissent voir qui d'autre est présent. Tout autre nom est public.
Seul votre backend détient le secret d'application. Le client demande à votre serveur de signer un abonnement spécifique, et le nœud Realtime vérifie cette signature avant de l'accepter. Votre serveur décide si l'appelant peut s'abonner sans exposer le secret au client.
Dirigez le client vers votre endpoint
Fournissez au client un authEndpoint sur votre propre backend :
import { BirdRealtime } from "@messagebird/realtime";
const bird = new BirdRealtime({
appKey: "your-app-key",
region: "us1",
authEndpoint: "/bird/auth",
});
const room = bird.subscribe("presence-room-1");import BirdRealtime
let bird = BirdRealtime(options: .init(
appKey: "your-app-key",
region: "us1",
authEndpoint: URL(string: "https://your-backend.example.com/bird/auth")
))
let room = bird.subscribe("presence-room-1")import com.bird.realtime.BirdRealtime
import com.bird.realtime.BirdRealtimeOptions
val bird = BirdRealtime(
BirdRealtimeOptions(
appKey = "your-app-key",
region = "us1",
authEndpoint = "https://your-backend.example.com/bird/auth",
)
)
val room = bird.subscribe("presence-room-1")Le client appelle cet endpoint pour chaque abonnement privé ou de présence, y compris les abonnements restaurés après une reconnexion. L'autorisation s'applique à une seule connexion, car la signature inclut son identifiant de connexion.
Le client navigateur exige un endpoint de même origine par défaut. Définissez allowCrossOriginAuth: true pour utiliser un authEndpoint d'origine différente. Le client navigateur envoie les authHeaders configurés uniquement aux endpoints de même origine.
Ce que votre endpoint reçoit et renvoie
Le client envoie un POST avec JSON :
Exemple de code
{ "connection_id": "26896.319537", "channel_name": "presence-room-1" }Répondez avec la signature :
Exemple de code
{ "auth": "your-app-key:8f9a…" }Pour un canal de présence, renvoyez aussi l'identité du membre sous forme de JSON chaîne, la même chaîne que vous avez signée :
Exemple de code
{
"auth": "your-app-key:8f9a…",
"member_data": "{\"member_id\":\"u_42\",\"member_info\":{\"name\":\"Ada\"}}"
}member_id est l'identité que les autres membres voient et la valeur ciblée par l'opération de déconnexion. member_info est un champ optionnel de données JSON transmis à chaque membre du canal. Il a une limite de 1 Ko, n'incluez donc que des données de profil légères et non sensibles.
Autorisez l'appelant dans cet endpoint à l'aide de son cookie de session ou de son jeton bearer. Renvoyez 403 Forbidden lorsque l'appelant ne doit pas rejoindre le canal. Pour les canaux de présence, attribuez l'identité dans la même réponse.
La chaîne à signer
Concaténez avec des deux-points, puis appliquez HMAC-SHA256 avec le secret d'application et encodez en hexadécimal. Préfixez le résultat avec la clé d'application et un deux-points.
| Type de canal | Chaîne à signer |
|---|---|
| private-… | <connection_id>:<channel_name> |
| private-encrypted-… | <connection_id>:<channel_name> |
| presence-… | <connection_id>:<channel_name>:<member_data> |
Pour les canaux de présence, signez la chaîne member_data exacte que vous renvoyez. Re-sérialiser le même objet peut modifier l'ordre des clés ou l'espacement et invalider la signature.
Un canal chiffré se signe comme un canal privé, et sa réponse d'authentification renvoie en plus la clé de déchiffrement du canal sous la forme shared_secret. Le helper SDK l'ajoute automatiquement ; Canaux chiffrés couvre la dérivation et le comportement du canal.
Chaque SDK serveur SDK fournit un helper authorizeChannel. Il signe avec les identifiants d'application configurés et renvoie le corps de la réponse sans effectuer de requête réseau. Pour les canaux chiffrés, le helper ajoute aussi shared_secret.
app.post("/bird/auth", async (req, res) => {
const { connection_id, channel_name } = req.body;
// Your own authorization decision goes here.
const user = getUserFromSession(req);
if (!user || !mayJoin(user, channel_name)) return res.sendStatus(403);
const memberData = channel_name.startsWith("presence-")
? JSON.stringify({ member_id: user.id, member_info: { name: user.name } })
: undefined;
res.json(
await bird.realtime.authorizeChannel({
connectionId: connection_id,
channelName: channel_name,
memberData,
}),
);
});import json
@app.post("/bird/auth")
def bird_auth():
body = request.get_json()
channel_name = body["channel_name"]
# Your own authorization decision goes here.
user = get_user_from_session()
if user is None or not may_join(user, channel_name):
abort(403)
member_data = None
if channel_name.startswith("presence-"):
member_data = json.dumps({"member_id": user.id, "member_info": {"name": user.name}})
return client.realtime.authorize_channel(
connection_id=body["connection_id"],
channel_name=channel_name,
member_data=member_data,
)func birdAuth(w http.ResponseWriter, r *http.Request) {
var body struct {
ConnectionID string `json:"connection_id"`
ChannelName string `json:"channel_name"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
http.Error(w, "bad request", http.StatusBadRequest)
return
}
// Your own authorization decision goes here.
user, ok := userFromSession(r)
if !ok || !mayJoin(user, body.ChannelName) {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
params := bird.RealtimeChannelAuthorizationParams{
ConnectionID: body.ConnectionID,
ChannelName: body.ChannelName,
}
if strings.HasPrefix(body.ChannelName, "presence-") {
memberData, _ := json.Marshal(map[string]any{
"member_id": user.ID,
"member_info": map[string]string{"name": user.Name},
})
params.MemberData = string(memberData)
}
auth, err := client.Realtime.AuthorizeChannel(params)
if err != nil {
http.Error(w, "authorization failed", http.StatusInternalServerError)
return
}
json.NewEncoder(w).Encode(auth)
}function birdAuth(string $connectionId, string $channelName, User $user): array
{
// Your own authorization decision goes here.
if (!mayJoin($user, $channelName)) {
http_response_code(403);
exit;
}
$memberData = null;
if (str_starts_with($channelName, 'presence-')) {
$memberData = json_encode(['member_id' => $user->id, 'member_info' => ['name' => $user->name]]);
}
return $bird->realtime->authorizeChannel($connectionId, $channelName, $memberData);
}Le contrat de signature est le même dans un langage sans SDK : appliquez HMAC-SHA256 à la chaîne avec le secret d'application, encodez en hexadécimal, et préfixez avec la clé d'application et un deux-points.
Membres et connexions
Un membre est une identité, tandis qu'une connexion est un WebSocket ouvert. Si quelqu'un ouvre votre application dans trois onglets, un seul membre détient trois connexions. member_added se déclenche quand la première connexion s'abonne, et member_removed se déclenche quand la dernière se retire. Les autres connexions modifient le nombre de connexions du canal sans produire d'événements de membre.
Erreurs courantes
Un abonnement refusé arrive sous forme d'erreur client. Vérifiez ces causes courantes :
- Signature invalide. La chaîne que vous avez signée ne correspond pas. Il s'agit presque toujours d'un member_data re-sérialisé, ou d'une signature calculée sur le nom du canal sans son préfixe private- ou presence-.
- Clé invalide. La clé dans auth appartient à une autre application, ou elle a été révoquée. Effectuer une rotation des clés implique de mettre à jour à la fois le appKey du client et le secret avec lequel votre endpoint signe.
- Données de membre manquantes. Un abonnement de présence est arrivé sans member_data. Les canaux de présence ne peuvent pas être rejoints anonymement.
- Un 403 provenant de votre propre endpoint. Votre décision d'autorisation a refusé l'accès, ce qui est le résultat attendu pour un utilisateur qui ne doit pas rejoindre le canal.
Étapes suivantes
- Envoyer votre premier événement temps réel est le guide de bout en bout sur lequel s'appuie ce document.
- Canaux chiffrés s'appuient sur cette signature pour remettre aussi une clé de déchiffrement aux abonnés approuvés.
- Canaux de présence couvre la liste des membres, les événements de membre et la lecture de la présence depuis votre serveur.
- Terminer les connexions d'un membre est l'autre signature que votre backend calcule, et celle qui vous permet de fermer les connexions d'un membre.
- Webhooks et événements couvre les événements realtime.*, y compris l'arrivée et le départ de membres, sur votre propre endpoint.
Ressources associées
Poursuivez avec la documentation, les guides et les exemples sur ce sujet. Les ressources sont en anglais.